blob: 7747007fbe11a7e3d0fa23c3bef0d56db437bed8 [file] [log] [blame]
// Copyright 2023 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------
// Uncomment one of these #define lines to test and bench alternative mimic
// libraries (stb_image) instead of libjpeg.
//
// These are collectively referred to as
// WUFFS_MIMICLIB_USE_XXX_INSTEAD_OF_LIBJPEG.
//
// #define WUFFS_MIMICLIB_USE_STB_IMAGE_INSTEAD_OF_LIBJPEG 1
// -------------------------------- WUFFS_MIMICLIB_USE_XXX_INSTEAD_OF_LIBJPEG
#if defined(WUFFS_MIMICLIB_USE_STB_IMAGE_INSTEAD_OF_LIBJPEG)
#define WUFFS_MIMICLIB_JPEG_DOES_NOT_EXACTLY_MATCH_LIBJPEG 1
#define mimic_jpeg_decode mimic_stb_decode
#include "./stb.c"
// -------------------------------- WUFFS_MIMICLIB_USE_XXX_INSTEAD_OF_LIBJPEG
#else
#include "jpeglib.h"
const char* //
mimic_jpeg_decode(uint64_t* n_bytes_out,
wuffs_base__io_buffer* dst,
uint32_t wuffs_initialize_flags,
wuffs_base__pixel_format pixfmt,
uint32_t* quirks_ptr,
size_t quirks_len,
wuffs_base__io_buffer* src) {
wuffs_base__io_buffer dst_fallback =
wuffs_base__slice_u8__writer(g_mimiclib_scratch_slice_u8);
if (!dst) {
dst = &dst_fallback;
}
const char* ret = NULL;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_mem_src(&cinfo, wuffs_base__io_buffer__reader_pointer(src),
wuffs_base__io_buffer__reader_length(src));
if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) {
ret = "mimic_jpeg_decode: jpeg_read_header failed";
goto cleanup0;
}
switch (pixfmt.repr) {
case WUFFS_BASE__PIXEL_FORMAT__Y:
cinfo.out_color_space = JCS_GRAYSCALE;
break;
case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
cinfo.out_color_space = JCS_EXT_BGRA;
break;
default:
ret = "mimic_jpeg_decode: unsupported pixfmt";
goto cleanup0;
}
jpeg_start_decompress(&cinfo);
size_t stride =
cinfo.output_width *
((size_t)(wuffs_base__pixel_format__bits_per_pixel(&pixfmt) / 8u));
while (cinfo.output_scanline < cinfo.output_height) {
if (wuffs_base__io_buffer__writer_length(dst) < stride) {
ret = "mimic_jpeg_decode: image is too large";
goto cleanup0;
}
JSAMPLE* scanlines[1] = {(void*)wuffs_base__io_buffer__writer_pointer(dst)};
if (jpeg_read_scanlines(&cinfo, scanlines, 1)) {
dst->meta.wi += stride;
if (n_bytes_out) {
*n_bytes_out += stride;
}
}
}
jpeg_finish_decompress(&cinfo);
cleanup0:;
jpeg_destroy_decompress(&cinfo);
return ret;
}
#endif
// -------------------------------- WUFFS_MIMICLIB_USE_XXX_INSTEAD_OF_LIBJPEG