1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
#include "jpeg_utils.h"
#include <stdexcept>
#include <cstring>
#include <csetjmp>
extern "C"
{
#include "libs/jpeg/jpeglib.h"
}
// #include "libs/openjp2/openjpeg.h"
namespace image
{
struct jpeg_error_struct
{
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
static void libjpeg_error_func(j_common_ptr cinfo)
{
longjmp(((jpeg_error_struct *)cinfo->err)->setjmp_buffer, 1);
}
static void libjpeg_error_func_ignore(j_common_ptr /*cinfo*/)
{
// longjmp(((jpeg_error_struct *)cinfo->err)->setjmp_buffer, 1);
}
Image decompress_jpeg(uint8_t *data, int length, bool ignore_errors)
{
Image img;
unsigned char *jpeg_decomp = NULL;
// Huge thanks to https://gist.github.com/PhirePhly/3080633
jpeg_error_struct jerr;
jpeg_decompress_struct cinfo;
// Init
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = ignore_errors ? libjpeg_error_func_ignore : libjpeg_error_func;
if (setjmp(jerr.setjmp_buffer))
{
// Free memory
delete[] jpeg_decomp;
return img;
}
jpeg_create_decompress(&cinfo);
// Parse and start decompressing
jpeg_mem__src(&cinfo, data, length);
jpeg_read_header(&cinfo, FALSE);
jpeg_start_decompress(&cinfo);
// Init output buffer
jpeg_decomp = new unsigned char[cinfo.image_width * cinfo.image_height];
// Decompress
while (cinfo.output_scanline < cinfo.output_height)
{
unsigned char *buffer_array[1];
buffer_array[0] = jpeg_decomp + (cinfo.output_scanline) * cinfo.image_width;
jpeg_read_scanlines(&cinfo, buffer_array, 1);
}
// Cleanup
// jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
// Init CImg image
img = Image(8, cinfo.image_width, cinfo.image_height, 1);
// Copy over
for (int i = 0; i < (int)cinfo.image_width * (int)cinfo.image_height; i++)
img.set(i, jpeg_decomp[i]);
// Free memory
delete[] jpeg_decomp;
return img;
}
/*Image<uint16_t> decompress_j2k_openjp2(uint8_t *data, int length)
{
Image<uint16_t> img;
// Init decoder parameters
opj_dparameters_t core;
memset(&core, 0, sizeof(opj_dparameters_t));
opj_set_default_decoder_parameters(&core);
// Set input buffer info struct
opj_buffer_info bufinfo;
bufinfo.buf = data;
bufinfo.cur = data;
bufinfo.len = length;
// Setup image, stream and codec
opj_image_t *image = NULL;
opj_stream_t *l_stream = opj_stream_create_buffer_stream(&bufinfo, true);
opj_codec_t *l_codec = opj_create_decompress(OPJ_CODEC_J2K);
// Check we could open the stream
if (!l_stream)
{
opj_destroy_codec(l_codec);
return img;
}
// Setup decoder
if (!opj_setup_decoder(l_codec, &core))
{
opj_stream_destroy(l_stream);
opj_destroy_codec(l_codec);
return img;
}
// Read header
if (!opj_read_header(l_stream, l_codec, &image))
{
opj_stream_destroy(l_stream);
opj_destroy_codec(l_codec);
opj_image_destroy(image);
return img;
}
// Decode image
if (!(opj_decode(l_codec, l_stream, image) &&
opj_end_decompress(l_codec, l_stream)))
{
opj_destroy_codec(l_codec);
opj_stream_destroy(l_stream);
opj_image_destroy(image);
return img;
}
// Parse into CImg
img = Image<uint16_t>(image->x1, image->y1, 1);
for (int i = 0; i < int(image->x1 * image->y1); i++)
img[i] = image->comps[0].data[i];
// Free everything up
opj_destroy_codec(l_codec);
opj_stream_destroy(l_stream);
opj_image_destroy(image);
return img;
}*/
}
|