File indexing completed on 2025-01-26 04:10:56

0001 /*
0002  *  SPDX-FileCopyrightText: 2009 Adrian Page <adrian@pagenet.plus.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_jpeg_source.h"
0008 
0009 #include <jerror.h>
0010 
0011 #include <QIODevice>
0012 
0013 #include "kis_debug.h"
0014 
0015 namespace
0016 {
0017 
0018 const qint64 INPUT_BUFFER_SIZE = 4096;
0019 
0020 struct KisJPEGSourceManager : public jpeg_source_mgr
0021 {
0022     QIODevice* input;
0023     JOCTET* buffer;
0024     bool anyDataReceived;
0025 };
0026 
0027 typedef KisJPEGSourceManager* KisJPEGSourceManagerPtr;
0028 
0029 extern "C"
0030 {
0031 
0032 void init_source(j_decompress_ptr cinfo)
0033 {
0034     KisJPEGSourceManagerPtr src = (KisJPEGSourceManagerPtr)cinfo->src;
0035     src->anyDataReceived = false;
0036 }
0037 
0038 boolean fill_input_buffer(j_decompress_ptr cinfo)
0039 {
0040     KisJPEGSourceManagerPtr src = (KisJPEGSourceManagerPtr)cinfo->src;
0041     qint64 numBytesRead = src->input->read(reinterpret_cast<char*>(src->buffer), INPUT_BUFFER_SIZE);
0042 
0043     if (numBytesRead <= 0) {
0044         if (!src->anyDataReceived)  {
0045             /* Treat empty input file as fatal error */
0046             ERREXIT(cinfo, JERR_INPUT_EMPTY);
0047         }
0048         WARNMS(cinfo, JWRN_JPEG_EOF);
0049 
0050         /* Insert a fake EOI marker */
0051         src->buffer[0] = (JOCTET)0xFF;
0052         src->buffer[1] = (JOCTET)JPEG_EOI;
0053         numBytesRead = 2;
0054     }
0055 
0056     src->next_input_byte = src->buffer;
0057     src->bytes_in_buffer = numBytesRead;
0058     src->anyDataReceived = true;
0059 
0060     return (boolean)true;
0061 }
0062 
0063 void skip_input_data(j_decompress_ptr cinfo, long numBytes)
0064 {
0065     KisJPEGSourceManagerPtr src = (KisJPEGSourceManagerPtr)cinfo->src;
0066 
0067     if (numBytes > 0) {
0068         while (numBytes > (long)src->bytes_in_buffer) {
0069             numBytes -= (long)src->bytes_in_buffer;
0070             (void)fill_input_buffer(cinfo);
0071         }
0072         src->next_input_byte += (size_t)numBytes;
0073         src->bytes_in_buffer -= (size_t)numBytes;
0074     }
0075 }
0076 
0077 void term_source(j_decompress_ptr cinfo)
0078 {
0079     Q_UNUSED(cinfo);
0080 }
0081 
0082 }
0083 }
0084 
0085 namespace KisJPEGSource
0086 {
0087 
0088 void setSource(j_decompress_ptr cinfo, QIODevice* inputDevice)
0089 {
0090     KisJPEGSourceManagerPtr src = 0;
0091 
0092     if (cinfo->src == 0) {
0093         cinfo->src = (struct jpeg_source_mgr*)
0094                      (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT,
0095                                                  sizeof(KisJPEGSourceManager));
0096         src = (KisJPEGSourceManagerPtr)cinfo->src;
0097         src->buffer = (JOCTET*)
0098                       (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT,
0099                                                   INPUT_BUFFER_SIZE*sizeof(JOCTET));
0100     }
0101 
0102     src = (KisJPEGSourceManagerPtr)cinfo->src;
0103     src->init_source = init_source;
0104     src->fill_input_buffer = fill_input_buffer;
0105     src->skip_input_data = skip_input_data;
0106     src->resync_to_restart = jpeg_resync_to_restart;
0107     src->term_source = term_source;
0108     src->input = inputDevice;
0109     src->bytes_in_buffer = 0;
0110     src->next_input_byte = 0;
0111 }
0112 
0113 }
0114