看着libjpeg的文档说明,写了个例子,备忘。
extern "C" {
#include "jpeglib.h"
}
class Sbuffer
{
public:
Sbuffer();
~Sbuffer();
bool SetSize(int size);
inline unsigned char* GetBuffer(){ return buffer_; }
private:
int size_;
unsigned char* buffer_;
};
Sbuffer::Sbuffer():size_(0), buffer_(NULL){}
Sbuffer::~Sbuffer()
{
if(buffer_){
delete[] buffer_;
buffer_ = NULL;
size_ = 0;
}
}
bool Sbuffer::SetSize(int size)
{
if(size > size_){
if(buffer_){
delete[] buffer_;
buffer_ = NULL;
}
size_ = 0;
buffer_ = new unsigned char[size];
if(NULL == buffer_){
TRACE("Sbuffer::SetSize new failed");
return false;
}
size_ = size;
return true;
}
return true;
}
static int reduce_jpeg(const char* filename)
{
int image_new_width = 0;
int image_new_height = 0;
int image_new_components = 0;
J_COLOR_SPACE image_new_colorspace = JCS_UNKNOWN;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
FILE* infile;
if((infile = fopen(filename, "rb")) == NULL) {
return -1;
}
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
//get jpeg info
jpeg_read_header(&cinfo, TRUE);
//set parameters
cinfo.scale_num = 1;
cinfo.scale_denom = 2;//reduce image 1/2
jpeg_start_decompress(&cinfo);
//restore
image_new_width = cinfo.output_width;
image_new_height = cinfo.output_height;
image_new_components = cinfo.output_components;
image_new_colorspace = cinfo.out_color_space;
int buffer_len = cinfo.output_width * cinfo.output_components * cinfo.output_height;
static Sbuffer s_buffer;
s_buffer.SetSize(buffer_len * sizeof(JSAMPLE));
JSAMPLE* image_buffer = static_cast<JSAMPLE*>(s_buffer.GetBuffer());
if(NULL == image_buffer){
fclose(infile);
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
return -1;
}
memset(image_buffer, 0, buffer_len*sizeof(JSAMPLE));
int row_stride = cinfo.output_width * cinfo.output_components;
JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
JSAMPLE* image_buffer_cur_pos = image_buffer;
while(cinfo.output_scanline < cinfo.output_height){
jpeg_read_scanlines(&cinfo, buffer , 1);
memcpy((void*)image_buffer_cur_pos, (const void*)buffer[0], row_stride*sizeof(JSAMPLE) );
image_buffer_cur_pos += row_stride;
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
///////////////////////////////////////////
//save
struct jpeg_compress_struct cinfo_save;
struct jpeg_error_mgr jerr_save;
cinfo_save.err = jpeg_std_error(&jerr_save);
FILE* outfile = fopen(filename, "wb");
if(NULL == outfile){
return -1;
}
jpeg_create_compress(&cinfo_save);
jpeg_stdio_dest(&cinfo_save, outfile);
cinfo_save.image_width = image_new_width;
cinfo_save.image_height = image_new_height;
cinfo_save.input_components = image_new_components;
cinfo_save.in_color_space = image_new_colorspace;
jpeg_set_defaults(&cinfo_save);
jpeg_set_quality(&cinfo_save, 80, true);
jpeg_start_compress(&cinfo_save, TRUE);
JSAMPROW row_pointer[1];
row_stride = cinfo_save.image_width * cinfo_save.input_components;
while(cinfo_save.next_scanline < cinfo_save.image_height){
row_pointer[0] = &image_buffer[ cinfo_save.next_scanline * row_stride];
jpeg_write_scanlines(&cinfo_save, row_pointer, 1);
}
jpeg_finish_compress(&cinfo_save);
jpeg_destroy_compress(&cinfo_save);
fclose(outfile);
image_buffer = NULL;
return 1;
}