日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C实现BMP转JPG 附源码

發布時間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C实现BMP转JPG 附源码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 時間:2019-7-13
  • 環境:ubuntu18.04+clion
  • 基本思路:利用libjpeg庫實現將bmp圖像轉換為jpg圖像,并可以設置jpg的質量因子。
  • 了解:BMP格式,參照網址:https://blog.csdn.net/lesky/article/details/2218850
  • 注意事項:
  • 1. RBG數據存儲為bmp時,數據是逆序存放,并且不是RGB,而是BGR;當將RGB數據存儲為jpg時,則不用,不用逆序,數據也還是RGB。
  • 2. 圖像位圖頭信息中的Height為正數時表示倒向的位圖,讀取的順序為(從左->右,從下->上),所以存為jpg需將數據順序調換。
  • 3. Windows在進行行掃描的時候最小的單位為4個字節,所以當每行字節數不為4的整數倍時要對字節數進行調整,缺省是每行補0。圖像位圖頭信息中的高寬是實際圖像的像素點的個數,與存儲時需要調整對其數據使其滿足4字節的倍數無關。
  • 5.此例程適用于彩色位圖,若為灰度圖需對程序做相應的修改,有空我會完善程序并增加jpg轉bmp部分代碼。關于第四點中的windows行掃描最小單位為4字節這個部分我不清楚linux中有無行掃描最小單位一說,希望得到指點。

    此篇博客參考于:https://blog.csdn.net/lzhq28/article/details/7775957


    ?

    目錄

    ?

    一、建立編譯環境

    二、bmp轉jpg壓縮步驟

    步驟一:讀取bmp文件,并將數據調整為從從上到下、從左到右、RGB順序

    1.申請并初始化jpeg壓縮對象,同時要指定錯誤處理器

    2.讀取bmp文件頭和位圖信息

    3.讀取數據并調整數據的存儲順序

    步驟二:對步驟一得到的數據進行jpeg壓縮,將調用libjpeg庫

    4.對得到的數據進行設置

    5.寫入數據

    6.釋放壓縮過程申請資源

    完整代碼


一、建立編譯環境

編譯libjpeg庫

Jpeg庫下載地址:http://www.ijg.org/files/

下載好先解壓,打開終端,進入解壓好的目錄。

【./configure --enable -shared --enable-static】

【make】

【make install】

在完成轉換功能的文件中加入#include <jpeglib.h>,編譯時鏈接libjpeg庫即可。

?

二、bmp轉jpg壓縮步驟

步驟一:讀取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 datafd = fopen(bmp_file, "rb");if(!fd){printf("ERROR1: Can not open the image.\n");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\n");return 0;}Line_data = (unsigned char*)malloc(m_iLineByteCnt);//每行圖像數據所需空間if(Line_data == NULL){printf("malloc error\r\n");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("\nERROR2: Can not read the pixel data.\n");free(Line_data);fclose(fd);return -1;}}for(int tmpCol = 0;tmpCol<m_iImageWidth;tmpCol++){data[(m_iImageHeight-1-scanline) * m_iLineByteCnt+tmpCol*3+0]=Line_data[tmpCol*3+2];data[(m_iImageHeight-1-scanline) * m_iLineByteCnt+tmpCol*3+1]=Line_data[tmpCol*3+1];data[(m_iImageHeight-1-scanline) * m_iLineByteCnt+tmpCol*3+2]=Line_data[tmpCol*3+0];}//調整數據存儲順序(BGR->RGB,從下到上->從上到下)}}

步驟二:對步驟一得到的數據進行jpeg壓縮,將調用libjpeg庫

4.對得到的數據進行設置

需要注意的是,jpeg_set_defaults函數一定要等設置好圖像寬、高、色彩通道數及色彩空間四個參數后才能調用,因為這個函數要用到這四個值,調用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\n", jeg_file);return -1;}jpeg_stdio_dest(&cinfo, outfile); //指定壓縮后的圖像所存放的目標文件 ,二進制打開cinfo.image_width = m_iImageWidth; //寬cinfo.image_height = m_iImageHeight;//高cinfo.input_components = depth; // 在此為3,表示彩色位圖, 如果是灰度圖,則為1cinfo.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 <jzy2410723051@163.com><zzzzyjin@foxmail.com>* 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\n");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 <jzy2410723051@163.com><zzzzyjin@foxmail.com>* 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 datafd = fopen(bmp_file, "rb");if(!fd){printf("ERROR1: Can not open the image.\n");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\n",sizeof(DWORD),sizeof(WORD));//printf("%d %d\r\n",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\n");return 0;}Line_data = (unsigned char*)malloc(m_iLineByteCnt);if(Line_data == NULL){printf("malloc error\r\n");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("\nERROR2: Can not read the pixel data.\n");free(Line_data);fclose(fd);return -1;}}for(int tmpCol = 0;tmpCol<m_iImageWidth;tmpCol++){data[(m_iImageHeight-1-scanline) * m_iLineByteCnt+tmpCol*3+0]=Line_data[tmpCol*3+2];data[(m_iImageHeight-1-scanline) * m_iLineByteCnt+tmpCol*3+1]=Line_data[tmpCol*3+1];data[(m_iImageHeight-1-scanline) * m_iLineByteCnt+tmpCol*3+2]=Line_data[tmpCol*3+0];}//調整數據存儲順序(BGR->RGB,從下到上->從上到下)}}jpeg_create_compress(&cinfo);//初始化jpeg壓縮對象if ((outfile = fopen(jeg_file, "wb")) == NULL){fprintf(stderr, "can't open %s\n", jeg_file);return -1;}jpeg_stdio_dest(&cinfo, outfile); //指定壓縮后的圖像所存放的目標文件 ,二進制打開cinfo.image_width = m_iImageWidth; //寬cinfo.image_height = m_iImageHeight;//高cinfo.input_components = depth; // 在此為3,表示彩色位圖, 如果是灰度圖,則為1cinfo.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 <jzy2410723051@163.com><zzzzyjin@foxmail.com>* ChangeLog: 1, Release initial version on "2019年7月13日 18時45分30秒"*********************************************************************************/ #ifndef BMPTOJPG_BMPTOJPG_H #define BMPTOJPG_BMPTOJPG_H #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <sys/timeb.h> #include <jpeglib.h>#define DWORD unsigned int #define WORD unsigned shorttypedef 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

?

總結

以上是生活随笔為你收集整理的C实现BMP转JPG 附源码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。