Skip to content

Instantly share code, notes, and snippets.

@niujiabenben
Created July 18, 2019 15:01
Show Gist options
  • Save niujiabenben/9becf1847fd0477686caadbe5bc4aca0 to your computer and use it in GitHub Desktop.
Save niujiabenben/9becf1847fd0477686caadbe5bc4aca0 to your computer and use it in GitHub Desktop.
imdecode with crop
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