c++ bmp图像保存之后为全黑

发布于 2022-09-05 01:36:11 字数 2636 浏览 24 评论 0

最近自己做一个工具最后涉及到一个存储成bmp位图的形式,由于这部分并不是整个project的重点我就从网上找了例子改了改,但是目前的问题是有很多时候都是存储的bmp全黑,我也并不知道是怎么回事。就像这样:
图片描述

我的保存bmp的c++头文件:

#ifndef ImgSave_hpp
#define ImgSave_hpp

#include "stdlib.h"
#include "stdio.h"
#include <string>
#include <algorithm>

#define BI_RGB      0L

typedef struct __attribute__ ((__packed__))
{
    uint16_t Signature;
    uint32_t Size;
    uint32_t Reserved;
    uint32_t BitsOffset;
} BITMAPFILEHEADER2;

#define BITMAP_FILEHEADER_SIZE 14

typedef struct __attribute__ ((__packed__))
{
    uint32_t HeaderSize;
    int32_t Width;
    int32_t Height;
    uint16_t Planes;
    uint16_t BitCount;
    uint32_t Compression;
    uint32_t SizeImage;
    int32_t PelsPerMeterX;
    int32_t PelsPerMeterY;
    uint32_t ClrUsed;
    uint32_t ClrImportant;
} BITMAPINFOHEADER2;

bool MSaveImage(std::string szPathName, void* lpBits, int w, int h);

#endif /* ImgSave_hpp */

实现文件:

#include "ImgSave.hpp"

bool MSaveImage(std::string szPathName, void* lpBits, int w, int h)
{
    BITMAPINFOHEADER2 BMIH;
    BITMAPFILEHEADER2 bmfh;
    
    FILE *pFile = fopen(szPathName.c_str(), "wb");
    
    if(pFile == NULL)
    {
        return false;
    }
    
    BMIH.HeaderSize = sizeof(BITMAPINFOHEADER2);
    BMIH.Width = w;
    BMIH.Height = h;
    BMIH.Planes = 1;
    BMIH.BitCount = 24;
    BMIH.Compression = BI_RGB;
    BMIH.SizeImage = w * h* 3;
    
    int nBitsOffset = sizeof(BITMAPFILEHEADER2) + BMIH.HeaderSize;
    long lImageSize = BMIH.SizeImage;
    long lFileSize = nBitsOffset + lImageSize;
    bmfh.Signature = 'B'+('M'<<8);
    bmfh.BitsOffset = nBitsOffset;
    bmfh.Size = (int)lFileSize;
    bmfh.Reserved =0;
    
    fwrite(&bmfh, 1, sizeof(BITMAPFILEHEADER2), pFile);
    fwrite(&BMIH, 1, sizeof(BITMAPINFOHEADER2), pFile);
    fwrite(lpBits, 1, lImageSize, pFile);
    
    fclose(pFile);
    
    return true;
    
}

调用方式:

 unsigned char *bitmapImage;

    bitmapImage = (unsigned char*)malloc(width*height*3);
    
    for(i=0;i<pixelNum;i++){
        bitmapImage[i*3] = (unsigned char)(sourcePixels[i][0]);
        bitmapImage[i*3+1]=(unsigned char)(sourcePixels[i][1]);
        bitmapImage[i*3+2]=(unsigned char)(sourcePixels[i][2]);
    }
    
    string fname = targetPath;
    MSaveImage(fname, bitmapImage, width, height);

这个sourcePixels保证是没有问题的,是一张图片的正常信息。

最后保存出来就是全黑,自己暂时没有找到原因,所以请经验人士指点一二 谢谢。

补充:可能跟bmp的文件尾有关 但是具体我还是不是特别清楚

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

柠栀 2022-09-12 01:36:12

感觉是BITMAPINFOHEADER2定义的有问题,我贴一段正确的代码你对比一下:

bool HDCToFile(const wchar_t* pszFilePath, HDC srcDC, RECT rect, uint16_t bitsPerPixel = 24)
{
    uint32_t width = rect.right - rect.left;
    uint32_t height = rect.bottom - rect.top;

    BITMAPINFO bminfo;
    BITMAPFILEHEADER header;
    memset(&bminfo, 0, sizeof(bminfo));
    memset(&header, 0, sizeof(header));
    bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bminfo.bmiHeader.biWidth = width;
    bminfo.bmiHeader.biHeight = height;
    bminfo.bmiHeader.biPlanes = 1;
    bminfo.bmiHeader.biBitCount = bitsPerPixel;
    bminfo.bmiHeader.biCompression = BI_RGB;
    bminfo.bmiHeader.biSizeImage = width * height * (bitsPerPixel > 24 ? 4 : 3);
    header.bfType = 0x4D42;
    header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    char* Pixels = NULL;
    HDC hMemDC = CreateCompatibleDC(srcDC);
    HBITMAP hBitmap = CreateDIBSection(srcDC, &bminfo, DIB_RGB_COLORS, (void**)&Pixels, 0, 0);
    DeleteObject(SelectObject(hMemDC, hBitmap));
    BOOL success = BitBlt(hMemDC, 0, 0, width, height, srcDC, rect.left, rect.top, SRCCOPY);
    DeleteDC(hMemDC);

    if (success)
    {
        std::fstream hFile(pszFilePath, std::ios::binary | std::ios::out);
        if (hFile.is_open())
        {
            hFile.write((char*)&header, sizeof(header));
            hFile.write((char*)&bminfo.bmiHeader, sizeof(bminfo.bmiHeader));
            hFile.write(Pixels, (((bitsPerPixel * width + 31) & ~31) / 8) * height);
            hFile.close();
            DeleteObject(hBitmap);
            return true;
        }
    }

    DeleteObject(hBitmap);
    return false;
}

其中bitmapinfo的定义是:

typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER    bmiHeader;
    RGBQUAD             bmiColors[1];
} BITMAPINFO, FAR *LPBITMAPINFO, *PBITMAPINFO;

typedef struct tagBITMAPINFOHEADER{
        DWORD      biSize;
        LONG       biWidth;
        LONG       biHeight;
        WORD       biPlanes;
        WORD       biBitCount;
        DWORD      biCompression;
        DWORD      biSizeImage;
        LONG       biXPelsPerMeter;
        LONG       biYPelsPerMeter;
        DWORD      biClrUsed;
        DWORD      biClrImportant;
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;


typedef struct tagRGBQUAD {
        BYTE    rgbBlue;
        BYTE    rgbGreen;
        BYTE    rgbRed;
        BYTE    rgbReserved;
} RGBQUAD;

RGBQUAD bmiColors[1]; 的定义没有在你的代码里发现,你确认下是不是少了这个定义。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文