Merge pull request #20085 from calixteman/bug1975719

Handle the case where all the image data are in the alpha channel (bug 1975719)
This commit is contained in:
calixteman 2025-07-14 22:44:19 +02:00 committed by GitHub
commit ac2a0c5080
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 86 additions and 19 deletions

View File

@ -614,6 +614,8 @@ pdfjs-editor-add-signature-save-checkbox = Save signature
pdfjs-editor-add-signature-save-warning-message = Youve reached the limit of 5 saved signatures. Remove one to save more. pdfjs-editor-add-signature-save-warning-message = Youve reached the limit of 5 saved signatures. Remove one to save more.
pdfjs-editor-add-signature-image-upload-error-title = Couldnt upload image pdfjs-editor-add-signature-image-upload-error-title = Couldnt upload image
pdfjs-editor-add-signature-image-upload-error-description = Check your network connection or try another image. pdfjs-editor-add-signature-image-upload-error-description = Check your network connection or try another image.
pdfjs-editor-add-signature-image-no-data-error-title = Cant convert this image into a signature
pdfjs-editor-add-signature-image-no-data-error-description = Please try uploading a different image.
pdfjs-editor-add-signature-error-close-button = Close pdfjs-editor-add-signature-error-close-button = Close
## Dialog buttons ## Dialog buttons

View File

@ -366,21 +366,12 @@ class SignatureExtractor {
let max = -Infinity; let max = -Infinity;
let min = Infinity; let min = Infinity;
for (let i = 0, ii = out.length; i < ii; i++) { for (let i = 0, ii = out.length; i < ii; i++) {
const A = buf[(i << 2) + 3];
if (A === 0) {
max = out[i] = 0xff;
continue;
}
const pix = (out[i] = buf[i << 2]); const pix = (out[i] = buf[i << 2]);
if (pix > max) { max = Math.max(max, pix);
max = pix; min = Math.min(min, pix);
}
if (pix < min) {
min = pix;
}
} }
const ratio = 255 / (max - min); const ratio = 255 / (max - min);
for (let i = 0; i < N; i++) { for (let i = 0, ii = out.length; i < ii; i++) {
out[i] = (out[i] - min) * ratio; out[i] = (out[i] - min) * ratio;
} }
@ -468,6 +459,8 @@ class SignatureExtractor {
} }
const offscreen = new OffscreenCanvas(newWidth, newHeight); const offscreen = new OffscreenCanvas(newWidth, newHeight);
const ctx = offscreen.getContext("2d", { willReadFrequently: true }); const ctx = offscreen.getContext("2d", { willReadFrequently: true });
ctx.fillStyle = "white";
ctx.fillRect(0, 0, newWidth, newHeight);
ctx.filter = "grayscale(1)"; ctx.filter = "grayscale(1)";
ctx.drawImage( ctx.drawImage(
bitmap, bitmap,

View File

@ -727,4 +727,47 @@ describe("Signature Editor", () => {
); );
}); });
}); });
describe("Bug 1975719", () => {
let pages;
beforeEach(async () => {
pages = await loadAndWait("empty.pdf", ".annotationEditorLayer");
});
afterEach(async () => {
await closePages(pages);
});
it("must check that an error is displayed with a monochrome image", async () => {
await Promise.all(
pages.map(async ([_, page]) => {
await switchToSignature(page);
await page.click("#editorSignatureAddSignature");
await page.waitForSelector("#addSignatureDialog", {
visible: true,
});
await page.click("#addSignatureImageButton");
await page.waitForSelector("#addSignatureImagePlaceholder", {
visible: true,
});
const input = await page.$("#addSignatureFilePicker");
await input.uploadFile(
`${path.join(__dirname, "../images/red.png")}`
);
await page.waitForSelector("#addSignatureError", { visible: true });
await page.waitForSelector(
"#addSignatureErrorTitle[data-l10n-id='pdfjs-editor-add-signature-image-no-data-error-title']"
);
await page.waitForSelector(
"#addSignatureErrorDescription[data-l10n-id='pdfjs-editor-add-signature-image-no-data-error-description']"
);
await page.click("#addSignatureErrorCloseButton");
await page.waitForSelector("#addSignatureError", { visible: false });
})
);
});
});
}); });

View File

