mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
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
13 changed files with 74 additions and 9 deletions
|
@ -589,6 +589,7 @@ class PartialEvaluator {
|
|||
}
|
||||
|
||||
const imageMask = dict.get("ImageMask", "IM") || false;
|
||||
const interpolate = dict.get("Interpolate", "I");
|
||||
let imgData, args;
|
||||
if (imageMask) {
|
||||
// This depends on a tmpCanvas being filled with the
|
||||
|
@ -612,6 +613,7 @@ class PartialEvaluator {
|
|||
height,
|
||||
imageIsFromDecodeStream: image instanceof DecodeStream,
|
||||
inverseDecode: !!decode && decode[0] > 0,
|
||||
interpolate,
|
||||
});
|
||||
imgData.cached = !!cacheKey;
|
||||
args = [imgData];
|
||||
|
|
|
@ -139,7 +139,7 @@ class PDFImage {
|
|||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.interpolate = dict.get("Interpolate", "I") || false;
|
||||
this.interpolate = dict.get("Interpolate", "I");
|
||||
this.imageMask = dict.get("ImageMask", "IM") || false;
|
||||
this.matte = dict.get("Matte") || false;
|
||||
|
||||
|
@ -294,6 +294,7 @@ class PDFImage {
|
|||
height,
|
||||
imageIsFromDecodeStream,
|
||||
inverseDecode,
|
||||
interpolate,
|
||||
}) {
|
||||
if (
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
|
@ -339,7 +340,7 @@ class PDFImage {
|
|||
}
|
||||
}
|
||||
|
||||
return { data, width, height };
|
||||
return { data, width, height, interpolate };
|
||||
}
|
||||
|
||||
get drawWidth() {
|
||||
|
@ -593,6 +594,7 @@ class PDFImage {
|
|||
const imgData = {
|
||||
width: drawWidth,
|
||||
height: drawHeight,
|
||||
interpolate: this.interpolate,
|
||||
kind: 0,
|
||||
data: null,
|
||||
// Other fields are filled in below.
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CSS_PIXELS_PER_INCH, PDF_PIXELS_PER_INCH } from "./display_utils.js";
|
||||
import {
|
||||
FONT_IDENTITY_MATRIX,
|
||||
IDENTITY_MATRIX,
|
||||
|
@ -871,6 +871,27 @@ function composeSMask(ctx, smask, layerCtx) {
|
|||
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_JOIN_STYLES = ["miter", "round", "bevel"];
|
||||
const NORMAL_CLIP = {};
|
||||
|
@ -1183,6 +1204,10 @@ class CanvasGraphics {
|
|||
maskCanvas.canvas,
|
||||
fillCtx.mozCurrentTransformInverse
|
||||
);
|
||||
fillCtx.imageSmoothingEnabled = getImageSmoothingEnabled(
|
||||
fillCtx.mozCurrentTransform,
|
||||
img.interpolate
|
||||
);
|
||||
fillCtx.drawImage(
|
||||
scaled.img,
|
||||
0,
|
||||
|
@ -2663,6 +2688,10 @@ class CanvasGraphics {
|
|||
}
|
||||
|
||||
const scaled = this._scaleImage(imgToPaint, ctx.mozCurrentTransformInverse);
|
||||
ctx.imageSmoothingEnabled = getImageSmoothingEnabled(
|
||||
ctx.mozCurrentTransform,
|
||||
imgData.interpolate
|
||||
);
|
||||
ctx.drawImage(
|
||||
scaled.img,
|
||||
0,
|
||||
|
|
|
@ -32,6 +32,9 @@ import {
|
|||
const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
|
||||
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 {
|
||||
constructor({ ownerDocument = globalThis.document } = {}) {
|
||||
super();
|
||||
|
@ -622,6 +625,7 @@ function getXfaPageViewport(xfaPage, { scale = 1, rotation = 0 }) {
|
|||
|
||||
export {
|
||||
addLinkAttributes,
|
||||
CSS_PIXELS_PER_INCH,
|
||||
DEFAULT_LINK_REL,
|
||||
deprecated,
|
||||
DOMCanvasFactory,
|
||||
|
@ -637,6 +641,7 @@ export {
|
|||
LinkTarget,
|
||||
loadScript,
|
||||
PageViewport,
|
||||
PDF_PIXELS_PER_INCH,
|
||||
PDFDateString,
|
||||
RenderingCancelledException,
|
||||
StatTimer,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
import {
|
||||
addLinkAttributes,
|
||||
CSS_PIXELS_PER_INCH,
|
||||
getFilenameFromUrl,
|
||||
getPdfFilenameFromUrl,
|
||||
getXfaPageViewport,
|
||||
|
@ -23,6 +24,7 @@ import {
|
|||
isValidFetchUrl,
|
||||
LinkTarget,
|
||||
loadScript,
|
||||
PDF_PIXELS_PER_INCH,
|
||||
PDFDateString,
|
||||
RenderingCancelledException,
|
||||
} from "./display/display_utils.js";
|
||||
|
@ -103,11 +105,13 @@ if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")) {
|
|||
export {
|
||||
// From "./display/display_utils.js":
|
||||
addLinkAttributes,
|
||||
CSS_PIXELS_PER_INCH,
|
||||
getFilenameFromUrl,
|
||||
getPdfFilenameFromUrl,
|
||||
isPdfFile,
|
||||
LinkTarget,
|
||||
loadScript,
|
||||
PDF_PIXELS_PER_INCH,
|
||||
PDFDateString,
|
||||
RenderingCancelledException,
|
||||
getXfaPageViewport,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue