美文网首页
图形图像基础知识(3)---- Bmp/Tga 图像格式分析

图形图像基础知识(3)---- Bmp/Tga 图像格式分析

作者: 特立独行的佩奇 | 来源:发表于2022-09-28 22:43 被阅读0次

BMP图像格式

BMP图像格式位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,占用的空间也比较大,BMP格式特点r如下:

  • 图形颜色深度 BitsPerPixel 可以选择为1bit,4bit,8bit,24bit
  • 图像的扫描方式是按从左到右、从下到上的顺序
  • 图形可以选择支持调色板,即采用颜色索引的方式

非压缩格式的BMP包含一个简单的格式头文件共54字节,包含BMP图像的宽、高、压缩方法,以及定义颜色等信息
以下面的图为例:

demoimage.jpg
文件头的信息如下:
bmp_header.jpg

BMP文件头信息含义如下:


bmp_header.jpg

示例代码(读取和写入文件头):

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <jpeglib.h>
#include "utils.h"

typedef struct __attribute__ ((__packed__)) tagBITMAPFILEHEADER
{
    unsigned short bfType;
    unsigned int bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned int bfOffBits;
}BITMAPFILEHEADER;

typedef struct __attribute__ ((__packed__)) tagBITMAPINFOHEADER
{
    unsigned int biSize;
    int biWidth;
    int biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned int biCompression;
    unsigned int biSizeImage;
    unsigned int biXPelsPerMeter;
    unsigned int biYPelsPerMeter;
    unsigned int biClrUsed;
    unsigned int biClrImportant;
}BITMAPINFOHEADER;

typedef struct __attribute__ ((__packed__)) tagRGBPLATE
{
    unsigned char rgbBlue;
    unsigned char rgbGreen;
    unsigned char rgbRed;
    unsigned char rgbReserved;
}RGBPLATE;

unsigned char* load_bmp(char* file_name, int *width, int *height)
{
    BITMAPFILEHEADER file_header;
    BITMAPINFOHEADER info_header;
    int h, w, i, j, offset, bpp, stride;
    FILE *file;
    unsigned char* buf = NULL, *buf_ptr;

    file=fopen(file_name,"rb");
    if (!file){
        printf("ERROR: cannot open file %s\n", file_name);
        return NULL;
    }
    fread(&file_header,1,sizeof(BITMAPFILEHEADER), file);
    fread(&info_header,1,sizeof(BITMAPINFOHEADER), file);
    fseek(file, file_header.bfOffBits, SEEK_SET);

    printf("bmp bfOffBits:%d biBitCount:%d biWidth:%d biHeight:%d\n",
            file_header.bfOffBits, info_header.biBitCount, info_header.biWidth, info_header.biHeight);
 
    w=info_header.biWidth;
    h=info_header.biHeight;
    bpp=info_header.biBitCount/8;
    buf = (unsigned char*)malloc(w*h*bpp);
    stride = w*bpp;
        //注意bmp 是从下到上读取的
    buf_ptr = buf + stride*(h-1);
    for(j=0; j<h; j++){
        for(i=0; i<w; i++){
            fread(buf_ptr+i*bpp+2, 1, 1, file);
            fread(buf_ptr+i*bpp+1, 1, 1, file);
            fread(buf_ptr+i*bpp+0, 1, 1, file);
        }
        buf_ptr -= stride;
    }

    fclose(file);

    if(width!=NULL)
        *width = w;
    if(height!=NULL)
        *height = h;
    return buf;
}

