From 3672f36e6e513e839dac4c906ce40f3ac2406798 Mon Sep 17 00:00:00 2001 From: Andrii Rodzyk Date: Sun, 29 Mar 2026 16:19:54 +0300 Subject: [PATCH] feat(zip/cbz): enhance image filtering and processing for SVG files --- src/app/file/utils/filter-images.ts | 2 +- .../file/utils/process-images-in-batches.ts | 15 +++++++++++- .../hint-page/hint-page.component.html | 2 +- .../components/page/page.component.html | 4 ++-- .../viewer/components/page/page.component.ts | 23 ++++++++++++++++++- 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/app/file/utils/filter-images.ts b/src/app/file/utils/filter-images.ts index bfd6853..f6ae481 100644 --- a/src/app/file/utils/filter-images.ts +++ b/src/app/file/utils/filter-images.ts @@ -1,5 +1,5 @@ export function filterImages(fileList: Array) { - const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']; + const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.tiff', '.svg', '.svgz']; return fileList.filter(file => { const extension = file.substring(file.lastIndexOf('.')).toLowerCase(); diff --git a/src/app/file/utils/process-images-in-batches.ts b/src/app/file/utils/process-images-in-batches.ts index 3d6a5ef..6402379 100644 --- a/src/app/file/utils/process-images-in-batches.ts +++ b/src/app/file/utils/process-images-in-batches.ts @@ -10,8 +10,21 @@ export async function processImagesInBatches( await Promise.all( batch.map(async (filename, index) => { - const blob = await zip.files[filename].async('blob'); + const file = zip.files[filename]; + if (!file) return; + + const svgExtensions = ['.svg', '.svgz']; + let blob: Blob; + + if (svgExtensions.some(ext => filename.toLowerCase().endsWith(ext))) { + const text = await file.async('string'); + blob = new Blob([text], { type: 'image/svg+xml' }); + } else { + blob = await file.async('blob'); + } + const url = URL.createObjectURL(blob); + postMessage({ type: 'file', url, diff --git a/src/app/viewer/viewer/components/hint-page/hint-page.component.html b/src/app/viewer/viewer/components/hint-page/hint-page.component.html index 5c9cbb5..e7737dc 100644 --- a/src/app/viewer/viewer/components/hint-page/hint-page.component.html +++ b/src/app/viewer/viewer/components/hint-page/hint-page.component.html @@ -1,4 +1,4 @@ - + {{lang.ph().getByKey(viewer.viewModeOption().hintPhraceKey)}} diff --git a/src/app/viewer/viewer/components/page/page.component.html b/src/app/viewer/viewer/components/page/page.component.html index b6835fd..84db5ae 100644 --- a/src/app/viewer/viewer/components/page/page.component.html +++ b/src/app/viewer/viewer/components/page/page.component.html @@ -10,8 +10,8 @@ }
@if(src()){ -
+ } @else { } diff --git a/src/app/viewer/viewer/components/page/page.component.ts b/src/app/viewer/viewer/components/page/page.component.ts index 3d5055d..a95519f 100644 --- a/src/app/viewer/viewer/components/page/page.component.ts +++ b/src/app/viewer/viewer/components/page/page.component.ts @@ -28,6 +28,9 @@ export class PageComponent { width = computed(() => this.naturalWidth() ?? this.inputWidth()); height = computed(() => this.naturalHeight() ?? this.inputHeight()); + widthPx = computed(() => this.width().toString() + 'px'); + heightPx = computed(() => this.height().toString() + 'px'); + index: InputSignal = input(0); agree: OutputEmitterRef = output(); @@ -42,12 +45,30 @@ export class PageComponent { this.disagree.emit(); } - imageLoad(event: Event) { + async imageLoad(event: Event) { const img = event.target as HTMLImageElement; this.imageLoading.set(false) this.naturalWidth.set(img.naturalWidth); this.naturalHeight.set(img.naturalHeight); + try { + const response = await fetch(img.src); + const blob = await response.blob(); + + if (blob.type === 'image/svg+xml' || blob.type === 'image/svg+xml-compressed') { + const text = await blob.text(); + const parser = new DOMParser(); + const svgDoc = parser.parseFromString(text, 'image/svg+xml'); + const svgElement: SVGSVGElement = svgDoc.documentElement as unknown as SVGSVGElement; + console.log(svgElement.viewBox.baseVal.width); + + this.naturalWidth.set(svgElement.viewBox.baseVal.width); + this.naturalHeight.set(svgElement.viewBox.baseVal.height); + } + } catch (e) { + console.warn('Failed to get bitmap size, fallback to naturalWidth/naturalHeight', e); + } + this.detectLongPage(this.naturalWidth(), this.naturalHeight()) }