Commit graph

16 commits

Author SHA1 Message Date
Michael Giacomelli
142a6fbb39 jpeg: decode RGB images
Both decoders treated every 3-component image as YCbCr, so RGB JPEGs
(as written by cjpeg -rgb, and by some Adobe software) came out with
wrong colours.

Decide the colour space as libjpeg does: a JFIF marker means YCbCr;
otherwise the transform flag of an Adobe APP14 marker decides (0 is
RGB); otherwise component IDs 'R', 'G', 'B' mean RGB.

Core loader: on colour targets R, G and B are stored in place in the
row buffer and the YUV conversion is skipped. Greyscale builds now
also decode G and B for RGB and combine them into luma per block,
which needs every component to be one block per MCU; other RGB
layouts are rejected there.

Plugin: RGB needs one block per MCU for every component, otherwise it
is rejected (colour targets fall back to jpegp). Colour builds convert
the R, G and B planes to YCbCr in place after decoding, so display and
greyscale view modes are unchanged; greyscale builds combine R, G and
B into luma per block as the core does.

Code size on the e200: core loader +351 bytes, plugin decoder +603
bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ib24a0b7690ca4c00b3ac01b2f511309efeac5975
2026-10-02 08:23:46 -04:00
Michael Giacomelli
1488b30c62 imageviewer/jpeg: reject damaged files safely
Damaged and truncated JPEGs could make the image viewer read or write
outside its buffers:

- process_markers() trusted segment lengths, and Huffman table symbol
  counts, so a segment running past the end of the file was parsed
  from whatever memory followed it. Check that each marker segment,
  and each Huffman table in it, lies within the file.
- A file without a complete SOS header was decoded from a NULL entropy
  data pointer, as load_image() checked only for DQT and SOF. Require
  SOS as well.
- img_mem() computed the image size in an int, which overflows for a
  large image (a 65535x65535 file came out as 0), so the decode wrote
  far past the buffer. Compute it in 64 bits and saturate.

Found with the jpeg-conformance files of the imazen codec-corpus,
which include truncated files and files from fuzzing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I1e2a9a4346fd1c0e34b0813267c6317dbf704bc7
2026-10-01 19:32:57 -04:00
Michael Giacomelli
e32bfaadb1 jpeg: reject layouts the decoders cannot handle
Both JPEG decoders accepted several baseline layouts they cannot decode
and produced garbage without an error:

- chroma with sampling factors other than 1x1 (the MCU layout is chosen
  from luma alone, so any other chroma layout desynchronises)
- files written as more than one scan, where the first scan does not
  hold every component (it was decoded as if it were interleaved)
- scans whose components are not in frame order
- a height of 0 in SOF, to be defined later by a DNL marker

Reject these in process_markers(). The imageviewer then falls back to
the jpegp decoder on colour targets, which handles all of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ia3373f2b934eef6e3f354b4d064faf2d89868050
2026-10-01 13:22:53 -04:00
Michael Giacomelli
0e50ed3c43 jpeg: use the quantization table each component selects
Both JPEG decoders ignored the Tq selector in the frame header and
always dequantized luma with table 0 and chroma with table 1. Files
with a single shared table multiplied chroma by an empty table, and
files with separate Cb and Cr tables used the wrong one for Cr.

imageviewer/jpeg: build one dequantization table per component (3
instead of 2, +256 bytes) from the table it selects. tab_membership is
no longer used and is removed.

Core loader: the raw tables are pre-scaled in place for the IDCT, and
luma and chroma can use different IDCT scales. fix_quant_tables() now
maps each component to a table slot, copying a table that luma and
chroma share at different scales to a slot no component uses (there are
4 slots and at most 3 components, so one is always free), and rewrites
quanttable_select to that slot. No extra memory.

Selectors above 3 are rejected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: If04c61fb0fef95da11d98d9918ea7225d8a440b0
2026-10-01 13:13:40 -04:00
Michael Giacomelli
b897766a7a jpeg: use the Huffman tables the scan header selects
Both JPEG decoders ignored the DC/AC table selectors in the SOS header
and always decoded luma with tables 0 and chroma with tables 1, the
layout libjpeg writes by default. Files where all components share
table 0, or where the slots are assigned differently, decoded to noise.

