首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++:将24 bpp转换为8 bpp或1bpp图像

c++:将24 bpp转换为8 bpp或1bpp图像
EN

Stack Overflow用户
提问于 2015-01-16 19:01:29
回答 1查看 1.5K关注 0票数 1

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

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

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

代码语言:javascript
复制
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;
}

在评论建议之后尝试这样做:

代码语言:javascript
复制
#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分配内存)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-20 16:28:14

根据汉斯·帕桑特提出的例子(谢谢你也指出了这一步的重要性),我写了这个小小的转换。

代码语言:javascript
复制
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);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27990952

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档