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).
This commit is contained in:
Jonas Jenwald 2017-12-29 14:39:29 +01:00
parent d6eed132e5
commit c5700211d6
4 changed files with 18 additions and 8 deletions

View File

@ -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;
}

View File

@ -67,6 +67,7 @@
!issue9105_reduced.pdf
!issue9291.pdf
!bad-PageLabels.pdf
!decodeACSuccessive.pdf
!filled-background.pdf
!ArabicCIDTrueType.pdf
!ThuluthFeatures.pdf

Binary file not shown.

View File

@ -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",