欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語(yǔ)言讀取和存儲(chǔ)bmp格式圖片

 更新時(shí)間:2021年10月25日 10:03:30   作者:HsiangUp  
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言讀取和存儲(chǔ)bmp格式圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

開發(fā)過(guò)程中有時(shí)候需要解析bmp數(shù)據(jù),下面先簡(jiǎn)單介紹bmp數(shù)據(jù)組成,后面附上C語(yǔ)言讀取和存儲(chǔ)bmp格式圖片代碼。

典型的位圖文件格式通常包含下面幾個(gè)數(shù)據(jù)塊:

1、BMP文件頭:保存位圖文件的總體信息。
2、位圖信息頭:保存位圖圖像的詳細(xì)信息。位圖信息:保存位圖圖像的詳細(xì)信息。
3、調(diào)色板:保存所用顏色的定義。調(diào)色板:保存所用顏色的定義。
4、位圖數(shù)據(jù):保存一個(gè)又一個(gè)像素的實(shí)際圖像。位圖數(shù)據(jù):保存一個(gè)又一個(gè)像素的實(shí)際圖像。

1. BMP文件頭(14字節(jié))

BMP文件頭數(shù)據(jù)結(jié)構(gòu)含有BMP文件的類型、文件大小和位圖起始位置等信息。

這部分是識(shí)別信息,典型的應(yīng)用程序會(huì)首先普通讀取這部分?jǐn)?shù)據(jù)以確保的確是位圖文件并且沒(méi)有損壞。

位圖頭結(jié)構(gòu)體定義如下:

typedef struct
{
    uint16_t type;  //位圖文件的類型,必須為BM(1-2字節(jié))
    uint32_t size;  //位圖文件的大小,以字節(jié)為單位(3-6字節(jié),低位在前)
    uint16_t reserved1;  //位圖文件保留字,必須為0(7-8字節(jié))
    uint16_t reserved2;  //位圖文件保留字,必須為0(9-10字節(jié))
    uint32_t off_bits;  //位圖數(shù)據(jù)位置的地址偏移,即起始位置,以相對(duì)于位圖(11-14字節(jié),低位在前)
}__attribute__ ((packed)) bmp_file_header_t;

2. 位圖信息頭(40字節(jié))

這部分告訴應(yīng)用程序圖像的詳細(xì)信息,在屏幕上顯示圖像將會(huì)使用這些信息,它從文件的第15個(gè)字節(jié)開始。

位圖信息頭結(jié)構(gòu)體定義如下:

typedef struct
{
    uint32_t size;
    int32_t width;
    int32_t height;
    uint16_t planes;
    uint16_t bit_count;
    uint32_t compression;
    uint32_t size_image;
    uint32_t x_pels_permeter;
    uint32_t y_pels_permeter;
    uint32_t clr_used;
    uint32_t clr_important;
} bmp_info_header_t;

結(jié)構(gòu)體變量解析如下:

  • uint32_t size; 15-18字節(jié):定義以下用來(lái)描述影像的區(qū)塊(BitmapInfoHeader)的大小,即本結(jié)構(gòu)所占用字節(jié)數(shù),它的值是:40
  • int32_t width; 19-22字節(jié):位圖寬度,以像素為單位。
  • int32_t height; 23-26字節(jié):位圖高度,以像素為單位。
  • uint16_t planes; 27-28字節(jié):保存所用彩色位面的個(gè)數(shù)。不經(jīng)常使用。
  • uint16_t bit_count; 29-30字節(jié):保存每個(gè)像素的位數(shù),它是圖像的顏色深度。常用值是1(雙色灰階)、4(16色灰階)、8(256色灰階)和24(彩色)。
  • uint32_t compression; 31-34字節(jié):定義所用的壓縮算法。允許的值是0、1、2、3、4、5。
  • 0 - 沒(méi)有壓縮(也用BI_RGB表示)

