生成按色调饱和度排列的BMP位图

来源:互联网 发布:java和java大数据区别 编辑:程序博客网 时间:2024/06/05 00:15

1、首先需要了解BMP文件的结构

生成的BMP为32位真彩色图像(一个像素4个字节BGRA),所以不需要调色板。
2、还需要了解的是HSB和RGB的转换公式


3、程序代码
1、bmp.h

#pragma once#include <string>typedef long            LONG;typedef unsigned long   DWORD;typedef int             BOOL;typedef unsigned char   BYTE;typedef unsigned short  WORD;typedef BYTE            *LPBYTE;typedef DWORD           *LPDWORD;#pragma pack(1)typedef struct  tagBITMAPFILEHEADER{      WORD    bfType;             // 文件类型,必须是0x424D,即字符“BM”       DWORD   bfSize;             // 文件大小       WORD    bfReserved1;        // 保留字       WORD    bfReserved2;        // 保留字       DWORD   bfOffBits;          // 从文件头到实际位图数据的偏移字节数   }BITMAPFILEHEADER;              // 位图文件头定义 typedef struct tagBITMAPINFOHEADER{      DWORD   biSize;             // 信息头大小       LONG    biWidth;            // 图像宽度       LONG    biHeight;           // 图像高度       WORD    biPlanes;           // 位平面数,必须为1       WORD    biBitCount;         // 每像素位数: 1, 2, 4, 8, 16, 24, 32    DWORD   biCompression;      // 压缩类型       DWORD   biSizeImage;        // 压缩图像大小字节数       LONG    biXPelsPerMeter;    // 水平分辨率       LONG    biYPelsPerMeter;    // 垂直分辨率       DWORD   biClrUsed;          // 位图实际用到的色彩数       DWORD   biClrImportant;     // 本位图中重要的色彩数   }BITMAPINFOHEADER;              // 位图信息头定义   #pragma pack()// class BMP//// BMP is an image file format that stores bitmap digital images and retains // information for each pixel of the image. The BMP format stores color data // for each pixel in the image without any compression. For example, a 10x10 // pixel BMP image will include color data for 100 pixels. This method of // storing image information allows for crisp, high-quality graphics, but // also produces large file sizes. class BMP{    public:        BMP();        ~BMP();    public:        void    save(const std::string &location);        void    draw(const float bright);    private:        BITMAPFILEHEADER    *head;          BITMAPINFOHEADER    *info;          BYTE                *pixels;    // iamge pixel data  }; /* end for class BMP */

2、bmp.cpp

#include <iostream>#include <fstream>#include "bmp.h"BMP::BMP(){    head    = NULL;    info    = NULL;    pixels  = NULL;}BMP::~BMP(){    if (pixels != NULL)        delete[] pixels;    if (info != NULL)        delete info;    if (head != NULL)        delete head;}void BMP::draw(const float bright){    head = new BITMAPFILEHEADER;    info = new BITMAPINFOHEADER;    head = new BITMAPFILEHEADER;    info = new BITMAPINFOHEADER;    head->bfType = 0x4D42;              //从低位往高位读,反过来了    head->bfSize = 432054;              //总字节数    head->bfReserved1 = 0;    head->bfReserved2 = 0;    head->bfOffBits = 54;    info->biSize = 40;    info->biWidth = 360;    info->biHeight = 300;    info->biPlanes = 1;    info->biBitCount = 32;    info->biCompression = 0;    info->biSizeImage = 432000;         //360*300*4    info->biXPelsPerMeter = 0;    info->biYPelsPerMeter = 0;    info->biClrUsed = 0;    info->biClrImportant = 0;    unsigned long size = info->biWidth * info->biHeight * 4;    pixels = new BYTE[size];    auto p = pixels;    for (int s=0;s<300;s++)           //先绘制底部的像素,所以饱和度由小变大    {        for (int h=0;h<360;h++)        {            BYTE r, g, b;            if (h >= 0 && h < 60)            {                 r = BYTE(255 * bright);                 b = BYTE((1 - s / 300.0)*r);                 g = BYTE(h*(r - b) / 60.0 + b);            }            else if (h >= 60&&h<120)            {                g = BYTE(255 * bright);                b = BYTE((1 - s / 300.0)*g);                r = BYTE((120 - h)*(g - b) / 60.0 + b);            }             else if (h>=120&&h<180)            {                g = BYTE(255 * bright);                r = BYTE((1 - s / 300.0)*g);                b = BYTE((h - 120)*(g - r) / 60.0 + r);            }            else if (h >= 180 && h < 240)            {                b = BYTE(255 * bright);                r = BYTE((1 - s / 300.0)*b);                g = BYTE((240 - h)*(b - r) / 60.0 + r);            }            else if (h >= 240 && h < 300)            {                b = BYTE(255 * bright);                g = BYTE((1 - s / 300.0)*b);                r = BYTE((h-240)*(b - g) / 60.0 + g);            }            else if (h >= 300 && h < 360)            {                r = BYTE(255 * bright);                g = BYTE((1 - s / 300.0)*r);                b = BYTE((360 - h)*(r - g) / 60.0 + g);            }            *p = b;            p++;            *p = g;            p++;            *p = r;            p++;            *p = 0;            p++;        }    }}void BMP::save(const std::string &location){    std::ofstream file(location, std::ios::binary);    if (!file)    {        std::cout << "Failed to open or create bitmap file." << std::endl;        return;    }    if (head == NULL || info == NULL || pixels == NULL)    {        std::cout << "Failed to save bitmap file." << std::endl;        return;    }    file.write((char*)head, sizeof(BITMAPFILEHEADER));    file.write((char*)info, sizeof(BITMAPINFOHEADER));    file.write((char*)pixels, info->biWidth * info->biHeight * 4);}

3、main.cpp

#include"bmp.h"int main(){    BMP bmp;    bmp.draw(0.5);    bmp.save("0.5.bmp");    bmp.draw(0.8);    bmp.save("0.8.bmp");    bmp.draw(1.0);    bmp.save("1.0.bmp");    return 0;}

4、最终结果

                 0.5.bmp

                 0.8.bmp

                 1.0.bmp
0 0
原创粉丝点击