@ -56,6 +56,10 @@ class SignatureManager {
#errorBar; #errorBar;
#errorDescription;
#errorTitle;
#extractedSignatureData = null; #extractedSignatureData = null;
#imagePath = null; #imagePath = null;
@ -123,6 +127,8 @@ class SignatureManager {
addButton, addButton,
errorCloseButton, errorCloseButton,
errorBar, errorBar,
errorTitle,
errorDescription,
saveCheckbox, saveCheckbox,
saveContainer, saveContainer,
}, },
@ -142,6 +148,8 @@ class SignatureManager {
this.#drawPlaceholder = drawPlaceholder; this.#drawPlaceholder = drawPlaceholder;
this.#drawThickness = drawThickness; this.#drawThickness = drawThickness;
this.#errorBar = errorBar; this.#errorBar = errorBar;
this.#errorTitle = errorTitle;
this.#errorDescription = errorDescription;
this.#imageSVG = imageSVG; this.#imageSVG = imageSVG;
this.#imagePlaceholder = imagePlaceholder; this.#imagePlaceholder = imagePlaceholder;
this.#imagePicker = imagePicker; this.#imagePicker = imagePicker;
@ -161,6 +169,12 @@ class SignatureManager {
SignatureManager.#l10nDescription ||= Object.freeze({ SignatureManager.#l10nDescription ||= Object.freeze({
signature: "pdfjs-editor-add-signature-description-default-when-drawing", signature: "pdfjs-editor-add-signature-description-default-when-drawing",
errorUploadTitle: "pdfjs-editor-add-signature-image-upload-error-title",
errorUploadDescription:
"pdfjs-editor-add-signature-image-upload-error-description",
errorNoDataTitle: "pdfjs-editor-add-signature-image-no-data-error-title",
errorNoDataDescription:
"pdfjs-editor-add-signature-image-no-data-error-description",
}); });
dialog.addEventListener("close", this.#close.bind(this)); dialog.addEventListener("close", this.#close.bind(this));
@ -506,6 +520,18 @@ class SignatureManager {
); );
} }
#showError(type) {
this.#errorTitle.setAttribute(
"data-l10n-id",
SignatureManager.#l10nDescription[`error${type}Title`]
);
this.#errorDescription.setAttribute(
"data-l10n-id",
SignatureManager.#l10nDescription[`error${type}Description`]
);
this.#errorBar.hidden = false;
}
#initImageTab(reset) { #initImageTab(reset) {
if (reset) { if (reset) {
this.#resetTab("image"); this.#resetTab("image");
@ -539,7 +565,7 @@ class SignatureManager {
async () => { async () => {
const file = this.#imagePicker.files?.[0]; const file = this.#imagePicker.files?.[0];
if (!file || !SupportedImageMimeTypes.includes(file.type)) { if (!file || !SupportedImageMimeTypes.includes(file.type)) {
this.#errorBar.hidden = false; this.#showError("Upload");
this.#dialog.classList.toggle("waiting", false); this.#dialog.classList.toggle("waiting", false);
return; return;
} }
@ -601,18 +627,19 @@ class SignatureManager {
console.error("SignatureManager.#extractSignature.", e); console.error("SignatureManager.#extractSignature.", e);
} }
if (!data) { if (!data) {
this.#errorBar.hidden = false; this.#showError("Upload");
this.#dialog.classList.toggle("waiting", false); this.#dialog.classList.toggle("waiting", false);
return; return;
} }
const { outline } = (this.#extractedSignatureData = const lineData = (this.#extractedSignatureData =
this.#currentEditor.getFromImage(data.bitmap)); this.#currentEditor.getFromImage(data.bitmap));
if (!lineData) {
if (!outline) { this.#showError("NoData");
this.#dialog.classList.toggle("waiting", false); this.#dialog.classList.toggle("waiting", false);
return; return;
} }
const { outline } = lineData;
this.#imagePlaceholder.hidden = true; this.#imagePlaceholder.hidden = true;
this.#disableButtons(true); this.#disableButtons(true);

View File

@ -735,8 +735,8 @@ See https://github.com/adobe-type-tools/cmap-resources
<div id="addSignatureError" hidden="true" class="messageBar"> <div id="addSignatureError" hidden="true" class="messageBar">
<div> <div>
<div> <div>
<span class="title" data-l10n-id="pdfjs-editor-add-signature-image-upload-error-title"></span> <span id="addSignatureErrorTitle" class="title" data-l10n-id="pdfjs-editor-add-signature-image-upload-error-title"></span>
<span class="description" data-l10n-id="pdfjs-editor-add-signature-image-upload-error-description"></span> <span id="addSignatureErrorDescription" class="description" data-l10n-id="pdfjs-editor-add-signature-image-upload-error-description"></span>
</div> </div>
<button id="addSignatureErrorCloseButton" class="closeButton" type="button" tabindex="0"><span data-l10n-id="pdfjs-editor-add-signature-error-close-button"></span></button> <button id="addSignatureErrorCloseButton" class="closeButton" type="button" tabindex="0"><span data-l10n-id="pdfjs-editor-add-signature-error-close-button"></span></button>
</div> </div>

View File

@ -227,6 +227,8 @@ function getViewerConfiguration() {
saveContainer: document.getElementById("addSignatureSaveContainer"), saveContainer: document.getElementById("addSignatureSaveContainer"),
saveCheckbox: document.getElementById("addSignatureSaveCheckbox"), saveCheckbox: document.getElementById("addSignatureSaveCheckbox"),
errorBar: document.getElementById("addSignatureError"), errorBar: document.getElementById("addSignatureError"),
errorTitle: document.getElementById("addSignatureErrorTitle"),
errorDescription: document.getElementById("addSignatureErrorDescription"),
errorCloseButton: document.getElementById("addSignatureErrorCloseButton"), errorCloseButton: document.getElementById("addSignatureErrorCloseButton"),
cancelButton: document.getElementById("addSignatureCancelButton"), cancelButton: document.getElementById("addSignatureCancelButton"),
addButton: document.getElementById("addSignatureAddButton"), addButton: document.getElementById("addSignatureAddButton"),