summaryrefslogtreecommitdiffstats
path: root/kit/Delta.hpp
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2022-03-08 15:27:20 +0100
committerMichael Meeks <michael.meeks@collabora.com>2022-05-10 09:35:47 +0100
commitb6445a9692f991fba055e31fde9a637321f937cb (patch)
tree4e2bf994f4268726559a60514bca7f3dbae63b99 /kit/Delta.hpp
parentCompress raw images too directly with zlib. (diff)
downloadonline-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.hpp44
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);