【问题标题】:c++: Convert 24bpp to 8 bpp or 1bpp imagec++: 将 24bpp 转换为 8 bpp 或 1bpp 图像
【发布时间】:2015-01-21 00:28:14
【问题描述】:

我必须根据颜色表将24bpp 图像转换为1bpp 图像或8bpp 图像。在任何一种情况下,调用者都需要一个unsigned char*(这将被进一步处理,或者现在可能通过将BITMAPINFOHEADER.biBitCount 发送到其适当的值8 或1 来调试输出)。

我有将颜色索引提取到调色板的代码(colorIndexArray 来自颜色转换或抖动算法)...我可以获得 8bpp 位图的信息...

但我的问题是,我不知道如何将这些信息放入 1bpp 位图

typedef struct {
    unsigned int size;
    unsigned char* pixels;
} ColorIndexArray;

unsigned char* convertImage(const ColorIndexArray& colorIndexArray, unsigned int paletteSize)
{
    unsigned char* outputImage;
    if (paleteSize > 2)
    {
        outputImage = (unsigned char*)LocalAlloc(LPTR, colorIndexArray.size);
        for (int i=0; i<colorIndexArray.size; i++)
            *(outputImage+i) = colorIndexArray.pixels[i];  
        // this works great              
    }
    else  // monochrome, caller has palette colors likely b/w (or purple/magenta or anything), must be 1bpp
    {
        outputImage = (unsigned char*)LocalAlloc(LPTR, colorIndexArray.size / 8);
        // how can i place the unsigned char* info (which is already 
        // determined based on desired algorithm, representing index in 
        // color table) into the output image inside a single bit ?
        // (obviously its value for a monochrome image would be 0 or 1 but    
        // it is saved as unsigned char* at the algorithm output) 
        // And how do I advance the pointer ?
        // Will it be type safe ? Aligned to byte ? or do I have to fill 
        // with something at the end to make multiple of 8 bits ?
    }

    return outputImage;
}

在评论建议后尝试这个:

#include <GdiPlus.h>
....
else {
    Gdiplus::Bitmap monoBitmap(w, h, PixelFormat1bppIndexed);
    Gdiplus::BitmapData monoBitmapData;
    Gdiplus::Rect rect(0, 0, w, h);
    monoBitmap.LockBits(&rect, Gdiplus::ImageLockModeWrite, PixelFormat1bppIndexed, &monoBitmapData);
    outputImage = (unsigned char*)monoBitmapData.Scan0;

    for (unsigned int y = 0; y < h; y++)
    {
        for (unsigned int x = 0; x < w; x++)
        {
            if (colorIndexArray.pixels[x + y * w])
                outputImage[y*monoBitmapData.Stride + x / 8] |= (unsigned char)(0x80 >> (x % 8));
        }           
    }
    monoBitmap.UnlockBits(&monoBitmapData); 
}
return outputImage;

(也需要为outputImage分配内存)

【问题讨论】:

  • 一个 1bpp 图像有一个包含 2 个条目的调色板。一些用于编码像素is here 的示例代码。不要忘记步伐。
  • @HansPassant:感谢您的建议-我不知道如何获取创建 Gdiplus 位图所需的所有信息-如何在 c++ 中获取 Scan0、Stride、LockBits...-还有,如果我添加 GdiPlus 库会不会增加很多开销?
  • 您不必使用 gdiplus,我没有推荐它,只是向您指出了一些乱七八糟的示例代码。然而,不这样做毫无意义。
  • 我正在努力让它发挥作用(请参阅更新),但如果有替代品,我会很乐意使用它们。
  • 你已经远远超出了你的舒适区。在你工作的公司里没有人可以帮助你吗?不要害怕寻求帮助,对于一个共同努力完成工作的优秀团队来说,SO 是一个非常糟糕的替代品。您只需将 gdiplus.lib 添加到链接器的 Additional Dependencies 设置中。

标签: c++ image bitmap byte monochrome


【解决方案1】:

根据 Hans Passant 建议的示例(也感谢您指出步幅的重要性),我写了这个小转换

unsigned long stride = (((w + 31) & ~31) >> 3); 

outputImage = (unsigned char*)LocalAlloc(LPTR, stride * h);

for (unsigned int y = 0; y < h; y++)
{           
    unsigned char* b = (unsigned char*)LocalAlloc(LPTR, stride);
    for (unsigned int x = 0; x < w; x++)
        if (colorIndexArray.pixels[x + y * w])
            b[x / 8] |= (unsigned char)(0x80 >> (x % 8));               
    CopyMemory(outputImage + stride * y, b, stride);
}

【讨论】:

    猜你喜欢
    • 2013-02-25
    • 2014-08-09
    • 1970-01-01
    • 2013-06-16
    • 2019-12-03
    • 2016-05-18
    • 2012-10-19
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多