2

我想读取 bmp 图像并在 GUI 窗口中绘制像素值,但它没有给我正确的结果,它显示的图片与原始图像完全不同,我不知道我哪里出错了。有什么帮助吗?

int main() {


char filename[100];
printf("Enter the bitmap image name:");

scanf("%s",filename);

 int i;
    FILE* f = fopen(filename, "rb");

    if(f == NULL)
        throw "Argument Exception";

    unsigned char info[54];
    fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header

    // extract image height and width from header
    int width = *(int*)&info[18];
    int height = *(int*)&info[22];

 int gdriver = DETECT, gmode;
  initgraph (&gdriver, &gmode,"");


    cout << "  Name: " << filename << endl;
    cout << " Width: " << width << endl;
    cout << "Height: " << height << endl;

    int row_padded = (width*3 + 3) & (~3);
    unsigned char* data = new unsigned char[row_padded];
    unsigned char tmp;


    for(int i = 0; i < height; i++)
    {
        fread(data, sizeof(unsigned char), row_padded, f);
        for(int j = 0; j < width; j += 3)
        {
            // Convert (B, G, R) to (R, G, B)
            tmp = data[j];
            data[j] = data[j+2];
            data[j+2] = tmp;

       int last=width*height;
       int index=last;


            cout << "R: "<< (int)data[j] << " G: " << (int)data[j+1]<< " B: " << (int)data[j+2]<< endl;

            cout <<((data[j] & 0xff) << 16) + ((data[j+1] & 0xff) << 8) + (data[j+2] & 0xff);

            cout<<"number of time" <<i;

unsigned long rgb = 0xFA09CA;

rgb =((data[j] & 0xff) << 16) + ((data[j+1] & 0xff) << 8) + (data[j+2] & 0xff);


  putpixel(j,i,data[j]);

                putpixel(j,i,data[j+1]);

                putpixel(j,i,data[j+1]);


        }
    }

getch();
}
4

3 回答 3

0
putpixel(j,i,data[j]);
 putpixel(j,i,data[j+1]);
 putpixel(j,i,data[j+1]);  

您非常坚持[j][i]要更改像素,以至于您要写入相同的像素位置 3 次。

是否有像素流,每次写入将像素放入队列或流中(如 SPI 总线接口)?

最后一行看起来也不正确。我相信它应该是data[j+2],但我不知道。

可能还有其他问题,但我无法在您的代码上使用我的调试器

于 2015-05-01T23:30:26.190 回答
0

这段代码似乎是使用 Borland 的 BGI 库在 MS DOS 下绘制图形。事实上,你已经为autodetect你的显卡指定了,它将把它初始化为 VGA 16 调色板和平面模式(除非你使用的是 EGA 卡或更旧的卡)。

稍后,您正在从 BMP 中读取看起来是 24 位彩色图像的内容,并进行像素化处理,好像 BGI 将支持 24 位(它不支持)。

所以你的程序需要大量重写:

  • 初始化图形并检查结果值以查看计算机的图形模式。
  • 打开 BMP,读取其属性,如果它在当前图形模式下不适合您的屏幕,或者它不是调色板图像,或者颜色数(调色板条目)大于您的图形模式支持的数量,则将其拒绝.
  • 从 BMP 读取调色板,将其调整为每原色 6 位并更新调色板寄存器
  • 从 BMP 中读取像素,并 putpixel 他们,考虑到 BMP 图片是倒置存储的

这只是一个基本的显示程序。更通用的解决方案将要求您添加代码以调整平移图像的大小以将其显示在屏幕上。此外,您必须检查图片是否为真彩色格式,如果是,请执行一些抖动以将颜色数量减少到图形模式中可用的最大颜色数量,然后为每个颜色分配一个调色板条目。

例如,考虑这个显示 RAW 图像文件的简单程序。RAW文件假定为640x480像素,每个像素有3个字节对应其红、绿、蓝的等级,依次排列。图片需要事先进行颜色降级,最多有16种不同的颜色。该程序读取像素并将其颜色分配给调色板索引。如果调色板中已存在新像素,则其索引用于putpixel. 如果不是,则将其颜色添加到调色板,更新硬件调色板,并在putpixel.

#include <conio.h>
#include <graphics.h>
#include <stdio.h>
#include <dos.h>

typedef struct
{
  unsigned char r;
  unsigned char g;
  unsigned char b;
} RGB;

void setvgapalette (int entry, RGB *val);

int main()
{
  int gdriver = VGA;
  int gmodo = VGAHI;
  RGB palette[16];
  int indxp = 0;
  FILE *f;
  RGB pixel;
  int x, y, i;

  initgraph (&gdriver, &gmodo, "c:\\comp\\tc\\bgi");

  f = fopen ("PICTURE.RAW", "rb");

  fread (&pixel.r, 1, 1, f);  //
  fread (&pixel.g, 1, 1, f);  // Read one pixel (first one)
  fread (&pixel.b, 1, 1, f);  //
  x = 0;
  y = 0;
  while (!feof(f))
  {
    for (i=0;i<indxp;i++)  // search pixel color in current palette
    {
      if (palette[i].r == pixel.r &&
          palette[i].g == pixel.g &&
          palette[i].b == pixel.b)
            break;         // if found, finish search
    }
    if (i==indxp)    // if not found, add its color to the palette
    {
      palette[i] = pixel;
      setvgapalette (i, &pixel);
      indxp++;
    }
    putpixel (x, y, i);  // put pixel with color from palette index

    // Update coordinates for next pixel and exit if screen full
    x++;
    if (x==640)
    {
      x = 0;
      y++;
      if (y==480)
        break;
    }
    fread (&pixel.r, 1, 1, f);  //
    fread (&pixel.g, 1, 1, f);  // Read next pixel
    fread (&pixel.b, 1, 1, f);  //
  }  
  fclose (f);

  getch();
  closegraph();
  return 0;
}

void setvgapalette (int entry, RGB *val)
{
  outp (0x3c8, entry);     // palette entry to write to
  outp (0x3c9, val->r/4);  // 6 MSb of R
  outp (0x3c9, val->g/4);  // 6 MSb of G
  outp (0x3c9, val->b/4);  // 6 MSb of B
}
于 2015-05-01T23:30:39.623 回答
0

使用以下getcol功能获得正确的颜色。在您的putpixel函数中,将 data[i] 替换为getcol(data[i]).

EGAVGA和位图的颜色代码不同。

int getcol(int col)

{

   switch(col)
   {
      case 0: return 0;     //BLACK;
      case 1: return 4;     //RED;
      case 2: return 2;     //GREEN
      case 3: return 6;     //BROWN
      case 4: return 1;     //BLUE;
      case 5: return 5;     //MAGENTA;
      case 6: return 3;     //CYAN;
      case 7: return 7;     //LIGHTGRAY;
      case 8: return 8;     //DARKGRAY;
      case 9: return 12;    //LIGHTRED;
      case 10:return 10;    //LIGHTGREEN
      case 11:return 14;    //YELLOW;
      case 12:return 9;     //LIGHTBLUE;
      case 13:return 13;    //LIGHTMAGENTA
      case 14:return 11;    //LIGHTCYAN;
      case 15:return 15;    //WHITE;
   }
   return col;
}
于 2016-02-19T07:40:43.297 回答