jpg壓縮原理可以參考這篇文章http://hi.baidu.com/tiandsp/item/f5a2dcde6ef1405bd73aae41,我很早以前轉的一篇文章。
沒有使用libjpeg的壓縮代碼可以看看這篇文章http://hi.baidu.com/tiandsp/item/9b5843c58a3b4474cfd4f841,也是我很早以前轉的。
這次使用libjpeg庫壓縮和上一篇的解壓正好對應起來,有好多函數名稱我都是對稱的起的,所以結合起來看效果更好。
和上一篇一樣,只能處理24位和8位的圖像。
代碼如下:
#include <iostream> #include <stdio.h> extern "C"{ #include "jpeglib.h" }; #pragma comment(lib,"jpeg.lib") using namespace std; #pragma pack(2) //兩字節對齊,否則bmp_fileheader會占16Byte struct bmp_fileheader { unsigned short bfType; //若不對齊,這個會占4Byte unsigned long bfSize; unsigned short bfReverved1; unsigned short bfReverved2; unsigned long bfOffBits; }; struct bmp_infoheader { unsigned long biSize; unsigned long biWidth; unsigned long biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned long biCompression; unsigned long biSizeImage; unsigned long biXPelsPerMeter; unsigned long biYpelsPerMeter; unsigned long biClrUsed; unsigned long biClrImportant; }; FILE *input_file; FILE *output_file; struct bmp_fileheader bfh; struct bmp_infoheader bih; unsigned char *src_buffer; unsigned char *dst_buffer; void read_bmp_header() { fread(&bfh,sizeof(struct bmp_fileheader),1,input_file); fread(&bih,sizeof(struct bmp_infoheader),1,input_file); } void read_bmp_data() { fseek(input_file,bfh.bfOffBits,SEEK_SET); src_buffer=new unsigned char[bih.biWidth*bih.biHeight*bih.biBitCount/8]; fread(src_buffer,sizeof(unsigned char)*bih.biWidth*bih.biHeight*bih.biBitCount/8,1,input_file); unsigned long width=bih.biWidth; unsigned long height=bih.biHeight; unsigned short depth=unsigned short(bih.biBitCount/8); unsigned char *src_point; unsigned char *dst_point; dst_buffer=new unsigned char[width*height*depth]; src_point=src_buffer+width*depth*(height-1); dst_point=dst_buffer+width*depth*(height-1); for (unsigned long i=0;i<height;i++) { for (unsigned long j=0;j<width*depth;j+=depth) { if (depth==1) //處理灰度圖 { dst_point[j]=src_point[j]; } if (depth==3) //處理彩色圖 { dst_point[j+2]=src_point[j+0]; dst_point[j+1]=src_point[j+1]; dst_point[j+0]=src_point[j+2]; } } dst_point-=width*depth; src_point-=width*depth; } } void synthese_jpeg() { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPARRAY buffer; unsigned long width=bih.biWidth; unsigned long height=bih.biHeight; unsigned short depth=unsigned short(bih.biBitCount/8); unsigned char *point; cinfo.err=jpeg_std_error(&jerr); //libjpeg各種配置 jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo,output_file); cinfo.image_width=width; cinfo.image_height=height; cinfo.input_components=depth; if (depth==1) cinfo.in_color_space=JCS_GRAYSCALE; else cinfo.in_color_space=JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo,20,TRUE); //中間的值為壓縮質量,越大質量越好 jpeg_start_compress(&cinfo,TRUE); buffer=(*cinfo.mem->alloc_sarray) ((j_common_ptr)&cinfo,JPOOL_IMAGE,width*depth,1); point=dst_buffer+width*depth*(height-1); while (cinfo.next_scanline<height) { memcpy(*buffer,point,width*depth); jpeg_write_scanlines(&cinfo,buffer,1); point-=width*depth; } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); } int main() { input_file=fopen("lena_gray.bmp","rb"); output_file=fopen("lena.jpg","wb"); read_bmp_header(); read_bmp_data(); synthese_jpeg(); fclose(input_file); fclose(output_file); delete[] src_buffer; delete[] dst_buffer; cout<<"good job."<<endl; cin.get(); return 0; }
