1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * Provide a simple API around the Wuffs JPEG decoder
5 * Uses the heap (and lots of it) for the image-size specific
6 * work buffer, so ramstage-only.
13 #define WUFFS_CONFIG__AVOID_CPU_ARCH
14 #define WUFFS_CONFIG__MODULES
15 #define WUFFS_CONFIG__MODULE__BASE
16 #define WUFFS_CONFIG__MODULE__JPEG
17 #define WUFFS_CONFIG__STATIC_FUNCTIONS
18 #define WUFFS_IMPLEMENTATION
19 #include "../vendorcode/wuffs/wuffs-v0.4.c"
21 /* ~16K is big enough to move this off the stack */
22 static wuffs_jpeg__decoder dec
;
24 int jpeg_fetch_size(unsigned char *filedata
, size_t filesize
, unsigned int *width
,
27 if (!width
|| !height
) {
28 return JPEG_DECODE_FAILED
;
31 wuffs_base__status status
= wuffs_jpeg__decoder__initialize(
32 &dec
, sizeof(dec
), WUFFS_VERSION
, WUFFS_INITIALIZE__DEFAULT_OPTIONS
);
34 return JPEG_DECODE_FAILED
;
37 wuffs_base__image_config imgcfg
;
38 wuffs_base__io_buffer src
= wuffs_base__ptr_u8__reader(filedata
, filesize
, true);
39 status
= wuffs_jpeg__decoder__decode_image_config(&dec
, &imgcfg
, &src
);
41 return JPEG_DECODE_FAILED
;
44 *width
= wuffs_base__pixel_config__width(&imgcfg
.pixcfg
);
45 *height
= wuffs_base__pixel_config__height(&imgcfg
.pixcfg
);
50 int jpeg_decode(unsigned char *filedata
, size_t filesize
, unsigned char *pic
,
51 unsigned int width
, unsigned int height
, unsigned int bytes_per_line
,
54 if (!filedata
|| !pic
) {
55 return JPEG_DECODE_FAILED
;
57 /* Relatively arbitrary limit that shouldn't hurt anybody.
58 * 300M (10k*10k*3bytes/pixel) is already larger than our heap, so
59 * it's on the safe side.
60 * This avoids overflows when width or height are used for
61 * calculations in this function.
63 if ((width
> 10000) || (height
> 10000)) {
64 return JPEG_DECODE_FAILED
;
70 pixfmt
= WUFFS_BASE__PIXEL_FORMAT__BGR_565
;
73 pixfmt
= WUFFS_BASE__PIXEL_FORMAT__BGR
;
76 pixfmt
= WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL
;
79 return JPEG_DECODE_FAILED
;
82 wuffs_base__status status
= wuffs_jpeg__decoder__initialize(
83 &dec
, sizeof(dec
), WUFFS_VERSION
, WUFFS_INITIALIZE__DEFAULT_OPTIONS
);
85 return JPEG_DECODE_FAILED
;
88 wuffs_base__image_config imgcfg
;
89 wuffs_base__io_buffer src
= wuffs_base__ptr_u8__reader(filedata
, filesize
, true);
90 status
= wuffs_jpeg__decoder__decode_image_config(&dec
, &imgcfg
, &src
);
92 return JPEG_DECODE_FAILED
;
95 wuffs_base__pixel_config pixcfg
;
96 wuffs_base__pixel_config__set(&pixcfg
, pixfmt
, 0, width
, height
);
98 wuffs_base__pixel_buffer pixbuf
;
99 status
= wuffs_base__pixel_buffer__set_interleaved(
101 wuffs_base__make_table_u8(pic
, width
* (depth
/ 8), height
, bytes_per_line
),
102 wuffs_base__empty_slice_u8());
104 return JPEG_DECODE_FAILED
;
107 uint64_t workbuf_len_min_incl
= wuffs_jpeg__decoder__workbuf_len(&dec
).min_incl
;
108 uint8_t *workbuf_array
= malloc(workbuf_len_min_incl
);
109 if ((workbuf_array
== NULL
) && workbuf_len_min_incl
) {
110 return JPEG_DECODE_FAILED
;
113 wuffs_base__slice_u8 workbuf
=
114 wuffs_base__make_slice_u8(workbuf_array
, workbuf_len_min_incl
);
115 status
= wuffs_jpeg__decoder__decode_frame(&dec
, &pixbuf
, &src
,
116 WUFFS_BASE__PIXEL_BLEND__SRC
, workbuf
, NULL
);
121 return JPEG_DECODE_FAILED
;