【问题标题】:c++ trouble with making a bitmap from scratchc++ 从头开始​​制作位图的麻烦
【发布时间】:2014-09-24 17:14:54
【问题描述】:

我正在尝试从头开始制作位图。我有一个BYTE RGB 值数组(大小已知),我想生成一个 HBITMAP。

为了进一步说明,我正在使用的字节数组是纯 RGB 值。

我已确保所有变量均已设置且正确,并且我认为问题与 lpvBits 有关。在过去的几天里,我一直在为此做大量的研究,但我找不到任何对我有意义的东西。

出于测试目的,width = 6height = 1

代码:

HBITMAP RayTracing::getBitmap(void){
    BYTE * bytes = getPixels();
    void * lpvBits = (void *)bytes;
    HBITMAP hBMP = CreateBitmap(width, height, 1, 24, lpvBits);
    return hBMP;
}
BYTE * RayTracing::getPixels(void){
    Vec3 * vecs = display.getPixels();
    BYTE * bytes;
    bytes = new BYTE[(3 * width * height)];
    for (unsigned int i = 0; i < (width * height); i++){
        *bytes = static_cast<BYTE>(vecs->x);
        bytes++;
        *bytes = static_cast<BYTE>(vecs->y);
        bytes++;
        *bytes = static_cast<BYTE>(vecs->z);
        bytes++;
        vecs++;
    }
    return bytes;
}

【问题讨论】:

  • 那么您预计会发生什么以及实际发生了什么?
  • 我正在尝试显示 HBITMAP,但没有任何显示,也没有错误。
  • 您是否对扫描线进行了字对齐? msdn.microsoft.com/en-us/library/dd183485(v=vs.85).aspx
  • @Deduplicator 我很难理解字对齐原始像素的含义
  • @MichaelMitchell:为每行像素分配的空间必须是 2 个字节的偶数倍。您正在创建 24 位位图。假设width 为 1。每条扫描线需要 3 个字节的像素数据和 1 个填充字节,因此您必须为数组分配 (3+1)*height 字节。如果 width 为 2,则每条扫描线将需要 6 个字节,这是对齐的,因此数组将需要 6*height 字节,依此类推。分配数组时,将width 乘以bits/8 并四舍五入到 2 的下一个最高倍数,并确保在用像素填充数组时考虑该填充

标签: c++ winapi bitmap


【解决方案1】:

您需要正确地对数组进行双字对齐,以便每行是 4 个字节的偶数倍,然后在填充数组时跳过这些字节:

HBITMAP RayTracing::getBitmap(void)
{
    BYTE * bytes = getPixels();
    HBITMAP hBMP = CreateBitmap(width, height, 1, 24, bytes);
    delete[] bytes;
    return hBMP;
}

BYTE * RayTracing::getPixels(void)
{
    Vec3 * vecs = display.getPixels(); // <-- don't forget to free if needed
    int linesize = ((3 * width) + 3) & ~3; // <- 24bit pixels, width number of pixels, rounded to nearest dword boundary
    BYTE * bytes = new BYTE[linesize * height];
    for (unsigned int y = 0; y < height; y++)
    {
        BYTE *line = &bytes[linesize*y];
        Vec3 *vec = &vecs[width*y];
        for (unsigned int x = 0; x < width; x++)
        {
            *line++ = static_cast<BYTE>(vec->x);
            *line++ = static_cast<BYTE>(vec->y);
            *line++ = static_cast<BYTE>(vec->z);
            ++vec;
        }
    }
    return bytes;
}

【讨论】:

    【解决方案2】:

    CreateBitmap 的第三个参数应该是 3,而不是 1。有三个颜色平面:Red、Green 和 Blue。

    此外,如果将高度设置为大于 1 的值,则需要用零填充每一行像素以使宽度成为 4 的倍数。因此,对于 6x2 图像,在保存 6*3 字节后对于第一行,您需要保存两个零字节以使该行长 20 个字节。

    【讨论】:

    • 我不确定。我相信它仍然应该是一个。此外,如果我将其更改为 3 而不是 1,则会出现运行时错误。
    • 我查了谷歌,看起来 CreateBitmap 是一个非常古老的函数,应该只用于单色位图。请改用 CreateDIBSection。
    • 1 是正确的值 - 检查文档中的 BITMAPINFOHEADER(“目标设备的平面数。此值必须设置为 1。”)
    • 每条扫描线的宽度需要对齐,即使高度为1。
    • 不要检查谷歌,检查MSDN。不仅仅是 CreateBitmap 太旧而无法创建彩色位图,而是颜色匹配很难。 CreateCompatibleBitmap 和 CreateDIBSection 稍微容易一些。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多