source_manager.cc (3225B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #include "lib/jpegli/decode.h" 7 #include "lib/jpegli/error.h" 8 #include "lib/jpegli/memory_manager.h" 9 10 namespace jpegli { 11 12 void init_mem_source(j_decompress_ptr cinfo) {} 13 void init_stdio_source(j_decompress_ptr cinfo) {} 14 15 void skip_input_data(j_decompress_ptr cinfo, long num_bytes /* NOLINT */) { 16 if (num_bytes <= 0) return; 17 while (num_bytes > 18 static_cast<long>(cinfo->src->bytes_in_buffer)) { // NOLINT 19 num_bytes -= cinfo->src->bytes_in_buffer; 20 (*cinfo->src->fill_input_buffer)(cinfo); 21 } 22 cinfo->src->next_input_byte += num_bytes; 23 cinfo->src->bytes_in_buffer -= num_bytes; 24 } 25 26 void term_source(j_decompress_ptr cinfo) {} 27 28 boolean EmitFakeEoiMarker(j_decompress_ptr cinfo) { 29 static constexpr uint8_t kFakeEoiMarker[2] = {0xff, 0xd9}; 30 cinfo->src->next_input_byte = kFakeEoiMarker; 31 cinfo->src->bytes_in_buffer = 2; 32 return TRUE; 33 } 34 35 constexpr size_t kStdioBufferSize = 64 << 10; 36 37 struct StdioSourceManager { 38 jpeg_source_mgr pub; 39 FILE* f; 40 uint8_t* buffer; 41 42 static boolean fill_input_buffer(j_decompress_ptr cinfo) { 43 auto* src = reinterpret_cast<StdioSourceManager*>(cinfo->src); 44 size_t num_bytes_read = fread(src->buffer, 1, kStdioBufferSize, src->f); 45 if (num_bytes_read == 0) { 46 return EmitFakeEoiMarker(cinfo); 47 } 48 src->pub.next_input_byte = src->buffer; 49 src->pub.bytes_in_buffer = num_bytes_read; 50 return TRUE; 51 } 52 }; 53 54 } // namespace jpegli 55 56 void jpegli_mem_src(j_decompress_ptr cinfo, const unsigned char* inbuffer, 57 unsigned long insize /* NOLINT */) { 58 if (cinfo->src && cinfo->src->init_source != jpegli::init_mem_source) { 59 JPEGLI_ERROR("jpegli_mem_src: a different source manager was already set"); 60 } 61 if (!cinfo->src) { 62 cinfo->src = jpegli::Allocate<jpeg_source_mgr>(cinfo, 1); 63 } 64 cinfo->src->next_input_byte = inbuffer; 65 cinfo->src->bytes_in_buffer = insize; 66 cinfo->src->init_source = jpegli::init_mem_source; 67 cinfo->src->fill_input_buffer = jpegli::EmitFakeEoiMarker; 68 cinfo->src->skip_input_data = jpegli::skip_input_data; 69 cinfo->src->resync_to_restart = jpegli_resync_to_restart; 70 cinfo->src->term_source = jpegli::term_source; 71 } 72 73 void jpegli_stdio_src(j_decompress_ptr cinfo, FILE* infile) { 74 if (cinfo->src && cinfo->src->init_source != jpegli::init_stdio_source) { 75 JPEGLI_ERROR("jpeg_stdio_src: a different source manager was already set"); 76 } 77 if (!cinfo->src) { 78 cinfo->src = reinterpret_cast<jpeg_source_mgr*>( 79 jpegli::Allocate<jpegli::StdioSourceManager>(cinfo, 1)); 80 } 81 auto* src = reinterpret_cast<jpegli::StdioSourceManager*>(cinfo->src); 82 src->f = infile; 83 src->buffer = jpegli::Allocate<uint8_t>(cinfo, jpegli::kStdioBufferSize); 84 src->pub.next_input_byte = src->buffer; 85 src->pub.bytes_in_buffer = 0; 86 src->pub.init_source = jpegli::init_stdio_source; 87 src->pub.fill_input_buffer = jpegli::StdioSourceManager::fill_input_buffer; 88 src->pub.skip_input_data = jpegli::skip_input_data; 89 src->pub.resync_to_restart = jpegli_resync_to_restart; 90 src->pub.term_source = jpegli::term_source; 91 }