Loading libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h +5 −4 Original line number Diff line number Diff line Loading @@ -36,11 +36,11 @@ public: JpegDecoder(); ~JpegDecoder(); /* * Decompresses JPEG image to raw image (YUV420planer or grey-scale) format. After calling * this method, call getDecompressedImage() to get the image. * Decompresses JPEG image to raw image (YUV420planer, grey-scale or RGBA) format. After * calling this method, call getDecompressedImage() to get the image. * Returns false if decompressing the image fails. */ bool decompressImage(const void* image, int length); bool decompressImage(const void* image, int length, bool decodeToRGBA = false); /* * Returns the decompressed raw image buffer pointer. This method must be called only after * calling decompressImage(). Loading Loading @@ -98,10 +98,11 @@ public: bool extractEXIF(const void* image, int length); private: bool decode(const void* image, int length); bool decode(const void* image, int length, bool decodeToRGBA); // Returns false if errors occur. bool decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, bool isSingleChannel); bool decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest); bool decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest); bool decompressSingleChannel(jpeg_decompress_struct* cinfo, const uint8_t* dest); // Process 16 lines of Y and 16 lines of U/V each time. // We must pass at least 16 scanlines according to libjpeg documentation. Loading libs/jpegrecoverymap/jpegdecoder.cpp +38 −10 Original line number Diff line number Diff line Loading @@ -93,7 +93,7 @@ JpegDecoder::JpegDecoder() { JpegDecoder::~JpegDecoder() { } bool JpegDecoder::decompressImage(const void* image, int length) { bool JpegDecoder::decompressImage(const void* image, int length, bool decodeToRGBA) { if (image == nullptr || length <= 0) { ALOGE("Image size can not be handled: %d", length); return false; Loading @@ -101,7 +101,7 @@ bool JpegDecoder::decompressImage(const void* image, int length) { mResultBuffer.clear(); mXMPBuffer.clear(); if (!decode(image, length)) { if (!decode(image, length, decodeToRGBA)) { return false; } Loading Loading @@ -140,7 +140,7 @@ size_t JpegDecoder::getDecompressedImageHeight() { return mHeight; } bool JpegDecoder::decode(const void* image, int length) { bool JpegDecoder::decode(const void* image, int length, bool decodeToRGBA) { jpeg_decompress_struct cinfo; jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length); jpegrerror_mgr myerr; Loading Loading @@ -210,15 +210,26 @@ bool JpegDecoder::decode(const void* image, int length) { mWidth = cinfo.image_width; mHeight = cinfo.image_height; if (decodeToRGBA) { if (cinfo.jpeg_color_space == JCS_GRAYSCALE) { // We don't intend to support decoding grayscale to RGBA return false; } // 4 bytes per pixel mResultBuffer.resize(cinfo.image_width * cinfo.image_height * 4); cinfo.out_color_space = JCS_EXT_RGBA; } else { if (cinfo.jpeg_color_space == JCS_YCbCr) { // 1 byte per pixel for Y, 0.5 byte per pixel for U+V mResultBuffer.resize(cinfo.image_width * cinfo.image_height * 3 / 2, 0); } else if (cinfo.jpeg_color_space == JCS_GRAYSCALE) { mResultBuffer.resize(cinfo.image_width * cinfo.image_height, 0); } cinfo.out_color_space = cinfo.jpeg_color_space; cinfo.raw_data_out = TRUE; } cinfo.dct_method = JDCT_IFAST; cinfo.out_color_space = cinfo.jpeg_color_space; jpeg_start_decompress(&cinfo); Loading Loading @@ -292,6 +303,9 @@ bool JpegDecoder::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, if (isSingleChannel) { return decompressSingleChannel(cinfo, dest); } if (cinfo->out_color_space == JCS_EXT_RGBA) return decompressRGBA(cinfo, dest); else return decompressYUV(cinfo, dest); } Loading Loading @@ -331,6 +345,20 @@ bool JpegDecoder::getCompressedImageParameters(const void* image, int length, return true; } bool JpegDecoder::decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest) { JSAMPLE* decodeDst = (JSAMPLE*) dest; uint32_t lines = 0; // TODO: use batches for more effectiveness while (lines < cinfo->image_height) { uint32_t ret = jpeg_read_scanlines(cinfo, &decodeDst, 1); if (ret == 0) { break; } decodeDst += cinfo->image_width * 4; lines++; } return lines == cinfo->image_height; } bool JpegDecoder::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) { Loading libs/jpegrecoverymap/recoverymap.cpp +20 −15 Original line number Diff line number Diff line Loading @@ -544,23 +544,37 @@ status_t RecoveryMap::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, if (compressed_jpegr_image == nullptr || dest == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; } // TODO: fill EXIF data (void) exif; if (request_sdr) { JpegDecoder jpeg_decoder; if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length, true)) { return ERROR_JPEGR_DECODE_ERROR; } jpegr_uncompressed_struct uncompressed_rgba_image; uncompressed_rgba_image.data = jpeg_decoder.getDecompressedImagePtr(); uncompressed_rgba_image.width = jpeg_decoder.getDecompressedImageWidth(); uncompressed_rgba_image.height = jpeg_decoder.getDecompressedImageHeight(); memcpy(dest->data, uncompressed_rgba_image.data, uncompressed_rgba_image.width * uncompressed_rgba_image.height * 4); dest->width = uncompressed_rgba_image.width; dest->height = uncompressed_rgba_image.height; return NO_ERROR; } jpegr_compressed_struct compressed_map; jpegr_metadata metadata; JPEGR_CHECK(extractRecoveryMap(compressed_jpegr_image, &compressed_map)); JpegDecoder jpeg_decoder; if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length)) { return ERROR_JPEGR_DECODE_ERROR; } JpegDecoder recovery_map_decoder; if (!recovery_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) { if (!recovery_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) { return ERROR_JPEGR_DECODE_ERROR; } Loading @@ -569,7 +583,6 @@ status_t RecoveryMap::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, map.width = recovery_map_decoder.getDecompressedImageWidth(); map.height = recovery_map_decoder.getDecompressedImageHeight(); jpegr_uncompressed_struct uncompressed_yuv_420_image; uncompressed_yuv_420_image.data = jpeg_decoder.getDecompressedImagePtr(); uncompressed_yuv_420_image.width = jpeg_decoder.getDecompressedImageWidth(); Loading @@ -580,15 +593,7 @@ status_t RecoveryMap::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, return ERROR_JPEGR_DECODE_ERROR; } if (request_sdr) { memcpy(dest->data, uncompressed_yuv_420_image.data, uncompressed_yuv_420_image.width*uncompressed_yuv_420_image.height *3 / 2); dest->width = uncompressed_yuv_420_image.width; dest->height = uncompressed_yuv_420_image.height; } else { JPEGR_CHECK(applyRecoveryMap(&uncompressed_yuv_420_image, &map, &metadata, dest)); } return NO_ERROR; } Loading Loading
libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h +5 −4 Original line number Diff line number Diff line Loading @@ -36,11 +36,11 @@ public: JpegDecoder(); ~JpegDecoder(); /* * Decompresses JPEG image to raw image (YUV420planer or grey-scale) format. After calling * this method, call getDecompressedImage() to get the image. * Decompresses JPEG image to raw image (YUV420planer, grey-scale or RGBA) format. After * calling this method, call getDecompressedImage() to get the image. * Returns false if decompressing the image fails. */ bool decompressImage(const void* image, int length); bool decompressImage(const void* image, int length, bool decodeToRGBA = false); /* * Returns the decompressed raw image buffer pointer. This method must be called only after * calling decompressImage(). Loading Loading @@ -98,10 +98,11 @@ public: bool extractEXIF(const void* image, int length); private: bool decode(const void* image, int length); bool decode(const void* image, int length, bool decodeToRGBA); // Returns false if errors occur. bool decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, bool isSingleChannel); bool decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest); bool decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest); bool decompressSingleChannel(jpeg_decompress_struct* cinfo, const uint8_t* dest); // Process 16 lines of Y and 16 lines of U/V each time. // We must pass at least 16 scanlines according to libjpeg documentation. Loading
libs/jpegrecoverymap/jpegdecoder.cpp +38 −10 Original line number Diff line number Diff line Loading @@ -93,7 +93,7 @@ JpegDecoder::JpegDecoder() { JpegDecoder::~JpegDecoder() { } bool JpegDecoder::decompressImage(const void* image, int length) { bool JpegDecoder::decompressImage(const void* image, int length, bool decodeToRGBA) { if (image == nullptr || length <= 0) { ALOGE("Image size can not be handled: %d", length); return false; Loading @@ -101,7 +101,7 @@ bool JpegDecoder::decompressImage(const void* image, int length) { mResultBuffer.clear(); mXMPBuffer.clear(); if (!decode(image, length)) { if (!decode(image, length, decodeToRGBA)) { return false; } Loading Loading @@ -140,7 +140,7 @@ size_t JpegDecoder::getDecompressedImageHeight() { return mHeight; } bool JpegDecoder::decode(const void* image, int length) { bool JpegDecoder::decode(const void* image, int length, bool decodeToRGBA) { jpeg_decompress_struct cinfo; jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length); jpegrerror_mgr myerr; Loading Loading @@ -210,15 +210,26 @@ bool JpegDecoder::decode(const void* image, int length) { mWidth = cinfo.image_width; mHeight = cinfo.image_height; if (decodeToRGBA) { if (cinfo.jpeg_color_space == JCS_GRAYSCALE) { // We don't intend to support decoding grayscale to RGBA return false; } // 4 bytes per pixel mResultBuffer.resize(cinfo.image_width * cinfo.image_height * 4); cinfo.out_color_space = JCS_EXT_RGBA; } else { if (cinfo.jpeg_color_space == JCS_YCbCr) { // 1 byte per pixel for Y, 0.5 byte per pixel for U+V mResultBuffer.resize(cinfo.image_width * cinfo.image_height * 3 / 2, 0); } else if (cinfo.jpeg_color_space == JCS_GRAYSCALE) { mResultBuffer.resize(cinfo.image_width * cinfo.image_height, 0); } cinfo.out_color_space = cinfo.jpeg_color_space; cinfo.raw_data_out = TRUE; } cinfo.dct_method = JDCT_IFAST; cinfo.out_color_space = cinfo.jpeg_color_space; jpeg_start_decompress(&cinfo); Loading Loading @@ -292,6 +303,9 @@ bool JpegDecoder::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, if (isSingleChannel) { return decompressSingleChannel(cinfo, dest); } if (cinfo->out_color_space == JCS_EXT_RGBA) return decompressRGBA(cinfo, dest); else return decompressYUV(cinfo, dest); } Loading Loading @@ -331,6 +345,20 @@ bool JpegDecoder::getCompressedImageParameters(const void* image, int length, return true; } bool JpegDecoder::decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest) { JSAMPLE* decodeDst = (JSAMPLE*) dest; uint32_t lines = 0; // TODO: use batches for more effectiveness while (lines < cinfo->image_height) { uint32_t ret = jpeg_read_scanlines(cinfo, &decodeDst, 1); if (ret == 0) { break; } decodeDst += cinfo->image_width * 4; lines++; } return lines == cinfo->image_height; } bool JpegDecoder::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) { Loading
libs/jpegrecoverymap/recoverymap.cpp +20 −15 Original line number Diff line number Diff line Loading @@ -544,23 +544,37 @@ status_t RecoveryMap::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, if (compressed_jpegr_image == nullptr || dest == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; } // TODO: fill EXIF data (void) exif; if (request_sdr) { JpegDecoder jpeg_decoder; if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length, true)) { return ERROR_JPEGR_DECODE_ERROR; } jpegr_uncompressed_struct uncompressed_rgba_image; uncompressed_rgba_image.data = jpeg_decoder.getDecompressedImagePtr(); uncompressed_rgba_image.width = jpeg_decoder.getDecompressedImageWidth(); uncompressed_rgba_image.height = jpeg_decoder.getDecompressedImageHeight(); memcpy(dest->data, uncompressed_rgba_image.data, uncompressed_rgba_image.width * uncompressed_rgba_image.height * 4); dest->width = uncompressed_rgba_image.width; dest->height = uncompressed_rgba_image.height; return NO_ERROR; } jpegr_compressed_struct compressed_map; jpegr_metadata metadata; JPEGR_CHECK(extractRecoveryMap(compressed_jpegr_image, &compressed_map)); JpegDecoder jpeg_decoder; if (!jpeg_decoder.decompressImage(compressed_jpegr_image->data, compressed_jpegr_image->length)) { return ERROR_JPEGR_DECODE_ERROR; } JpegDecoder recovery_map_decoder; if (!recovery_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) { if (!recovery_map_decoder.decompressImage(compressed_map.data, compressed_map.length)) { return ERROR_JPEGR_DECODE_ERROR; } Loading @@ -569,7 +583,6 @@ status_t RecoveryMap::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, map.width = recovery_map_decoder.getDecompressedImageWidth(); map.height = recovery_map_decoder.getDecompressedImageHeight(); jpegr_uncompressed_struct uncompressed_yuv_420_image; uncompressed_yuv_420_image.data = jpeg_decoder.getDecompressedImagePtr(); uncompressed_yuv_420_image.width = jpeg_decoder.getDecompressedImageWidth(); Loading @@ -580,15 +593,7 @@ status_t RecoveryMap::decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, return ERROR_JPEGR_DECODE_ERROR; } if (request_sdr) { memcpy(dest->data, uncompressed_yuv_420_image.data, uncompressed_yuv_420_image.width*uncompressed_yuv_420_image.height *3 / 2); dest->width = uncompressed_yuv_420_image.width; dest->height = uncompressed_yuv_420_image.height; } else { JPEGR_CHECK(applyRecoveryMap(&uncompressed_yuv_420_image, &map, &metadata, dest)); } return NO_ERROR; } Loading