2

I want to read bmp image and draw the pixel values in GUI window but it is not giving me the correct result,the picture it is showing is completely different then the original image I don't know where I am going wrong. any help?

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();
}
mcleod_ideafix
  • 11,128
  • 2
  • 24
  • 32
user3370649
  • 57
  • 1
  • 8
  • 2
    Is this [tag:c] or [tag:c++]? How come these questions always get tagged as both...? – nhgrif May 01 '15 at 23:16
  • Don't cross the I/O streams. Use either `printf` or `cout`. Don't mix them. Similarly, don't mix `fread` with `ifstream`. – Thomas Matthews May 01 '15 at 23:18
  • Are you using Turbo C/C++ in DOS environment ? it only support VGAHI which is 640x480 with 16 colors. It's very difficult to display image with only 16 colors. Try GDI+ API on Windows ! – DU Jiaen Feb 19 '16 at 07:54

3 Answers3

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

You are very insistent that the pixel at [j][i] be changed, so much, that you are writing to the same pixel location 3 times.

Is there a pixel stream, where by each write puts the pixel into a queue or stream (like the SPI bus interface)?

The last line doesn't look correct either. I believe it should be data[j+2], but I dunno.

There may be other issues, but I can't use my debugger on your code.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
0

This code seems to be using the BGI library from Borland to draw graphics under MS DOS. You have, in fact, specified to autodetect your graphics card, which will initialize it into VGA 16 paletized colors and planar mode (unless you are using an EGA card or older).

Later, you are reading what it seems to be a 24-bit color image from the BMP and putpixeling as if BGI would support 24 bits (which does not).

So your program needs a massive rewritting:

  • Init graphics and check result values to see what graphics mode the computer is.
  • Open BMP, read its properties and reject it if it doesn't fit your screen in the current graphics mode, or if it isn't a palettized image, or if the number of colors (palette entries) is greater than your graphics mode supports.
  • Read palette from BMP, adjust it to be 6 bits per primary color and update palette registers
  • Read pixels from BMP, and putpixel them, taking into account that BMP pictures are stored upside down

This is just for a basic display program. A more general solution would require you to add code to either resize of pan the image to display it in your screen. Besides, you would have to check if the picture is in true color format and if so, perform some dithering to reduce the number of colors to the maximum available in your graphics mode, and then assign a palette entry to each of them.

Consider, for example, this simple program to display RAW image files. The RAW file is assumed to be 640x480 pixels, and each pixel to have 3 bytes corresponding to its level of red, green and blue, in this order. The picture needs to be color downgraded previously, to have up to 16 different colors. The program reads pixels and assign its colors to palette index. If a new pixel is already present in the palette, its index is used in putpixel. If not, its color is added to the palette, the hardware palette is updated, and the new index is used in 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
}
mcleod_ideafix
  • 11,128
  • 2
  • 24
  • 32
0

Use following getcol function to get correct color. In your putpixel function replace data[i] by getcol(data[i]).

Color code for EGAVGA and bitmap are different.

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;
}
Rao
  • 20,781
  • 11
  • 57
  • 77
Bhanu
  • 1
  • 7