Rotate is JPEG-only: PNG and WebP need a hard rotation to be supported
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 54/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- typescript
- Ambito
- frontend
Direzione di ricerca
Inizia da lib/private/Image.php:413, lib/private/Preview/Image.php:42 e lib/composables/useExportImage.ts, in particolare jpegSource() alla riga 112 e il risultato ridimensionato alla riga 235. Confronta state.rotation, orientedSize() e il flusso ENC0DABLE in @nextcloud/image-editor. Il lavoro è completato quando la rotazione PNG è disponibile solo se l’esportazione preserva i metadati e le dimensioni, rifiuta l’output ridimensionato e mantiene i metadati PNG durante l’esportazione.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
The rotate button being added for JPEG writes the Exif orientation tag: two bytes, no decode, no re-encode, nothing lost however many times it is pressed. PNG and WebP have no equivalent, so the button is hidden for them and those files cannot be rotated from the viewer at all.
Neither format carries an orientation the stack honours. lib/private/Image.php:413 in server returns -1 for anything that is not IMAGETYPE_JPEG, so fixOrientation() in lib/private/Preview/Image.php:42 never fires and previews would keep the old framing even if the file did carry a tag. PNG's eXIf chunk and WebP's EXIF chunk are both dead ends here.
The only route is a hard rotation: decode, turn the pixels, re-encode, upload. @nextcloud/image-editor already does exactly that (state.rotation, orientedSize(), ENCODABLE), so the work is not the rotation itself but deciding whether the result is worth writing.
I measured four 90° turns, decoding and re-encoding each time, on an 800x600 synthetic photo:
| format | PSNR after 4 turns, Chromium | Firefox | size after 1 turn |
|---|---|---|---|
| PNG | bit exact | bit exact | 292KB → 273KB |
| WebP, default quality | 40.4 dB | 43.0 dB | 14.4KB → 14.7KB |
| WebP, quality 1 | bit exact | bit exact | 14.4KB → 141KB |
PNG costs nothing in pixels. toBlob('image/webp', 1) turns out to be lossless in both engines, but a lossy source re-encoded that way grows 10x in Chromium and 3.4x in Firefox.
[!IMPORTANT]
The pixels are the easy part. What blocks PNG today is that the export drops metadata and can silently shrink the image.
jpegSource() (lib/composables/useExportImage.ts:112) returns null unless source and target are both JPEG, so carryMetadata never runs for a PNG: eXIf, ICC and text chunks are gone after a rotate. And the export is subject to the canvas cap, reporting downscaled at useExportImage.ts:235 when it had to work smaller. A rotate that quietly resizes someone's image is worse than no rotate.
So for PNG:
- carry PNG metadata through the export the way JPEG's is carried
- refuse the rotation, rather than writing it, when the export comes back
downscaled - then show the button for PNG
For WebP, a re-encode has to sniff the source first: RIFF VP8L means a lossless source that can be re-encoded losslessly at no cost, VP8 means a lossy one where the choice is generation loss or a 3-10x file. Worth doing only if someone asks for it.
GIF, BMP, ICO, SVG and the preview-backed mimes (HEIC, HEIF, TIFF) are out of scope: the editor cannot write any of them back in their own format.
- Lingua principale
- TypeScript
- Stelle
- 2
- Fork
- 0
- Merge medio
- 14h 1m
- PR unite (30g)
- 87
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di nextcloud-libraries/nextcloud-viewer
-
type: tests
Difficoltà 3/5 1-2 giorni Idoneità per principianti 68/100
nextcloud-libraries/nextcloud-viewer#111 ·
I maintainer di solito rispondono entro 1 giorno
-
type: enhancement
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
nextcloud-libraries/nextcloud-viewer#110 ·
I maintainer di solito rispondono entro 1 giorno
-
type: enhancement
Difficoltà 3/5 Mezza giornata Idoneità per principianti 68/100
nextcloud-libraries/nextcloud-viewer#108 ·
I maintainer di solito rispondono entro 1 giorno
-
type: enhancement
Difficoltà 3/5 1-2 giorni Idoneità per principianti 68/100
nextcloud-libraries/nextcloud-viewer#106 ·
I maintainer di solito rispondono entro 1 giorno
-
type: enhancement
Difficoltà 3/5 1-2 giorni Idoneità per principianti 65/100
nextcloud-libraries/nextcloud-viewer#105 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di nextcloud-libraries/nextcloud-viewer
Issue simili
-
area:ui effort:S enhancement priority:P2
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
QuantumNous/new-api#7839 ·
I maintainer di solito rispondono entro 1 giorno
-
good first issue maintenance
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
dark-princezz/stellar-hooks#1010 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
interledger/rhyza#352 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno