From c5700211d6dfff0ea36e13de8d96eaf100add062 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 29 Dec 2017 14:39:29 +0100 Subject: [PATCH] Adjust `decodeACSuccessive` in src/core/jpg.js to improve the rendering quality of (progressive) JPEG images I've been looking into the remaining point in 8637 about blurry images, to see if we could perhaps improve the rendering quality slightly there. After quite a bit of debugging, it seems that the issue is limited to certain progressive JPEG images. As mentioned previously, I've got no detailed knowledge of the JPEG format, but this patch does seem to improve things quite a bit for the images in question. Squinting at https://searchfox.org/mozilla-central/rev/6c33dde6ca02b389c52e8db3d22494df8b916f33/media/libjpeg/jdphuff.c#492-639, it seems reasonable that we should take the sign of the data into account. Furthermore, looking at the specification in https://www.w3.org/Graphics/JPEG/itu-t81.pdf#page=118, the "F.2.4.3 Decoding the binary decision sequence for non-zero DC differences and AC coefficients" section even contains a description of this (even though I cannot claim to really understand the details). --- src/core/jpg.js | 17 +++++++++-------- test/pdfs/.gitignore | 1 + test/pdfs/decodeACSuccessive.pdf | Bin 0 -> 2867 bytes test/test_manifest.json | 8 ++++++++ 4 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 test/pdfs/decodeACSuccessive.pdf diff --git a/src/core/jpg.js b/src/core/jpg.js index d2cc23fef..d7faa25ab 100644 --- a/src/core/jpg.js +++ b/src/core/jpg.js @@ -235,7 +235,8 @@ var JpegImage = (function JpegImageClosure() { var s; var rs; while (k <= e) { - var z = dctZigZag[k]; + let offsetZ = offset + dctZigZag[k]; + let sign = component.blockData[offsetZ] < 0 ? -1 : 1; switch (successiveACState) { case 0: // initial state rs = decodeHuffman(component.huffmanTableAC); @@ -259,8 +260,8 @@ var JpegImage = (function JpegImageClosure() { continue; case 1: // skipping r zero items case 2: - if (component.blockData[offset + z]) { - component.blockData[offset + z] += (readBit() << successive); + if (component.blockData[offsetZ]) { + component.blockData[offsetZ] += sign * (readBit() << successive); } else { r--; if (r === 0) { @@ -269,17 +270,17 @@ var JpegImage = (function JpegImageClosure() { } break; case 3: // set value for a zero item - if (component.blockData[offset + z]) { - component.blockData[offset + z] += (readBit() << successive); + if (component.blockData[offsetZ]) { + component.blockData[offsetZ] += sign * (readBit() << successive); } else { - component.blockData[offset + z] = + component.blockData[offsetZ] = successiveACNextValue << successive; successiveACState = 0; } break; case 4: // eob - if (component.blockData[offset + z]) { - component.blockData[offset + z] += (readBit() << successive); + if (component.blockData[offsetZ]) { + component.blockData[offsetZ] += sign * (readBit() << successive); } break; } diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index d7c1980a1..d74dbd5f8 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -67,6 +67,7 @@ !issue9105_reduced.pdf !issue9291.pdf !bad-PageLabels.pdf +!decodeACSuccessive.pdf !filled-background.pdf !ArabicCIDTrueType.pdf !ThuluthFeatures.pdf diff --git a/test/pdfs/decodeACSuccessive.pdf b/test/pdfs/decodeACSuccessive.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ed05a3cf5d464ffdbb566b9c1b9e27ce636c9adc GIT binary patch literal 2867 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 literal 0 HcmV?d00001 diff --git a/test/test_manifest.json b/test/test_manifest.json index 3958b19c6..0648b967c 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -3589,6 +3589,14 @@ "type": "eq", "nativeImageDecoderSupport": "none" }, + { "id": "decodeACSuccessive", + "file": "pdfs/decodeACSuccessive.pdf", + "md5": "7749c032624fe27ab8e8d7d5e9a4a93f", + "rounds": 1, + "link": false, + "type": "eq", + "nativeImageDecoderSupport": "none" + }, { "id": "issue5592", "file": "pdfs/issue5592.pdf", "md5": "a0750f95afa80c880f7966df7062616c",