in src/jpegUtil.cpp [49:118]
bool decodeJpeg(const int64_t width, const int64_t height,
const J_COLOR_SPACE colorSpace, const uint8_t* rawBuffer,
const uint64_t rawBufferSize, uint8_t *returnMemoryBuffer,
const int64_t returnMemoryBufferSize) {
if (returnMemoryBufferSize < 4 * width * height) {
// size of memory buffer passed in is to small
BOOST_LOG_TRIVIAL(error) << "Error insufficent memory hold "
"decoded image.";
return false;
}
struct jpeg_decompress_struct cinfo;
jpegErrorManager jerr;
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpegErrorExit;
// Establish the setjmp return context for my_error_exit to use.
if (setjmp(jerr.setjmp_buffer)) {
// If we get here, the JPEG code has signaled an error.
BOOST_LOG_TRIVIAL(error) << "Error occured decompressing jpeg";
jpeg_destroy_decompress(&cinfo);
return false;
}
jpeg_create_decompress(&cinfo);
jpeg_mem_src(&cinfo, rawBuffer, rawBufferSize);
int rc = jpeg_read_header(&cinfo, TRUE);
cinfo.jpeg_color_space = colorSpace;
if (rc == 0) {
BOOST_LOG_TRIVIAL(error) << "Not valid jpeg.";
jpeg_destroy_decompress(&cinfo);
return false;
}
jpeg_start_decompress(&cinfo);
const int row_stride = width * 3;
const int bgrBufferSize = height * row_stride;
std::unique_ptr<uint8_t[]> bmp_buffer =
std::make_unique<uint8_t[]>(bgrBufferSize);
while (cinfo.output_scanline < cinfo.output_height) {
unsigned char *buffer_array[1];
buffer_array[0] = bmp_buffer.get() + (cinfo.output_scanline) * row_stride;
jpeg_read_scanlines(&cinfo, buffer_array, 1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
std::unique_ptr<uint8_t[]> abgrBuffer;
uint64_t sourceCounter = 0;
uint64_t destCounter = 0;
const uint64_t sourceSize = height * width * 3;
// Aperio imaging encoded with colorspace == JCS_RGB
// requires colorspace setting for correct decoding.
// imaging is BGR. Does not require byte reording.
if (returnMemoryBuffer == nullptr) {
return true;
}
for (uint64_t sourceCounter = 0;
sourceCounter < sourceSize;
sourceCounter += 3) {
// color generated in BGR ordering
const uint8_t blue = bmp_buffer[sourceCounter];
const uint8_t green = bmp_buffer[sourceCounter+1];
const uint8_t red = bmp_buffer[sourceCounter+2];
returnMemoryBuffer[destCounter] = blue;
returnMemoryBuffer[destCounter+1] = green;
returnMemoryBuffer[destCounter+2] = red;
returnMemoryBuffer[destCounter+3] = 0xff; // alpha
destCounter += 4;
}
return true;
}