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圧縮オブジェクトを申請して初期化し、エラープロセッサを指定する
2.bmpファイルヘッダとビットマップ情報を読み込む
3.データを読み取り、データの格納順序を調整する
ステップ2:ステップ1で得られたデータをjpeg圧縮しlibjpegライブラリを呼び出す
4.得られたデータの設定
注意が必要なのはjpeg_set_defaults関数は、画像幅、高さ、カラーチャネル数、カラー空間の4つのパラメータを設定してから呼び出さなければなりません.この関数はこの4つの値を使用してjpeg_を呼び出すためです.set_defaults関数の後、jpeglibライブラリはデフォルトの設定で画像を圧縮します.圧縮品質などの設定を変更する必要がある場合は、この関数を呼び出すと、jpeg_などの他の設定関数を呼び出すことができます.set_quality関数.実は画像圧縮時に設定できるパラメータはたくさんありますが、ほとんどは設定する必要はありません.jpeg_を呼び出すだけです.set_defaults関数の値はデフォルトです.
5.書き込みデータ
6.圧縮プロセス申請リソースの解放
主にjpeg圧縮オブジェクトと動的割り当ての配列であり,ここではjpegオブジェクトの解放のみを紹介し,jpeg_を呼び出すだけである.destroy_compressという関数は、次のようになります.
完全なコード
基本構想: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