bmp转jpg(使用libjpeg)

  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;
}
posted @ 2012-12-03 14:25  Dsp Tian  阅读(7264)  评论(3编辑  收藏  举报