diff options
author | Michael Meeks <michael.meeks@collabora.com> | 2022-03-08 15:27:20 +0100 |
---|---|---|
committer | Michael Meeks <michael.meeks@collabora.com> | 2022-05-10 09:35:47 +0100 |
commit | b6445a9692f991fba055e31fde9a637321f937cb (patch) | |
tree | 4e2bf994f4268726559a60514bca7f3dbae63b99 /kit/Delta.hpp | |
parent | Compress raw images too directly with zlib. (diff) | |
download | online-b6445a9692f991fba055e31fde9a637321f937cb.tar.gz online-b6445a9692f991fba055e31fde9a637321f937cb.zip |
Un-pre-multiply pixels in deltas and BGRA -> RGBA swap.
Change-Id: I31eaf0580cfb9d43df3e85a5f15ae0443b6941f0
Signed-off-by: Michael Meeks <michael.meeks@collabora.com>
Diffstat (limited to 'kit/Delta.hpp')
-rw-r--r-- | kit/Delta.hpp | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/kit/Delta.hpp b/kit/Delta.hpp index 4e72cbd827..74d6a2e9c8 100644 --- a/kit/Delta.hpp +++ b/kit/Delta.hpp @@ -116,6 +116,39 @@ class DeltaGenerator { /// The last several bitmap entries as a cache std::vector<std::shared_ptr<DeltaData>> _deltaEntries; + // Unpremultiplies data and converts native endian ARGB => RGBA bytes + static void + unpremult_copy (unsigned char *dest, const unsigned char *src, unsigned int count) + { + for (unsigned int i = 0; i < count; i += 4) + { + uint32_t pix; + uint8_t alpha; + + std::memcpy (&pix, src + i, sizeof (uint32_t)); + + alpha = (pix & 0xff000000) >> 24; + if (alpha == 255) + { + dest[0] = ((pix & 0xff0000) >> 16); + dest[1] = ((pix & 0x00ff00) >> 8); + dest[2] = ((pix & 0x0000ff) >> 0); + dest[3] = 255; + } + else if (alpha == 0) + dest[0] = dest[1] = dest[2] = dest[3] = 0; + + else + { + dest[0] = (((pix & 0xff0000) >> 16) * 255 + alpha / 2) / alpha; + dest[1] = (((pix & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha; + dest[2] = (((pix & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha; + dest[3] = alpha; + } + dest += 4; + } + } + bool makeDelta( const DeltaData &prev, const DeltaData &cur, @@ -209,7 +242,10 @@ class DeltaGenerator { size_t dest = output.size(); output.resize(dest + diff * 4); - memcpy(&output[dest], &curRow.getPixels()[x], diff * 4); + + unpremult_copy(reinterpret_cast<unsigned char *>(&output[dest]), + (const unsigned char *)(&curRow.getPixels()[x]), + diff * 4); LOG_TRC("different " << diff << "pixels"); x += diff; @@ -411,10 +447,14 @@ class DeltaGenerator { zstr.next_out = compressed; zstr.avail_out = maxCompressed; + unsigned char fixedupLine[width * 4]; + // FIXME: should we RLE in pixels first ? for (int y = 0; y < height; ++y) { - zstr.next_in = (Bytef *)pixmap + ((startY + y) * bufferWidth * 4) + (startX * 4); + unpremult_copy(fixedupLine, (Bytef *)pixmap + ((startY + y) * bufferWidth * 4) + (startX * 4), width * 4); + + zstr.next_in = fixedupLine; zstr.avail_in = width * 4; bool lastRow = (y == height - 1); |