將bmp檔案壓縮為jpg檔案

52017發表於2024-05-14

目錄

目錄
  • bmp檔案壓縮為jpg檔案介面設計
    • 需要的相關標頭檔案
    • 結構體
    • 函式呼叫
    • 主函式

bmp檔案壓縮為jpg檔案介面設計

/*******************************************************************
 * file name: bmp2jpg
 * author   : 17666589210@163.com
 * date     : 2024-05-14
 * function : Retrieve images, shrink them, and open them on the LCD screen
 * note     : None
 * version  : 1.0
 * CopyRight (c)   2024  17666589210@163.com  Right Reseverd
 *******************************************************************/

需要的相關標頭檔案

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include "jpeglib.h"

結構體

#pragma pack(1) // 設定取消位元組對齊
// 檔案資訊結構體
typedef struct tag_bitmap_file_header
{
    unsigned short file_type; // 檔案標識,為字母ASCII碼“BM”
    unsigned int file_size;   // 點陣圖檔案大小,以位元組為單位
    unsigned short reserved1; // 點陣圖檔案保留字,必須為0
    unsigned short reserved2; // 點陣圖檔案保留字,必須為0
    unsigned int offset_bits; // 檔案開始到點陣圖資料開始之間的偏移量位元組
} bmp_file_header;

// 點陣圖資訊結構體
typedef struct tag_bitmap_info_header
{
    unsigned int bitmap_info_size; // 影像描述資訊快的大小,常為28H
    int bitmap_width;              // 影像寬度
    int bitmap_height;             // 影像高度
    unsigned short planes;         // 影像的plane總數(恆為1)
    unsigned short image_depth;    // 記錄顏色的位數取值1(雙色),4,6,24,,3
    unsigned int compression;      // 資料壓縮方式(0:不壓縮;1:8位壓縮;2:4位壓縮
    unsigned int image_size;       // 影像區資料的大小,必須是4的倍數
    int x_pels_permeter;           // 水平每米有多少畫素,在裝置無關點陣圖中,填寫00H
    int y_pels_permeter;           // 垂直每米有多少畫素,在裝置無關點陣圖中,填寫00H
    unsigned int color_used;       // 此影像所有的顏色數,不用,固定為0
    unsigned int color_important;  // 重要顏色數,不用,固定為0
} bmp_info_header;

#pragma pack() // 設定為位元組對齊

函式呼叫

/********************************************************************
 *
 *	name	 :	write_JPEG_file
 *	function :  實現bmp檔案壓縮為jpb檔案
 *	argument :
 *				@filename  :需要生成jpg的檔名
 *				@bmpname   :需要壓縮的bmp檔案
 *              @quality   :生成的jpg檔案的質量度
 *	retval	 :  呼叫成功返回生成檔案後的結果
 *	author	 :  17666589210@163.com
 *	date	 :  2024/05/14
 * 	note	 :  none
 *
 * *****************************************************************/
int write_JPEG_file(char *filename, int quality, char *bmpname)
{
    // 1.開啟bmp圖片檔案
    FILE *bmp_fb = fopen(bmpname, "rb");
    if (NULL == bmp_fb)
    {
        printf("open bmp file faild\n");
        return -1;
    }

    // 2.讀取BMP圖片檔案的影像資訊,獲取BMP的寬和高
    bmp_file_header headerinfo; // BMP標頭檔案結構體申請記憶體 14位元組
    bmp_info_header fileinfo;   // BMP檔案資訊結構體
    fread(&headerinfo, 1, 14, bmp_fb);
    fread(&fileinfo, 1, 40, bmp_fb); // 讀取BMP標頭檔案資訊
    // printf("current bmp width = %d\ncurrent bmp height = %d\n", fileinfo.bitmap_width, fileinfo.bitmap_height); // 輸出BMP圖片寬度和高度資訊

    // 3.讀取原BMP圖片的顏色分量
    int pxsize = fileinfo.bitmap_width * fileinfo.bitmap_height * fileinfo.image_depth / 8;
    printf("pxsize = %d\n", pxsize);
    char bmp_buf[pxsize];              // 申請圖片畫素大小的緩衝區
    fread(bmp_buf, 1, pxsize, bmp_fb); // 讀取BMP顏色分量資料

    char newbmp_buf[pxsize]; // 申請一塊新的BMP圖片大小的緩衝區
    int cnt = 0;
    for (int y = 480 - 1; y > 0; y--)
    {
        for (int x = 0; x < 800; x++)
        {
            for (int k = 2; k >= 0; k--)
            {
                newbmp_buf[cnt] = bmp_buf[(y * 800 + x) * 3 + k]; // 獲取三個位元組為一組的資料,並隔一行一列獲取資料
                cnt++;
            }
        }
    }
    struct jpeg_compress_struct cinfo;

    struct jpeg_error_mgr jerr;

    FILE *outfile;                 /* target file */
    unsigned char *row_pointer[1]; /* pointer to JSAMPLE row[s] */
    int row_stride;                /* physical row width in image buffer */

    /* Step 1: allocate and initialize JPEG compression object */

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo); // 初始化JPEG壓縮物件
    if ((outfile = fopen(filename, "wb")) == NULL)
    {
        fprintf(stderr, "can't open %s\n", filename);
        exit(1);
    }
    jpeg_stdio_dest(&cinfo, outfile);

    /* Step 3: set parameters for compression */

    cinfo.image_width = fileinfo.bitmap_width; /* image width and height, in pixels */
    cinfo.image_height = fileinfo.bitmap_height;
    cinfo.input_components = 3;     /* # of color components per pixel */
    cinfo.in_color_space = JCS_RGB; /* colorspace of input image */

    jpeg_set_defaults(&cinfo);

    /* Step 4: Start compressor */
    jpeg_start_compress(&cinfo, TRUE);

    /* Step 5: while (scan lines remain to be written) */
    row_stride = fileinfo.bitmap_width * 3; /* JSAMPLEs per row in image_buffer */

    while (cinfo.next_scanline < cinfo.image_height)
    {
        row_pointer[0] = &newbmp_buf[cinfo.next_scanline * row_stride];
        (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    /* Step 6: Finish compression */
    jpeg_finish_compress(&cinfo);
    /* After finish_compress, we can close the output file. */
    fclose(outfile);

    /* Step 7: release JPEG compression object */
    jpeg_destroy_compress(&cinfo);

    return 1;
}

主函式

int main()
{
    int quality = 100;
    write_JPEG_file("demo.jpg", quality, "demo.bmp");
    return 0;
}

相關文章