Enable/disable image smoothing based on image interpolate value. (bug 1722191)
While some of the output looks worse to my eye, this behavior more closely matches what I see when I open the PDFs in Adobe acrobat. Fixes: #4706, #9713, #8245, #1344
This commit is contained in:
parent
8a79f13e5a
commit
f38fb42b42
@ -589,6 +589,7 @@ class PartialEvaluator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const imageMask = dict.get("ImageMask", "IM") || false;
|
const imageMask = dict.get("ImageMask", "IM") || false;
|
||||||
|
const interpolate = dict.get("Interpolate", "I");
|
||||||
let imgData, args;
|
let imgData, args;
|
||||||
if (imageMask) {
|
if (imageMask) {
|
||||||
// This depends on a tmpCanvas being filled with the
|
// This depends on a tmpCanvas being filled with the
|
||||||
@ -612,6 +613,7 @@ class PartialEvaluator {
|
|||||||
height,
|
height,
|
||||||
imageIsFromDecodeStream: image instanceof DecodeStream,
|
imageIsFromDecodeStream: image instanceof DecodeStream,
|
||||||
inverseDecode: !!decode && decode[0] > 0,
|
inverseDecode: !!decode && decode[0] > 0,
|
||||||
|
interpolate,
|
||||||
});
|
});
|
||||||
imgData.cached = !!cacheKey;
|
imgData.cached = !!cacheKey;
|
||||||
args = [imgData];
|
args = [imgData];
|
||||||
|
@ -139,7 +139,7 @@ class PDFImage {
|
|||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
|
||||||
this.interpolate = dict.get("Interpolate", "I") || false;
|
this.interpolate = dict.get("Interpolate", "I");
|
||||||
this.imageMask = dict.get("ImageMask", "IM") || false;
|
this.imageMask = dict.get("ImageMask", "IM") || false;
|
||||||
this.matte = dict.get("Matte") || false;
|
this.matte = dict.get("Matte") || false;
|
||||||
|
|
||||||
@ -294,6 +294,7 @@ class PDFImage {
|
|||||||
height,
|
height,
|
||||||
imageIsFromDecodeStream,
|
imageIsFromDecodeStream,
|
||||||
inverseDecode,
|
inverseDecode,
|
||||||
|
interpolate,
|
||||||
}) {
|
}) {
|
||||||
if (
|
if (
|
||||||
typeof PDFJSDev === "undefined" ||
|
typeof PDFJSDev === "undefined" ||
|
||||||
@ -339,7 +340,7 @@ class PDFImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { data, width, height };
|
return { data, width, height, interpolate };
|
||||||
}
|
}
|
||||||
|
|
||||||
get drawWidth() {
|
get drawWidth() {
|
||||||
@ -593,6 +594,7 @@ class PDFImage {
|
|||||||
const imgData = {
|
const imgData = {
|
||||||
width: drawWidth,
|
width: drawWidth,
|
||||||
height: drawHeight,
|
height: drawHeight,
|
||||||
|
interpolate: this.interpolate,
|
||||||
kind: 0,
|
kind: 0,
|
||||||
data: null,
|
data: null,
|
||||||
// Other fields are filled in below.
|
// Other fields are filled in below.
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import { CSS_PIXELS_PER_INCH, PDF_PIXELS_PER_INCH } from "./display_utils.js";
|
||||||
import {
|
import {
|
||||||
FONT_IDENTITY_MATRIX,
|
FONT_IDENTITY_MATRIX,
|
||||||
IDENTITY_MATRIX,
|
IDENTITY_MATRIX,
|
||||||
@ -871,6 +871,27 @@ function composeSMask(ctx, smask, layerCtx) {
|
|||||||
ctx.drawImage(mask, 0, 0);
|
ctx.drawImage(mask, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getImageSmoothingEnabled(transform, interpolate) {
|
||||||
|
const scale = Util.singularValueDecompose2dScale(transform);
|
||||||
|
// Round to a 32bit float so that `<=` check below will pass for numbers that
|
||||||
|
// are very close, but not exactly the same 64bit floats.
|
||||||
|
scale[0] = Math.fround(scale[0]);
|
||||||
|
scale[1] = Math.fround(scale[1]);
|
||||||
|
const actualScale = Math.fround(
|
||||||
|
((globalThis.devicePixelRatio || 1) * CSS_PIXELS_PER_INCH) /
|
||||||
|
PDF_PIXELS_PER_INCH
|
||||||
|
);
|
||||||
|
if (interpolate !== undefined) {
|
||||||
|
// If the value is explicitly set use it.
|
||||||
|
return interpolate;
|
||||||
|
} else if (scale[0] <= actualScale || scale[1] <= actualScale) {
|
||||||
|
// Smooth when downscaling.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Don't smooth when upscaling.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const LINE_CAP_STYLES = ["butt", "round", "square"];
|
const LINE_CAP_STYLES = ["butt", "round", "square"];
|
||||||
const LINE_JOIN_STYLES = ["miter", "round", "bevel"];
|
const LINE_JOIN_STYLES = ["miter", "round", "bevel"];
|
||||||
const NORMAL_CLIP = {};
|
const NORMAL_CLIP = {};
|
||||||
@ -1183,6 +1204,10 @@ class CanvasGraphics {
|
|||||||
maskCanvas.canvas,
|
maskCanvas.canvas,
|
||||||
fillCtx.mozCurrentTransformInverse
|
fillCtx.mozCurrentTransformInverse
|
||||||
);
|
);
|
||||||
|
fillCtx.imageSmoothingEnabled = getImageSmoothingEnabled(
|
||||||
|
fillCtx.mozCurrentTransform,
|
||||||
|
img.interpolate
|
||||||
|
);
|
||||||
fillCtx.drawImage(
|
fillCtx.drawImage(
|
||||||
scaled.img,
|
scaled.img,
|
||||||
0,
|
0,
|
||||||
@ -2663,6 +2688,10 @@ class CanvasGraphics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const scaled = this._scaleImage(imgToPaint, ctx.mozCurrentTransformInverse);
|
const scaled = this._scaleImage(imgToPaint, ctx.mozCurrentTransformInverse);
|
||||||
|
ctx.imageSmoothingEnabled = getImageSmoothingEnabled(
|
||||||
|
ctx.mozCurrentTransform,
|
||||||
|
imgData.interpolate
|
||||||
|
);
|
||||||
ctx.drawImage(
|
ctx.drawImage(
|
||||||
scaled.img,
|
scaled.img,
|
||||||
0,
|
0,
|
||||||
|
@ -32,6 +32,9 @@ import {
|
|||||||
const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
|
const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
|
||||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||||
|
|
||||||
|
const CSS_PIXELS_PER_INCH = 96.0;
|
||||||
|
const PDF_PIXELS_PER_INCH = 72.0;
|
||||||
|
|
||||||
class DOMCanvasFactory extends BaseCanvasFactory {
|
class DOMCanvasFactory extends BaseCanvasFactory {
|
||||||
constructor({ ownerDocument = globalThis.document } = {}) {
|
constructor({ ownerDocument = globalThis.document } = {}) {
|
||||||
super();
|
super();
|
||||||
@ -622,6 +625,7 @@ function getXfaPageViewport(xfaPage, { scale = 1, rotation = 0 }) {
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
addLinkAttributes,
|
addLinkAttributes,
|
||||||
|
CSS_PIXELS_PER_INCH,
|
||||||
DEFAULT_LINK_REL,
|
DEFAULT_LINK_REL,
|
||||||
deprecated,
|
deprecated,
|
||||||
DOMCanvasFactory,
|
DOMCanvasFactory,
|
||||||
@ -637,6 +641,7 @@ export {
|
|||||||
LinkTarget,
|
LinkTarget,
|
||||||
loadScript,
|
loadScript,
|
||||||
PageViewport,
|
PageViewport,
|
||||||
|
PDF_PIXELS_PER_INCH,
|
||||||
PDFDateString,
|
PDFDateString,
|
||||||
RenderingCancelledException,
|
RenderingCancelledException,
|
||||||
StatTimer,
|
StatTimer,
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
addLinkAttributes,
|
addLinkAttributes,
|
||||||
|
CSS_PIXELS_PER_INCH,
|
||||||
getFilenameFromUrl,
|
getFilenameFromUrl,
|
||||||
getPdfFilenameFromUrl,
|
getPdfFilenameFromUrl,
|
||||||
getXfaPageViewport,
|
getXfaPageViewport,
|
||||||
@ -23,6 +24,7 @@ import {
|
|||||||
isValidFetchUrl,
|
isValidFetchUrl,
|
||||||
LinkTarget,
|
LinkTarget,
|
||||||
loadScript,
|
loadScript,
|
||||||
|
PDF_PIXELS_PER_INCH,
|
||||||
PDFDateString,
|
PDFDateString,
|
||||||
RenderingCancelledException,
|
RenderingCancelledException,
|
||||||
} from "./display/display_utils.js";
|
} from "./display/display_utils.js";
|
||||||
@ -103,11 +105,13 @@ if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")) {
|
|||||||
export {
|
export {
|
||||||
// From "./display/display_utils.js":
|
// From "./display/display_utils.js":
|
||||||
addLinkAttributes,
|
addLinkAttributes,
|
||||||
|
CSS_PIXELS_PER_INCH,
|
||||||
getFilenameFromUrl,
|
getFilenameFromUrl,
|
||||||
getPdfFilenameFromUrl,
|
getPdfFilenameFromUrl,
|
||||||
isPdfFile,
|
isPdfFile,
|
||||||
LinkTarget,
|
LinkTarget,
|
||||||
loadScript,
|
loadScript,
|
||||||
|
PDF_PIXELS_PER_INCH,
|
||||||
PDFDateString,
|
PDFDateString,
|
||||||
RenderingCancelledException,
|
RenderingCancelledException,
|
||||||
getXfaPageViewport,
|
getXfaPageViewport,
|
||||||
|
@ -20,15 +20,17 @@
|
|||||||
const {
|
const {
|
||||||
AnnotationLayer,
|
AnnotationLayer,
|
||||||
AnnotationMode,
|
AnnotationMode,
|
||||||
|
CSS_PIXELS_PER_INCH,
|
||||||
getDocument,
|
getDocument,
|
||||||
GlobalWorkerOptions,
|
GlobalWorkerOptions,
|
||||||
|
PDF_PIXELS_PER_INCH,
|
||||||
renderTextLayer,
|
renderTextLayer,
|
||||||
XfaLayer,
|
XfaLayer,
|
||||||
} = pdfjsLib;
|
} = pdfjsLib;
|
||||||
const { SimpleLinkService } = pdfjsViewer;
|
const { SimpleLinkService } = pdfjsViewer;
|
||||||
|
|
||||||
const WAITING_TIME = 100; // ms
|
const WAITING_TIME = 100; // ms
|
||||||
const PDF_TO_CSS_UNITS = 96.0 / 72.0;
|
const PDF_TO_CSS_UNITS = CSS_PIXELS_PER_INCH / PDF_PIXELS_PER_INCH;
|
||||||
const CMAP_URL = "/build/generic/web/cmaps/";
|
const CMAP_URL = "/build/generic/web/cmaps/";
|
||||||
const CMAP_PACKED = true;
|
const CMAP_PACKED = true;
|
||||||
const STANDARD_FONT_DATA_URL = "/build/generic/web/standard_fonts/";
|
const STANDARD_FONT_DATA_URL = "/build/generic/web/standard_fonts/";
|
||||||
|
2
test/pdfs/.gitignore
vendored
2
test/pdfs/.gitignore
vendored
@ -69,6 +69,7 @@
|
|||||||
!issue8229.pdf
|
!issue8229.pdf
|
||||||
!issue8276_reduced.pdf
|
!issue8276_reduced.pdf
|
||||||
!issue8372.pdf
|
!issue8372.pdf
|
||||||
|
!issue9713.pdf
|
||||||
!xfa_filled_imm1344e.pdf
|
!xfa_filled_imm1344e.pdf
|
||||||
!issue8424.pdf
|
!issue8424.pdf
|
||||||
!issue8480.pdf
|
!issue8480.pdf
|
||||||
@ -150,6 +151,7 @@
|
|||||||
!complex_ttf_font.pdf
|
!complex_ttf_font.pdf
|
||||||
!issue3694_reduced.pdf
|
!issue3694_reduced.pdf
|
||||||
!extgstate.pdf
|
!extgstate.pdf
|
||||||
|
!issue4706.pdf
|
||||||
!rotation.pdf
|
!rotation.pdf
|
||||||
!simpletype3font.pdf
|
!simpletype3font.pdf
|
||||||
!sizes.pdf
|
!sizes.pdf
|
||||||
|
BIN
test/pdfs/issue4706.pdf
Normal file
BIN
test/pdfs/issue4706.pdf
Normal file
Binary file not shown.
BIN
test/pdfs/issue9713.pdf
Normal file
BIN
test/pdfs/issue9713.pdf
Normal file
Binary file not shown.
@ -3110,6 +3110,12 @@
|
|||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "issue4706",
|
||||||
|
"file": "pdfs/issue4706.pdf",
|
||||||
|
"md5": "f3e90a3cf52550583fa2a07a138b8660",
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "issue11242",
|
{ "id": "issue11242",
|
||||||
"file": "pdfs/issue11242_reduced.pdf",
|
"file": "pdfs/issue11242_reduced.pdf",
|
||||||
"md5": "ba50b6ee537f3e815ccfe0c99e598e05",
|
"md5": "ba50b6ee537f3e815ccfe0c99e598e05",
|
||||||
@ -4421,6 +4427,12 @@
|
|||||||
"link": true,
|
"link": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "issue9713",
|
||||||
|
"file": "pdfs/issue9713.pdf",
|
||||||
|
"md5": "a62bd42d12271105b26a68c8eae5ea5f",
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "issue1936-text",
|
{ "id": "issue1936-text",
|
||||||
"file": "pdfs/issue1936.pdf",
|
"file": "pdfs/issue1936.pdf",
|
||||||
"md5": "7302eb9b6a626308e2a933aaed9e1756",
|
"md5": "7302eb9b6a626308e2a933aaed9e1756",
|
||||||
|
@ -13,7 +13,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AnnotationMode, RenderingCancelledException, shadow } from "pdfjs-lib";
|
import {
|
||||||
|
AnnotationMode,
|
||||||
|
PDF_PIXELS_PER_INCH,
|
||||||
|
RenderingCancelledException,
|
||||||
|
shadow,
|
||||||
|
} from "pdfjs-lib";
|
||||||
import { getXfaHtmlForPrinting } from "./print_utils.js";
|
import { getXfaHtmlForPrinting } from "./print_utils.js";
|
||||||
import { PDFPrintServiceFactory } from "./app.js";
|
import { PDFPrintServiceFactory } from "./app.js";
|
||||||
|
|
||||||
@ -29,7 +34,7 @@ function composePage(
|
|||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement("canvas");
|
||||||
|
|
||||||
// The size of the canvas in pixels for printing.
|
// The size of the canvas in pixels for printing.
|
||||||
const PRINT_UNITS = printResolution / 72.0;
|
const PRINT_UNITS = printResolution / PDF_PIXELS_PER_INCH;
|
||||||
canvas.width = Math.floor(size.width * PRINT_UNITS);
|
canvas.width = Math.floor(size.width * PRINT_UNITS);
|
||||||
canvas.height = Math.floor(size.height * PRINT_UNITS);
|
canvas.height = Math.floor(size.height * PRINT_UNITS);
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { AnnotationMode, PDF_PIXELS_PER_INCH } from "pdfjs-lib";
|
||||||
import { PDFPrintServiceFactory, PDFViewerApplication } from "./app.js";
|
import { PDFPrintServiceFactory, PDFViewerApplication } from "./app.js";
|
||||||
import { AnnotationMode } from "pdfjs-lib";
|
|
||||||
import { compatibilityParams } from "./app_options.js";
|
import { compatibilityParams } from "./app_options.js";
|
||||||
import { getXfaHtmlForPrinting } from "./print_utils.js";
|
import { getXfaHtmlForPrinting } from "./print_utils.js";
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ function renderPage(
|
|||||||
const scratchCanvas = activeService.scratchCanvas;
|
const scratchCanvas = activeService.scratchCanvas;
|
||||||
|
|
||||||
// The size of the canvas in pixels for printing.
|
// The size of the canvas in pixels for printing.
|
||||||
const PRINT_UNITS = printResolution / 72.0;
|
const PRINT_UNITS = printResolution / PDF_PIXELS_PER_INCH;
|
||||||
scratchCanvas.width = Math.floor(size.width * PRINT_UNITS);
|
scratchCanvas.width = Math.floor(size.width * PRINT_UNITS);
|
||||||
scratchCanvas.height = Math.floor(size.height * PRINT_UNITS);
|
scratchCanvas.height = Math.floor(size.height * PRINT_UNITS);
|
||||||
|
|
||||||
|
@ -13,7 +13,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const CSS_UNITS = 96.0 / 72.0;
|
import { CSS_PIXELS_PER_INCH, PDF_PIXELS_PER_INCH } from "pdfjs-lib";
|
||||||
|
|
||||||
|
const CSS_UNITS = CSS_PIXELS_PER_INCH / PDF_PIXELS_PER_INCH;
|
||||||
const DEFAULT_SCALE_VALUE = "auto";
|
const DEFAULT_SCALE_VALUE = "auto";
|
||||||
const DEFAULT_SCALE = 1.0;
|
const DEFAULT_SCALE = 1.0;
|
||||||
const MIN_SCALE = 0.1;
|
const MIN_SCALE = 0.1;
|
||||||
|
Loading…
Reference in New Issue
Block a user