1 - 行程長(zhǎng)度編碼 8位/像素(也用BI_RLE8表示)
2 - 行程長(zhǎng)度編碼4位/像素(也用BI_RLE4表示)
3 - Bit field(也用BI_BITFIELDS表示)
4 - JPEG圖像(也用BI_JPEG表示)
5 - PNG圖像(也用BI_PNG表示)

  • uint32_t size_image; 35-38字節(jié):位圖的大小(其中包含了為了補(bǔ)齊行數(shù)是4的倍數(shù)而添加的空字節(jié)),以字節(jié)為單位。這是原始位圖數(shù)據(jù)的大小,不要與文件大小混淆。
  • uint32_t x_pels_permeter; 39-42字節(jié):位圖水平分辨率,每米像素?cái)?shù)。
  • uint32_t y_pels_permeter; 43-46字節(jié):位圖垂直分辨率,每米像素?cái)?shù)。
  • uint32_t clr_used; 47-50字節(jié):位圖實(shí)際使用的顏色表中的顏色數(shù)。
  • uint32_t clr_important; 51-54字節(jié):位圖顯示過(guò)程中重要的顏色數(shù),當(dāng)每個(gè)顏色都重要時(shí)這個(gè)值與顏色數(shù)目(clr_used)相等。

3. 調(diào)色板

BMP調(diào)色板結(jié)構(gòu)體定義如下:

typedef struct _tagRGBQUAD
{
BYTE  rgbBlue;       //指定藍(lán)色強(qiáng)度
BYTE  rgbGreen;      //指定綠色強(qiáng)度
BYTE  rgbRed;        //指定紅色強(qiáng)度
BYTE  rgbReserved;  //保留,設(shè)置為0
} RGBQUAD;

1,4,8位圖像才會(huì)使用調(diào)色板數(shù)據(jù),16,24,32位圖像不需要調(diào)色板數(shù)據(jù),即調(diào)色板最多只需要256項(xiàng)(索引0 - 255)。

顏色表的大小根據(jù)所使用的顏色模式而定:2色圖像為8字節(jié);16色圖像位64字節(jié);256色圖像為1024字節(jié)。其中,每4字節(jié)表示一種顏色,并以B(藍(lán)色)、G(綠色)、R(紅色)、alpha(32位位圖的透明度值,一般不需要)。即首先4字節(jié)表示顏色號(hào)1的顏色,接下來(lái)表示顏色號(hào)2的顏色,依此類推。

顏色表中RGBQUAD結(jié)構(gòu)數(shù)據(jù)的個(gè)數(shù)有biBitCount來(lái)確定,當(dāng)biBitCount=1,4,8時(shí),分別有2,16,256個(gè)表項(xiàng):

  • 當(dāng)biBitCount=1時(shí),為2色圖像,BMP位圖中有2個(gè)數(shù)據(jù)結(jié)構(gòu)RGBQUAD,一個(gè)調(diào)色板占用4字節(jié)數(shù)據(jù),所以2色圖像的調(diào)色板長(zhǎng)度為2*4為8字節(jié)。
  • 當(dāng)biBitCount=4時(shí),為16色圖像,BMP位圖中有16個(gè)數(shù)據(jù)結(jié)構(gòu)RGBQUAD,一個(gè)調(diào)色板占用4字節(jié)數(shù)據(jù),所以16像的調(diào)色板長(zhǎng)度為16*4為64字節(jié)。
  • 當(dāng)biBitCount=8時(shí),為256色圖像,BMP位圖中有256個(gè)數(shù)據(jù)結(jié)構(gòu)RGBQUAD,一個(gè)調(diào)色板占用4字節(jié)數(shù)據(jù),所以256色圖像的調(diào)色板長(zhǎng)度為256*4為1024字節(jié)。
  • 當(dāng)biBitCount=16,24或32時(shí),沒(méi)有顏色表。

4. 位圖數(shù)據(jù)

位圖數(shù)據(jù)記錄了位圖的每一個(gè)像素值。

像素是從下到上、從左到右保存的。

每個(gè)像素使用一個(gè)或者多個(gè)字節(jié)表示。

如果一個(gè)圖像水平線的字節(jié)數(shù)不是4的倍數(shù),這行就使用空字節(jié)補(bǔ)齊,通常是ASCII碼0。

例如:

1、一張5 * 6的圖片,有30個(gè)pixels,因?yàn)榱袛?shù)6不是4的倍數(shù),所以會(huì)顯示成:
xxxxxx00 xxxxxx00 xxxxxx00 xxxxxx00 xxxxxx00
其中,x代表調(diào)色盤的編號(hào),0代表補(bǔ)齊的空字節(jié)

2、一張4 * 4的圖片,有16個(gè)pixels,因?yàn)榱袛?shù)剛好是4的倍數(shù),所以會(huì)顯示成:
xxxx xxxx xxxx xxxx

C語(yǔ)言讀取和存儲(chǔ)bmp示例代碼

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

