1 /* SPDX-License-Identifier: GPL-2.0-only */
4 * Provide a simple API around the Wuffs JPEG decoder.
11 #define WUFFS_CONFIG__AVOID_CPU_ARCH
12 #define WUFFS_CONFIG__MODULES
13 #define WUFFS_CONFIG__MODULE__BASE
14 #define WUFFS_CONFIG__MODULE__JPEG
15 #define WUFFS_CONFIG__STATIC_FUNCTIONS
16 #define WUFFS_IMPLEMENTATION
17 #include "../vendorcode/wuffs/wuffs-v0.4.c"
19 /* ~16K is big enough to move this off the stack */
20 static wuffs_jpeg__decoder dec
;
22 const char *jpeg_fetch_size(unsigned char *filedata
, size_t filesize
, unsigned int *width
,
25 if (!width
|| !height
) {
29 wuffs_base__status status
= wuffs_jpeg__decoder__initialize(
30 &dec
, sizeof(dec
), WUFFS_VERSION
, WUFFS_INITIALIZE__DEFAULT_OPTIONS
);
35 wuffs_base__image_config imgcfg
;
36 wuffs_base__io_buffer src
= wuffs_base__ptr_u8__reader(filedata
, filesize
, true);
37 status
= wuffs_jpeg__decoder__decode_image_config(&dec
, &imgcfg
, &src
);
42 *width
= wuffs_base__pixel_config__width(&imgcfg
.pixcfg
);
43 *height
= wuffs_base__pixel_config__height(&imgcfg
.pixcfg
);
48 const char *jpeg_decode(unsigned char *filedata
, size_t filesize
, unsigned char *pic
,
49 unsigned int width
, unsigned int height
, unsigned int bytes_per_line
,
52 if (!filedata
|| !pic
) {
55 /* Relatively arbitrary limit that shouldn't hurt anybody.
56 * 300M (10k*10k*3bytes/pixel) is already larger than our heap, so
57 * it's on the safe side.
58 * This avoids overflows when width or height are used for
59 * calculations in this function.
61 if ((width
> 10000) || (height
> 10000)) {
68 pixfmt
= WUFFS_BASE__PIXEL_FORMAT__BGR_565
;
71 pixfmt
= WUFFS_BASE__PIXEL_FORMAT__BGR
;
74 pixfmt
= WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL
;
80 wuffs_base__status status
= wuffs_jpeg__decoder__initialize(
81 &dec
, sizeof(dec
), WUFFS_VERSION
, WUFFS_INITIALIZE__DEFAULT_OPTIONS
);
86 /* Opting in to lower quality means that we can pass an empty slice as the
87 * "work buffer" argument to wuffs_jpeg__decoder__decode_frame below.
89 * Decoding progressive (not sequential) JPEGs would still require dynamic
90 * memory allocation (and the amount of work buffer required depends on the
91 * image dimensions), but we choose to just reject progressive JPEGs. It is
92 * simpler than sometimes calling malloc (which can fail, especially for
93 * large allocations) and free.
95 * More commentary about these quirks is at
96 * https://github.com/google/wuffs/blob/beaf45650085a16780b5f708b72daaeb1aa865c8/std/jpeg/decode_quirks.wuffs
98 wuffs_jpeg__decoder__set_quirk(
99 &dec
, WUFFS_BASE__QUIRK_QUALITY
,
100 WUFFS_BASE__QUIRK_QUALITY__VALUE__LOWER_QUALITY
);
101 wuffs_jpeg__decoder__set_quirk(
102 &dec
, WUFFS_JPEG__QUIRK_REJECT_PROGRESSIVE_JPEGS
, 1);
104 wuffs_base__image_config imgcfg
;
105 wuffs_base__io_buffer src
= wuffs_base__ptr_u8__reader(filedata
, filesize
, true);
106 status
= wuffs_jpeg__decoder__decode_image_config(&dec
, &imgcfg
, &src
);
111 wuffs_base__pixel_config pixcfg
;
112 wuffs_base__pixel_config__set(&pixcfg
, pixfmt
, 0, width
, height
);
114 wuffs_base__pixel_buffer pixbuf
;
115 status
= wuffs_base__pixel_buffer__set_interleaved(
117 wuffs_base__make_table_u8(pic
, width
* (depth
/ 8), height
, bytes_per_line
),
118 wuffs_base__empty_slice_u8());
123 status
= wuffs_jpeg__decoder__decode_frame(&dec
, &pixbuf
, &src
,
124 WUFFS_BASE__PIXEL_BLEND__SRC
,
125 wuffs_base__empty_slice_u8(), NULL
);