高手请进!关于用C语言读取24位BMP图的问题

little_0ne 2015-11-09 09:36:10
是这样的,我想把一张24位的bmp的像素分别存到3个一维数组R[ ],G[ ],B[ ]里,但是输出某一行的R,G,B后发现有错位,后来百度了一下,原因是BMP存放时遵循了对齐原则,因为长度不是4的倍数所以进行了比特填充,而我没有注意到这个问题,错把一些填充位也读到了RGB数组里,导致了错位。搞了一天都不知道怎么跳过填充位,求高手帮忙解答。
现在已经得到了该位图数据的宽度和高度:bmpWidth与bmpHeight
这个是小弟的代码,求帮忙
void separate(unsigned char* imgBuf, int* R,int* G,int* B,int lineByte) //imgBuf是读取图像数据的指针, lineByte是每行像素所占字节数
{
int i, j;
//int k = 0;
for (i = 0; i < bmpHeight; i++)
{
for (j = 0; j < bmpWidth; j++)
{
R[i*bmpWidth + j] = *(imgBuf + i*lineByte + j * 3 + 2);
G[i*bmpWidth + j] = *(imgBuf + i*lineByte + j * 3 + 1);
B[i*bmpWidth + j] = *(imgBuf + i*lineByte + j * 3 + 0);
//k++;
}
}
//printf("\nthe value of k is %d\n", k);
}
...全文
214 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
little_0ne 2015-11-10
  • 打赏
  • 举报
回复
这么说吧,怎么把一个24位图的位图数据中的每个像素都拆分成3部分分别存入R, G, B, 三个数组里,就是把一张图拷到R G B三个数组里然后分别操作完再用RGB三个数组合成另一张图,贴个代码上来,用到的变量帮我注释一下它的意义,不胜感激
ID870177103 2015-11-10
  • 打赏
  • 举报
回复
实际上有填充位,比如16图,你发现它最高位总为0,因为rgb每个5位 但是32位图的高8位不是填充位,那个是alpha位,标志每个像素点的不透明度,你可以想想png 因为一个字节是8位,所以像8位对齐,这就是为什么15位图要16位来储存
little_0ne 2015-11-10
  • 打赏
  • 举报
回复
引用 5 楼 ID870177103 的回复:
没有填充位!!! BITMAPINFOHEADER指定了biBitCount 如果为8,黑白图,r[i]=b[i]=g[i]=bmp[i] 如果为16,bmp[i]=(r[i]&0x1f<<10)|(g[i]&0x1f<<5)|b[i]&0x1f 如果为24,bmp[i]=(r[i]<<16)|(g[i]<<8)|b[i] 如果为32,带通道alpha,bmp[i]=(
alpha[i]<<24)(r[i]<<16)|(g[i]<<8)|b[i]
这个没有填充位是什么意思,因为24位的像素的字节恒为24的倍数所以无论行宽是多少都可以整除4是吗,我也这么想过,那所有的bmp图岂不是都没有填充位了?
ID870177103 2015-11-10
  • 打赏
  • 举报
回复
没有填充位!!! BITMAPINFOHEADER指定了biBitCount 如果为8,黑白图,r[i]=b[i]=g[i]=bmp[i] 如果为16,bmp[i]=(r[i]&0x1f<<10)|(g[i]&0x1f<<5)|b[i]&0x1f 如果为24,bmp[i]=(r[i]<<16)|(g[i]<<8)|b[i] 如果为32,带通道alpha,bmp[i]=(
alpha[i]<<24)(r[i]<<16)|(g[i]<<8)|b[i]
little_0ne 2015-11-10
  • 打赏
  • 举报
回复
引用 2 楼 fly_dragon_fly 的回复:
int *rgb[]={B,G,R};
    int pad =lineByte - bmpWidth *3;
    unsigned char* imgBufEnd =imgBuf +(bmpHeight-1)*lineByte;
    while(imgBuf<imgBufEnd){
        for(int i=0;i<bmpWidth;i++)
            for(int j=0;j<3;j++)
                *rgb[j]++ =*imgBuf++;
        imgBuf +=pad;
    }
这个代码勉强看懂了,但是贴回我的工程文件里跑出来的结果所有的RGB都是cdcdcdcdcd,而且我觉得这个好像还是没有解决填充位的问题啊
little_0ne 2015-11-10
  • 打赏
  • 举报
回复
[quote=引用 1 楼 an112 的回复:] 你把循环里面的j*3都改为j*4 你循环里面这样赋值正确么? 我i*3的意思是每个像素3个字节的意思,就是跳过它前面的像素,然后+0是B,+1是R,+2是G, 不知道大哥如何理解,望指教
fly_dragon_fly 2015-11-10
  • 打赏
  • 举报
回复
int *rgb[]={B,G,R};
    int pad =lineByte - bmpWidth *3;
    unsigned char* imgBufEnd =imgBuf +(bmpHeight-1)*lineByte;
    while(imgBuf<imgBufEnd){
        for(int i=0;i<bmpWidth;i++)
            for(int j=0;j<3;j++)
                *rgb[j]++ =*imgBuf++;
        imgBuf +=pad;
    }
赵4老师 2015-11-10
  • 打赏
  • 举报
回复
仅供参考:
#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")

using namespace std;
using namespace Gdiplus;

int main() {
    GdiplusStartupInput gdiplusstartupinput;
    ULONG_PTR gdiplustoken;
    GdiplusStartup(&gdiplustoken, &gdiplusstartupinput, NULL);

    wstring infilename(L"1.jpg");
    string outfilename("color.txt");

    Bitmap* bmp = new Bitmap(infilename.c_str());
    UINT height = bmp->GetHeight();
    UINT width  = bmp->GetWidth();
    cout << "width " << width << ", height " << height << endl;

    Color color;
    ofstream fout(outfilename.c_str());

    for (UINT y = 0; y < height; y++)
    for (UINT x = 0; x < width ; x++) {
            bmp->GetPixel(x, y, &color);
            fout << x << "," << y << ";"
                 << (int)color.GetRed()   << ","
                 << (int)color.GetGreen() << ","
                 << (int)color.GetBlue()  << endl;
    }

    fout.close();

    delete bmp;
    GdiplusShutdown(gdiplustoken);
    return 0;
}
Apricotly_wait 2015-11-10
  • 打赏
  • 举报
回复
你把循环里面的j*3都改为j*4 你循环里面这样赋值正确么?
fly_dragon_fly 2015-11-10
  • 打赏
  • 举报
回复
引用 4 楼 little_0ne 的回复:
[quote=引用 2 楼 fly_dragon_fly 的回复:]
int *rgb[]={B,G,R};
    int pad =lineByte - bmpWidth *3;
    unsigned char* imgBufEnd =imgBuf +(bmpHeight-1)*lineByte;
    while(imgBuf<imgBufEnd){
        for(int i=0;i<bmpWidth;i++)
            for(int j=0;j<3;j++)
                *rgb[j]++ =*imgBuf++;
        imgBuf +=pad;
    }
这个代码勉强看懂了,但是贴回我的工程文件里跑出来的结果所有的RGB都是cdcdcdcdcd,而且我觉得这个好像还是没有解决填充位的问题啊[/quote]pad就是跳过填充的部分, 你的lineByte有没有算正确对齐到4字节, 比如宽度为10, 那么linebyte应为32不是30 lineByte =(bmpWidth*3+3)&~3

3,882

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