typedef struct
{
    uint16_t type;
    uint32_t size;
    uint16_t reserved1;
    uint16_t reserved2;
    uint32_t off_bits;
}__attribute__ ((packed)) bmp_file_header_t;

typedef struct
{
    uint32_t size;
    int32_t width;
    int32_t height;
    uint16_t planes;
    uint16_t bit_count;
    uint32_t compression;
    uint32_t size_image;
    uint32_t x_pels_permeter;
    uint32_t y_pels_permeter;
    uint32_t clr_used;
    uint32_t clr_important;
} bmp_info_header_t;

static bmp_file_header_t s_bmp_file_header = { 0x4d42, 0, 0, 0, 0 };
static bmp_info_header_t s_bmp_info_header = { 0, 0, 0, 1, 8, 0, 0, 0, 0, 0, 0 };

static uint8_t s_bmpdata[200 * 200] = { 0 };
static uint32_t s_bmp_col = 0;
static uint32_t s_bmp_row = 0;
char in_file_path[256] = "in.bmp";
char out_file_path[256] = "out.bmp";

int32_t bmp_file_to_image(const char *file_path, uint8_t *image, uint32_t *col, uint32_t *row)
{
    FILE *file = NULL;
    uint32_t line_width = 0;
    uint32_t width = 0;
    uint32_t height = 0;
    int32_t err = 0;
    uint8_t buf[200 * 200] = { 0 };
    char temp[2048] = { 0 };
    int i = 0;

    do {
        if (NULL == file_path || NULL == image)
        {
            err = -1;
            break;
        }
        printf("[%s] file_path = %s\n", __func__, file_path);

        file = fopen(file_path, "rb");
        if (NULL == file)
        {
   err = -1;
            break;
        }
        fread(&s_bmp_file_header, sizeof(s_bmp_file_header), 1, file);

        fread(&s_bmp_info_header, sizeof(s_bmp_info_header), 1, file);
        fread(temp, 4*256, 1, file);
        width = s_bmp_info_header.width;
        height = s_bmp_info_header.height;
        *col = width;
        *row = height;
        line_width = (width + 3) / 4 * 4;
        printf("[%s] line_width = %d, width = %d, height = %d\n", __func__, line_width, width, height);

        for (i = height - 1; i >= 0; i--)
        {
   if (line_width == width)
   {
    fread(buf + i * width, width, 1, file);
      }
      else if (line_width > width)
   {
    fread(buf + i * width, width, 1, file);
    fread(temp, line_width-width, 1, file);
   }
        }
        memcpy(image, buf, width * height);

    } while (0);

    if (file != NULL)
    {
        fclose(file);
    }
    return err;
}

int32_t dump_image_to_bmp_file(const char *file_path, uint8_t *image, uint32_t width, uint32_t height)
{
    FILE *file = NULL;
    int32_t err = 0;

    do {
        if (NULL == file_path || NULL == image)
        {
            err = -1;
            break;
        }

        uint32_t line_width = (width + 3) / 4 * 4;
        s_bmp_file_header.off_bits = sizeof(bmp_file_header_t) + sizeof(bmp_info_header_t)
                + 4 * 256;
        s_bmp_file_header.size = s_bmp_file_header.off_bits + line_width * height;

        s_bmp_info_header.size = sizeof(bmp_info_header_t);
        s_bmp_info_header.width = width;
        s_bmp_info_header.height = height;
        s_bmp_info_header.size_image = line_width * height;

        printf("[%s] line_width = %d, width = %d, height = %d\n", __func__, line_width, width, height);

        file = fopen(file_path, "wb");
        if (NULL == file)
        {
   err = -1;
            break;
        }

        fwrite(&s_bmp_file_header.type, 1, sizeof(s_bmp_file_header.type), file);
        fwrite(&s_bmp_file_header.size, 1, sizeof(s_bmp_file_header.size), file);
        fwrite(&s_bmp_file_header.reserved1, 1, sizeof(s_bmp_file_header.reserved1), file);
        fwrite(&s_bmp_file_header.reserved2, 1, sizeof(s_bmp_file_header.reserved2), file);
        fwrite(&s_bmp_file_header.off_bits, 1, sizeof(s_bmp_file_header.off_bits), file);

        fwrite(&s_bmp_info_header, 1, sizeof(bmp_info_header_t), file);
        uint8_t alpha = 0;
        int32_t i;
        for (i = 0; i < 256; i++)
        {
            fwrite(&i, 1, sizeof(uint8_t), file);
            fwrite(&i, 1, sizeof(uint8_t), file);
            fwrite(&i, 1, sizeof(uint8_t), file);
            fwrite(&alpha, 1, sizeof(uint8_t), file);
        }

        for (i = height - 1; i >= 0; i--)
        {
            fwrite(image + i * width, 1, width, file);
            if (line_width > width)
            {
                uint8_t line_align[4] = { 0 };
                fwrite(line_align, 1, line_width - width, file);
            }
        }

        fflush(file);
    } while (0);

    if (file != NULL)
    {
        fclose(file);
    }

    return err;
}

