C BMP回転JPG付ソースコードを実現


時間:2019-7-13 環境:ubuntu 18.04+clion
基本構想:libjpegライブラリを用いてbmp画像をjpg画像に変換し、jpgの品質因子を設定することができる.
了解:BMPフォーマット、URLを参照:https://blog.csdn.net/lesky/article/details/2218850
注意事項:1.RBGデータがbmpに格納されている場合、データは逆順序で格納され、RGBではなくBGRである.RGBデータをjpgとして記憶する場合、逆シーケンスを用いず、データもRGBである.
2.画像ビットマップヘッダ情報のHeightが正数の場合は逆方向を示すビットマップであり、読み出される順番は(左→右、下→上)であるため、jpgとして保存するにはデータを順番に入れ替える必要がある.3.Windowsは行スキャンを行うときの最小単位が4バイトであるため、1行あたりのバイト数が4の整数倍でない場合はバイト数を調整し、デフォルトは行ごとに0を補う.画像ビットマップヘッダ情報におけるアスペクトは、実際の画像の画素点の個数であり、記憶時にそのデータが4バイトを満たすように調整する必要がある倍数に関係しない.
5.この例はカラービットマップに適しており、階調マップのためにプログラムを修正する必要がある場合は、暇があればプログラムを改善し、jpg回転bmp部分コードを追加します.第4点のwindows行のスキャンの最小単位が4バイトであるこの部分についてはlinuxの中で行のスキャンの最小単位があるかどうか分かりませんが、指摘してほしいです.このブログは次のように参照されています.https://blog.csdn.net/lzhq28/article/details/7775957
ディレクトリ1、コンパイル環境の確立2、bmp転送jpg圧縮ステップ1:bmpファイルを読み出し、データを上から下へ、左から右へ、RGB順1に調整する.jpeg圧縮オブジェクトを申請して初期化し、エラープロセッサ2を指定する.bmpファイルヘッダとビットマップ情報3を読み出す.データを読み出してデータの格納順序を調整するステップ2:ステップ1で得られたデータをjpeg圧縮するlibjpegライブラリ4を呼び出す.得られたデータを設定.書き込みデータ6.圧縮プロセス申請リソースの完全なコードを解放

一、コンパイル環境の構築
libjpegライブラリのコンパイル
Jpegライブラリのダウンロードアドレス:http://www.ijg.org/files/
ダウンロードして先に解凍して、端末を開けて、解凍したディレクトリに入ります.
【./configure --enable -shared --enable-static】
【make】
【make install】
変換機能を完了したファイルに#includeを加え、コンパイル時にlibjpegライブラリをリンクすればよい.
 
二、bmp回転jpg圧縮手順
ステップ1:bmpファイルを読み込み、データを上から下へ、左から右へ、RGB順に調整する
1.jpeg圧縮オブジェクトを申請して初期化し、エラープロセッサを指定する
    struct jpeg_compress_struct cinfo;
     //        ,    jcs.err 
    struct jpeg_error_mgr jerr;
    cinfo.err = jpeg_std_error(&jerr);