Look up each component's tables from its selectors instead. Baseline
JPEG only allows tables 0 and 1, which both decoders already hold, so
this needs no extra memory; selectors above 1 are rejected. In the core
loader tab_membership is no longer used and is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ie1ec407ddecf1256fef410b1256b97af412fb194
2026-10-01 13:03:53 -04:00
Michael Giacomelli
c12f6ebacd imageviewer/jpeg: don't read past the end of entropy data
The bit reader refilled from the input buffer without checking its end.
The end-of-data check in the decode loops only runs once per MCU row, so
a stream that desynchronises (or is truncated) read past the end of the
file buffer for the rest of the row. Return zero bytes past the end
instead; the pointer still advances so the per-row check stops the
decode.

Found with AddressSanitizer on a JPEG whose chroma is sampled more
densely than its luma.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iaada1bc3cbf62b18f10fb2377c12d4d5cb9524de
2026-10-01 11:57:40 -04:00
Michael Giacomelli
2bb498b963 jpeg: fix decoding of grayscale images with 2x2 sampling
A single-component (grayscale) scan is non-interleaved, so its MCU is
one 8x8 block regardless of the sampling factors in the frame header
(T.81 A.2.2). Some encoders write H=2,V=2 for the lone component, which
sent both the imageviewer plugin decoder and the core loader down the
4:2:0 path: 6 blocks per 16x16 MCU, the image treated as colour, and
the entropy data overrun.

Force 1x1 sampling for single-component frames when parsing SOF0 so
these images use the 4:4:4 layout with one block per MCU. Also add the
missing else in fix_headers() in the core loader, matching the plugin.

Tested on a Sansa e200 with both the plugin and the core loader, and
the plugin in the e200 simulator and built for PC and for ARM (qemu).

Fixes FS#13749.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iac2f925aab8cd602930470dca5da7dfb44e15961
2026-09-28 22:38:41 -04:00
Michael Giacomelli
89c38484ea fix missing else in jpeg decoder.
This didn't actually break anything since the error case wasn't
handled anyway but not a good idea to leave alone.
2026-09-28 22:38:41 -04:00
Solomon Peachy
d54b9e6f8d chore: Get rid of *all* vestigal CVS '$Id:$' tags
Change-Id: I35c13a9768c582e4851aa252dd3ea5c89f760c8c
2026-06-01 16:01:18 -04:00
Solomon Peachy
6f5760b41a jpeg: Silence -Wshift-negative-value warnings
These are all from upstream code, so just force-ignore the warnings

Change-Id: I9936e1cb79636b0bfee5dd4db0c98a06792d2f69
2025-04-22 09:43:40 -04:00
Aidan MacDonald
cf3fa437fc Remove unhelpful unsigned casting trick
Change-Id: Ice86f060974c51bbaf051ed8c5a369ce80ecfe15
2021-08-07 15:52:18 +00:00
Solomon Peachy
092c340a20 [1/4] Remove SH support and all archos targets
This removes all code specific to SH targets

Change-Id: I7980523785d2596e65c06430f4638eec74a06061
2020-07-24 21:20:13 +00:00
Boris Gjenero
26697d0891 Fix FS#12981 JPEG decoding problem when entropy data starts with FF
This changes JPEG fill and invalid byte handling to be like
mozjpeg, and bases entropy data start on SOS marker location.

Thanks to Stefan Waldmann and Dean Tersigni for reporting.

Change-Id: I3c79cc6ac8d714fdc75c12b57ba427d611c99519
Chaange-Id: Ibc7c17d38d5be63642bdaf6adfd6acc2a6cf4450
2016-04-01 19:29:41 +02:00
Bertrik Sikken
a7a78b3b52 Fix warnings from r31453
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31454 a1c6a512-1295-4272-9138-f99709370657
2011-12-28 11:47:35 +00:00
Bertrik Sikken
d2cdd80f5c plugins: another round of making local things static and adding missing #includes
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31453 a1c6a512-1295-4272-9138-f99709370657
2011-12-28 11:32:13 +00:00
Teruaki Kawashima
5bd0823749 jpeg,png: Merge user interface code and plugin entry point of the two plugins (part of FS#6321).
* Created new directory, imageviewer/ and moved both jpeg/ and png/ under it.
- this still doesn't merge the two plugins. i.e. both jpeg.rock and png.rock will be made for color targets.
- I'm thinking to merge the two plugins to single image viewer later.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24272 a1c6a512-1295-4272-9138-f99709370657
2010-01-18 12:46:19 +00:00
Renamed from apps/plugins/jpeg/jpeg_decoder.c (Browse further)