int main()
{
 int32_t err = 0;
 err = bmp_file_to_image(in_file_path, s_bmpdata, &s_bmp_col, &s_bmp_row);
 if (err != 0)
 {
  return -1;
    }
 printf("[%s] s_bmp_col = %d, s_bmp_row = %d\n", __func__, s_bmp_col, s_bmp_row);
 dump_image_to_bmp_file(out_file_path, s_bmpdata, s_bmp_col, s_bmp_row);
 return 0;
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 弦圖ZOJ 1015 Fishing Net 判定方法

    弦圖ZOJ 1015 Fishing Net 判定方法

    弦圖,算法完全按照CDQ的PPT上給的最大勢(shì)算法(MCS)完美消除序列..需要的朋友可以參考下
    2012-11-11
  • opencv實(shí)現(xiàn)定時(shí)錄像功能

    opencv實(shí)現(xiàn)定時(shí)錄像功能

    這篇文章主要為大家詳細(xì)介紹了opencv實(shí)現(xiàn)定時(shí)錄像功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Vscode Remote Development遠(yuǎn)程開發(fā)調(diào)試的實(shí)現(xiàn)思路

    Vscode Remote Development遠(yuǎn)程開發(fā)調(diào)試的實(shí)現(xiàn)思路

    這篇文章主要介紹了Vscode Remote Development遠(yuǎn)程開發(fā)調(diào)試的相關(guān)資料,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • C++設(shè)計(jì)模式之代理模式

    C++設(shè)計(jì)模式之代理模式

    這篇文章主要介紹了C++設(shè)計(jì)模式之代理模式,本文講解了什么是代理模式、代理模式的使用場(chǎng)合、代理模式的實(shí)現(xiàn)代碼等內(nèi)容,需要的朋友可以參考下
    2014-10-10
  • opengl繪制五星紅旗

    opengl繪制五星紅旗

    這篇文章主要為大家詳細(xì)介紹了opengl繪制五星紅旗的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • C++實(shí)現(xiàn)LeetCode(31.下一個(gè)排列)

    C++實(shí)現(xiàn)LeetCode(31.下一個(gè)排列)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(31.下一個(gè)排列),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • VC程序在Win32環(huán)境下動(dòng)態(tài)鏈接庫(kù)(DLL)編程原理

    VC程序在Win32環(huán)境下動(dòng)態(tài)鏈接庫(kù)(DLL)編程原理

    這篇文章主要介紹了VC程序在Win32環(huán)境下動(dòng)態(tài)鏈接庫(kù)(DLL)編程原理,包括了dll文件的原理與具體實(shí)現(xiàn)過(guò)程,對(duì)于深入掌握VC程序設(shè)計(jì)具有很好的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-10-10
  • C++實(shí)現(xiàn)對(duì)回收站里的文件進(jìn)行操作的示例代碼

    C++實(shí)現(xiàn)對(duì)回收站里的文件進(jìn)行操作的示例代碼

    這篇文章主要為大家詳細(xì)介紹了C++如何使用代碼對(duì)回收站里的文件進(jìn)行操作,譬如文件的刪除與恢復(fù)等,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • C語(yǔ)言入門的一些基本資源推薦和程序語(yǔ)法概覽

    C語(yǔ)言入門的一些基本資源推薦和程序語(yǔ)法概覽

    這篇文章主要介紹了C語(yǔ)言入門的一些基本資源推薦和程序語(yǔ)法概覽,C語(yǔ)言是很多現(xiàn)代高級(jí)編程語(yǔ)言的基礎(chǔ),需要的朋友可以參考下
    2015-12-12
  • C語(yǔ)言中關(guān)于scanf函數(shù)的一些問(wèn)題詳解

    C語(yǔ)言中關(guān)于scanf函數(shù)的一些問(wèn)題詳解

    這篇文章主要為大家介紹了C語(yǔ)言中關(guān)于scanf函數(shù)的一些問(wèn)題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-12-12

最新評(píng)論