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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值