2.bmpファイルヘッダとビットマップ情報を読み込む
    FILE *fd,*outfile;
    BITMAPFILEHEADER header;//     
    memset(&header, 0, sizeof(header));
    BITMAPINFOHEADER infoheader;//     
    memset(&infoheader, 0, sizeof(infoheader));
    long m_iImageWidth=0;
    long m_iImageHeight=0;
    WORD m_iBitsPerPixel=0;
    WORD m_iBytesPerPixel=0;
    int m_iLineByteCnt=0;//      
    int m_iImageDataSize=0;//         

    // Read bmp image data
    fd = fopen(bmp_file, "rb");
    if(!fd)
    {
        printf("ERROR1: Can not open the image.
"); return -1; } fread(&header,sizeof(unsigned char),sizeof(header),fd);// fread(&infoheader,sizeof(unsigned char),sizeof(infoheader),fd);// m_iImageWidth = infoheader.biWidth; m_iImageHeight = infoheader.biHeight; m_iBitsPerPixel = infoheader.biBitCount; m_iBytesPerPixel = m_iBitsPerPixel/8;// m_iLineByteCnt = ((m_iImageWidth * m_iBytesPerPixel+3)>>2)<<2;// 4

3.データを読み取り、データの格納順序を調整する
    m_iImageDataSize = m_iLineByteCnt * m_iImageHeight;
    data = (unsigned char*)malloc(m_iImageDataSize);//           
    if(data == NULL)
    {
        printf("malloc error\r
"); return 0; } Line_data = (unsigned char*)malloc(m_iLineByteCnt);// if(Line_data == NULL) { printf("malloc error\r
"); return 0; } if((3 == m_iBytesPerPixel)&&(m_iImageHeight)>0) { for(int scanline = 0;scanline < m_iImageHeight;scanline++) { ret = fread(Line_data, sizeof(unsigned char),m_iLineByteCnt,fd); if(ret == 0) { if(ferror(fd)) { printf("
ERROR2: Can not read the pixel data.
"); free(Line_data); fclose(fd); return -1; } } for(int tmpCol = 0;tmpColRGB, -> ) } }

ステップ2:ステップ1で得られたデータをjpeg圧縮しlibjpegライブラリを呼び出す
4.得られたデータの設定
注意が必要なのはjpeg_set_defaults関数は、画像幅、高さ、カラーチャネル数、カラー空間の4つのパラメータを設定してから呼び出さなければなりません.この関数はこの4つの値を使用してjpeg_を呼び出すためです.set_defaults関数の後、jpeglibライブラリはデフォルトの設定で画像を圧縮します.圧縮品質などの設定を変更する必要がある場合は、この関数を呼び出すと、jpeg_などの他の設定関数を呼び出すことができます.set_quality関数.実は画像圧縮時に設定できるパラメータはたくさんありますが、ほとんどは設定する必要はありません.jpeg_を呼び出すだけです.set_defaults関数の値はデフォルトです.
    jpeg_create_compress(&cinfo);//   jpeg    
    if ((outfile = fopen(jeg_file, "wb")) == NULL)
    {
        fprintf(stderr, "can't open %s
", jeg_file); return -1; } jpeg_stdio_dest(&cinfo, outfile); // , cinfo.image_width = m_iImageWidth; // cinfo.image_height = m_iImageHeight;// cinfo.input_components = depth; // 3, , , 1 cinfo.in_color_space = JCS_RGB; //JCS_GRAYSCALE ,JCS_RGB jpeg_set_defaults(&cinfo); // jpeg_set_defaults ,jpeglib jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE ); // jpeglib jpeg_start_compress(&cinfo, TRUE);

5.書き込みデータ
    row_pointer = malloc(m_iImageDataSize);
    while (cinfo.next_scanline < cinfo.image_height)
    {
        for(int j=0;j< m_iLineByteCnt;j++)
        {
            Line_data[j]=data[cinfo.next_scanline*m_iLineByteCnt+j];
        }
        row_pointer[0]=Line_data;
        jpeg_write_scanlines(&cinfo, row_pointer, 1);

    }
    jpeg_finish_compress(&cinfo);

6.圧縮プロセス申請リソースの解放
主にjpeg圧縮オブジェクトと動的割り当ての配列であり,ここではjpegオブジェクトの解放のみを紹介し,jpeg_を呼び出すだけである.destroy_compressという関数は、次のようになります.
    jpeg_destroy_compress(&cinfo);

完全なコード
/*********************************************************************************
 *    Copyright:  (C) 2019 zyjin
 *                  All rights reserved.
 *
 *    Filename:  main.c
 *    Description:  bmp to jpg
 *
 *    Created by zyjin on 19-7-13.
 *
 *    Version:  1.0.0(2019 7 13 )
 *    Author:  zyjin 
 *    ChangeLog:  1, Release initial version on "2019 7 13  19 18 "
 *
 ********************************************************************************/
#include "bmptojpg.h"

int main(int argc,char *argv[])
{
    int JPEG_QUALITY = 100;
    const char *bmp_file = "/root/CLionProjects/BMPTOJPG/test.bmp";
    const char *jpg_file = "/root/CLionProjects/BMPTOJPG/test2.jpg";
    BmptoJpg(bmp_file,jpg_file, JPEG_QUALITY);
    printf("BMP To JPG done\r
"); return 1; }
/*********************************************************************************
 *    Copyright:  (C) 2019 zyjin
 *                  All rights reserved.
 *
 *    Filename:  bmptojpg.c
 *    Description:  bmp to jpg
 *
 *    Created by zyjin on 19-7-13.
 *
 *    Version:  1.0.0(2019 7 13 )
 *    Author:  zyjin 
 *    ChangeLog:  1, Release initial version on "2019 7 13  18 55 "
 *
 ********************************************************************************/
#include "bmptojpg.h"
#define a
#ifdef a
int BmptoJpg(const char *bmp_file, const char *jeg_file, int JPEG_QUALITY)
{
    FILE *fd,*outfile;
    int ret;
    int i = 0;
    unsigned char *data,*Line_data;
    int depth = 3;
    JSAMPROW * row_pointer;
    //long rgb_index = 0;
    struct jpeg_compress_struct cinfo;//      jpeg    ,          
    struct jpeg_error_mgr jerr;//        ,    jcs.err 
    cinfo.err = jpeg_std_error(&jerr);

    BITMAPFILEHEADER header;//     
    memset(&header, 0, sizeof(header));
    BITMAPINFOHEADER infoheader;//     
    memset(&infoheader, 0, sizeof(infoheader));
    long m_iImageWidth=0;
    long m_iImageHeight=0;
    WORD m_iBitsPerPixel=0;
    WORD m_iBytesPerPixel=0;
    int m_iLineByteCnt=0;//      
    int m_iImageDataSize=0;//         

    // Read bmp image data
    fd = fopen(bmp_file, "rb");
    if(!fd)
    {
        printf("ERROR1: Can not open the image.
"); return -1; } fread(&header,sizeof(unsigned char),sizeof(header),fd);// fread(&infoheader,sizeof(unsigned char),sizeof(infoheader),fd);// m_iImageWidth = infoheader.biWidth; m_iImageHeight = infoheader.biHeight; m_iBitsPerPixel = infoheader.biBitCount; //printf("%d %d\r
",sizeof(DWORD),sizeof(WORD)); //printf("%d %d\r
",sizeof(header),sizeof(infoheader)); //printf("%ld %ld %d ",m_iImageWidth,m_iImageHeight,m_iBitsPerPixel); m_iBytesPerPixel = m_iBitsPerPixel/8;// m_iLineByteCnt = (m_iImageWidth * m_iBytesPerPixel); //m_iLineByteCnt = ((m_iImageWidth * m_iBytesPerPixel+3)>>2)<<2;// 4 m_iImageDataSize = m_iLineByteCnt * m_iImageHeight; data = (unsigned char*)malloc(m_iImageDataSize); if(data == NULL) { printf("malloc error\r
"); return 0; } Line_data = (unsigned char*)malloc(m_iLineByteCnt); if(Line_data == NULL) { printf("malloc error\r
"); return 0; } if((3 == m_iBytesPerPixel)&&(m_iImageHeight)>0) { for(int scanline = 0;scanline < m_iImageHeight;scanline++) { ret = fread(Line_data, sizeof(unsigned char),m_iLineByteCnt,fd); if(ret == 0) { if(ferror(fd)) { printf("
ERROR2: Can not read the pixel data.
"); free(Line_data); fclose(fd); return -1; } } for(int tmpCol = 0;tmpColRGB, -> ) } } jpeg_create_compress(&cinfo);// jpeg if ((outfile = fopen(jeg_file, "wb")) == NULL) { fprintf(stderr, "can't open %s
", jeg_file); return -1; } jpeg_stdio_dest(&cinfo, outfile); // , cinfo.image_width = m_iImageWidth; // cinfo.image_height = m_iImageHeight;// cinfo.input_components = depth; // 3, , , 1 cinfo.in_color_space = JCS_RGB; //JCS_GRAYSCALE ,JCS_RGB jpeg_set_defaults(&cinfo); // jpeg_set_defaults ,jpeglib jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE ); // jpeglib jpeg_start_compress(&cinfo, TRUE); // row_pointer = malloc(m_iImageDataSize); while (cinfo.next_scanline < cinfo.image_height) { for(int j=0;j< m_iLineByteCnt;j++) { Line_data[j]=data[cinfo.next_scanline*m_iLineByteCnt+j]; } row_pointer[0]=Line_data; jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); free(row_pointer); free(data); free(Line_data); fclose(fd); fclose(outfile); return 0; } #endif
/*********************************************************************************
 *    Copyright:  (C) 2019 zyjin
 *                  All rights reserved.
 *
 *    Filename:  bmptojpg.h
 *    Description:  bmp to jpg
 *
 *    Created by zyjin on 19-7-13.
 *
 *    Version:  1.0.0(2019 7 13 )
 *    Author:  zyjin 
 *    ChangeLog:  1, Release initial version on "2019 7 13  18 45 30 "
 *
 ********************************************************************************/
#ifndef BMPTOJPG_BMPTOJPG_H
#define BMPTOJPG_BMPTOJPG_H
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define DWORD unsigned int
#define WORD  unsigned short

typedef struct tagBITMAPFILEHEADER {
    WORD    bfType;
    WORD    bfReserved1;
    WORD    bfReserved2;
    WORD    bfSize;
    WORD    bbbb;
    WORD    bbba;
    WORD   bfOffBits;
} BITMAPFILEHEADER;// FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER{
    DWORD      biSize;
    DWORD      biWidth;
    DWORD      biHeight;
    WORD       biPlanes;
    WORD       biBitCount;
    DWORD      biCompression;
    DWORD      biSizeImage;
    DWORD      biXPelsPerMeter;
    DWORD      biYPelsPerMeter;
    DWORD      biClrUsed;
    DWORD      biClrImportant;
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

int BmptoJpg(const char *bmp_file, const char *jeg_file, int JPEG_QUALITY);
#endif //BMPTOJPG_BMPTOJPG_H