diff options
Diffstat (limited to 'saltoqd/msolimageiohandler.cpp')
-rw-r--r-- | saltoqd/msolimageiohandler.cpp | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/saltoqd/msolimageiohandler.cpp b/saltoqd/msolimageiohandler.cpp index e6a9065..5a18ff6 100644 --- a/saltoqd/msolimageiohandler.cpp +++ b/saltoqd/msolimageiohandler.cpp @@ -21,6 +21,17 @@ static inline QRgb decode_color(uchar p, uchar a = 255) return qRgba(p & 0xC0, (p & 0x30) << 2, (p & 0x0C) << 4, a); } +static inline uchar add_saturate(uchar val, int addend) +{ + int sum = val + addend; + return qMax(0, qMin(sum, 255)); +} + +static inline void add_saturate(uchar* val, int addend) +{ + *val = add_saturate(*val, addend); +} + } MSOLImageIOHandler::MSOLImageIOHandler() : QImageIOHandler() @@ -93,6 +104,7 @@ bool MSOLImageIOHandler::write(const QImage &image) const int line_size = width * pixel_size; QImage img = image.convertToFormat(alpha ? QImage::Format_ARGB32 : QImage::Format_RGB32); + img = ditherForMsol(img); uchar header[header_size] = { 0 }; strcpy(reinterpret_cast<char*>(&header[0]), "MSOL "); @@ -159,7 +171,8 @@ QVariant MSOLImageIOHandler::option(ImageOption option) const void MSOLImageIOHandler::setOption(ImageOption option, const QVariant &value) { - + Q_UNUSED(option); + Q_UNUSED(value); } QByteArray convertImageToMsol(const QImage &img) @@ -186,3 +199,47 @@ QImage convertMsolToImage(const QByteArray &msol) } return img; } + +QImage ditherForMsol(const QImage &src) +{ + Q_ASSERT(src.format() == QImage::Format_ARGB32 || src.format() == QImage::Format_RGB32); + const int width = src.width(), height = src.height(); + const int bytesPerLine = src.bytesPerLine(); + + QImage dst(src); + + // If we are on Big endian, then we must skip the first channel (=alpha). + // In LE, use the first three channels and skip the final one (=alpha). + const bool bigEndian = QSysInfo::ByteOrder == QSysInfo::BigEndian; + uchar *line = dst.bits() + (bigEndian ? 1 : 0); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + for (int chan = 0; chan < 3; chan++) { + const uchar val = line[x * 4 + chan]; + const uchar quant = add_saturate(val, 0x20) & 0xC0; + const int error = val - quant; + + line[x * 4 + chan] = quant; + + if (x + 1 < width) + add_saturate(&line[(x + 1) * 4 + chan], (error * 7) / 16); + + if (y + 1 < height) { + uchar *nextLine = line + bytesPerLine; + + if (x > 0) + add_saturate(&nextLine[(x - 1) * 4 + chan], (error * 3) / 16); + + add_saturate(&nextLine[x * 4 + chan], (error * 5) / 16); + + if (x + 1 < width) + add_saturate(&nextLine[(x + 1) * 4 + chan], (error * 1) / 16); + } + } + } + + line += bytesPerLine; + } + + return dst; +} |