void store_bmp(char* file_name, unsigned char* raw_buf, int width, int height)
{
    int i, j, stride;
    unsigned char *buf_ptr;
    FILE *file;
    BITMAPFILEHEADER file_header;
    BITMAPINFOHEADER info_header;

    memset(&file_header, 0x0, sizeof(BITMAPFILEHEADER));
    memset(&info_header, 0x0, sizeof(BITMAPINFOHEADER));

    file_header.bfType = 0x4D42;
    file_header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    file_header.bfSize = file_header.bfOffBits + width*height*3;

    info_header.biSize = sizeof(BITMAPINFOHEADER);
    info_header.biWidth = width;
    info_header.biHeight = height;
    info_header.biPlanes = 1;
    info_header.biCompression = 0;
    info_header.biBitCount = 24;
    info_header.biSizeImage = width*height*3;

    file=fopen(file_name,"wb");
    if (!file){
        printf("ERROR: cannot open file %s\n", file_name);
        return;
    }
    fwrite(&file_header, 1, sizeof(BITMAPFILEHEADER), file);
    fwrite(&info_header, 1, sizeof(BITMAPINFOHEADER), file);

    stride = width*3;
    buf_ptr = raw_buf+(height-1)*stride;
    for(j=0; j<height; j++){
        for(i=0; i<width; i++){
            fwrite(buf_ptr+i*3+2, 1, 1, file);
            fwrite(buf_ptr+i*3+1, 1, 1, file);
            fwrite(buf_ptr+i*3+0, 1, 1, file);
        }
        buf_ptr -= stride;
    }
    fclose(file);
}

TGA 图像格式

TGA(Targa)格式是计算机上应用最广泛的图象格式,在兼顾了BMP的图象质量的同时又兼顾了JPEG的体积优势,TGA 文件后缀名为 tga,主要特点如下:

  • 同时支持压缩和非压缩算法
  • 最该支持4个通道的颜色,支持 Alpha 通道
  • 通过一个18字节的头来标志 tga 文件,文件尾是可选的

tag 文件头的格式信息如下:


tgafileheader.jpg

以下面的图为例,对照tga 文件的头字段:


demo.jpg tag_02.jpg
元素 说明
第3-4个字节 0x02: 表示非压缩RGB格式
第13-14个字节 0x01f4: 图像宽度为 500
第15-16个字节 0x01f4: 图像高度为 500
第17个字节 0x18 图像每个Pixel 占用3字节
第18个字节 0x20 图像描述Bit

示例代码如下:

#pragma pack(1)  //在linux C中改为__attribute__ ((__packed__)) 
    struct TgaHeader
    {
        uint8_t id;
        uint8_t color_map;
        uint8_t image_type;
        uint16_t first_map_entry;
        uint16_t num_colors;
        uint8_t bits_per_palette_entry;
        uint16_t x_origin;
        uint16_t y_origin;
        uint16_t width;
        uint16_t height;
        uint8_t  bitsPerPixel;
        uint8_t  descriptor_bits;
    };

    struct TgaFooter {
        uint32_t extension_offset;
        uint32_t dev_area_offset;
        const char signature[18];
    };
#pragma pack()

void imageDumper::dumpTgaFile(uint32_t width, uint32_t height, uint32_t stride) {

    FILE *outfile = fopen(Name.c_str(), "wb");
    if (outfile) {
        TgaHeader header;
        TgaFooter footer = { 0,0,"TRUEVISION.XFILE." };
        memset(&header, 0, sizeof(header));

        header.image_type = 2;
        header.width = width;
        header.height = height;
        header.descriptor_bits = 0x20;
        // RGB888:24bits ARGB8888:32bit
        header.bitsPerPixel = 24;

        cout << "sizeof tga header :" << sizeof(header) << endl;
        cout << "sizeof tga footer :" << sizeof(footer) << endl;

        fwrite(&header, sizeof(header), 1, outfile);

        for (uint32_t i = 0; i < width; i++) {
            for (uint32_t j = 0; j < height; j++) {
                uint8_t Pixel[3];
                char* Psrc = &srcMem[i*stride + 3 * j];
                uint32_t nwrite;
                Pixel[0] = Psrc[0];
                Pixel[1] = Psrc[1];
                Pixel[2] = Psrc[2];
                nwrite = fwrite(Pixel, sizeof(uint8_t), sizeof(Pixel), outfile);
                if (nwrite != sizeof(Pixel))
                    cout << "Error Write Pixels" << endl;
               }
        }
        //fwrite(&footer, sizeof(footer), 1, outfile);
        fclose(outfile);
        cout << "dump to tga file success" << endl;
    }


相关文章

网友评论

      本文标题:图形图像基础知识(3)---- Bmp/Tga 图像格式分析

      本文链接:https://www.haomeiwen.com/subject/bnkbirtx.html