From 857c2a2bd5157adabdbe0c52052e298b62a43f5f Mon Sep 17 00:00:00 2001 From: Joseph Milazzo Date: Tue, 21 Sep 2021 08:22:07 -0700 Subject: [PATCH] High Res images breaking due to Canvas limits (#587) * Fixed an issue where on Safari with high resolution images, the canvas wouldn't be able to render them. Now we detect high res that might break canvas on different browsers and scale them. * Removed some code no longer needed --- .../manga-reader/manga-reader.component.ts | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/UI/Web/src/app/manga-reader/manga-reader.component.ts b/UI/Web/src/app/manga-reader/manga-reader.component.ts index 8511417a1..730f0be4b 100644 --- a/UI/Web/src/app/manga-reader/manga-reader.component.ts +++ b/UI/Web/src/app/manga-reader/manga-reader.component.ts @@ -774,11 +774,35 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { } } + /** + * There are some hard limits on the size of canvas' that we must cap at. https://github.com/jhildenbiddle/canvas-size#test-results + * For Safari, it's 16,777,216, so we cap at 4096x4096 when this happens. The drawImage in render will perform bi-cubic scaling for us. + * @returns If we should continue to the render loop + */ + setCanvasSize() { + if (this.ctx && this.canvas) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && window['safari'].pushNotification)); + const canvasLimit = isSafari ? 16_777_216 : 124_992_400; + const needsScaling = this.canvasImage.width * this.canvasImage.height > canvasLimit; + if (needsScaling) { + this.canvas.nativeElement.width = isSafari ? 4_096 : 16_384; + this.canvas.nativeElement.height = isSafari ? 4_096 : 16_384; + } else { + this.canvas.nativeElement.width = this.canvasImage.width; + this.canvas.nativeElement.height = this.canvasImage.height; + } + } + return true; + } + renderPage() { if (this.ctx && this.canvas) { this.canvasImage.onload = null; - this.canvas.nativeElement.width = this.canvasImage.width; - this.canvas.nativeElement.height = this.canvasImage.height; + + if (!this.setCanvasSize()) return; + const needsSplitting = this.canvasImage.width > this.canvasImage.height; this.updateSplitPage();