Created
July 18, 2019 15:01
-
-
Save niujiabenben/9becf1847fd0477686caadbe5bc4aca0 to your computer and use it in GitHub Desktop.
imdecode with crop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern "C" { | |
#include <jerror.h> | |
#include <jpeglib.h> | |
#include <setjmp.h> | |
} | |
struct JpegErrorManager { | |
struct jpeg_error_mgr pub; | |
jmp_buf setjmp_buffer; | |
}; | |
static void JpegErrorExit(j_common_ptr cinfo) { | |
char error_message[JMSG_LENGTH_MAX] = {0}; | |
JpegErrorManager* myerr = (JpegErrorManager*) cinfo->err; | |
(*(cinfo->err->format_message))(cinfo, error_message); | |
LOG(ERROR) << error_message; | |
longjmp(myerr->setjmp_buffer, 1); | |
} | |
//// 这里错误处理参考: | |
//// https://stackoverflow.com/questions/19857766/error-handling-in-libjpeg | |
cv::Mat CropDecodeJPEG(const std::vector<unsigned char>& content, | |
const int crop_width, | |
const int crop_height) { | |
struct jpeg_decompress_struct cinfo; | |
struct JpegErrorManager jerr; | |
cinfo.err = jpeg_std_error(&jerr.pub); | |
jerr.pub.error_exit = JpegErrorExit; | |
if (setjmp(jerr.setjmp_buffer)) { | |
jpeg_destroy_decompress(&cinfo); | |
return cv::Mat(); | |
} | |
jpeg_create_decompress(&cinfo); | |
jpeg_mem_src(&cinfo, content.data(), content.size()); | |
jpeg_read_header(&cinfo, TRUE); | |
cinfo.out_color_space = JCS_EXT_BGR; | |
jpeg_start_decompress(&cinfo); | |
const int width = cinfo.output_width; | |
const int height = cinfo.output_height; | |
const int channels = cinfo.out_color_components; | |
CHECK_GE(width, crop_width); | |
CHECK_GE(height, crop_height); | |
CHECK_EQ(channels, 3); | |
const int offset_x = (width - crop_width) / 2; | |
const int offset_y = (height - crop_height) / 2; | |
cv::Mat image(crop_height, crop_width, CV_8UC3); | |
if (offset_x > 0) { | |
unsigned int temp_offset_x = offset_x; | |
unsigned int temp_width = crop_width; | |
jpeg_crop_scanline(&cinfo, &temp_offset_x, &temp_width); | |
CHECK_EQ(temp_offset_x, offset_x); | |
CHECK_EQ(temp_width, crop_width); | |
} | |
uchar* temp = image.data; | |
if (offset_y > 0) { | |
jpeg_skip_scanlines(&cinfo, offset_y); | |
} | |
while(cinfo.output_scanline < height - offset_y) { | |
if (jpeg_read_scanlines(&cinfo, &temp, 1) == 1) { | |
temp += crop_width * channels; | |
} | |
} | |
if (offset_y > 0) { | |
jpeg_skip_scanlines(&cinfo, offset_y); | |
} | |
jpeg_finish_decompress(&cinfo); | |
jpeg_destroy_decompress(&cinfo); | |
return image; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment