Listing 7. Source code for program named ImageNegate03.
/*Project ImageNegate03 This program is similar to ImageNegate01. However, this version assumes that the programmer does not know the width and height of the image. The purpose of this program is to show how to load an image file into memory, how to determine the size of the image, how to create a negative of the image, and how to display both the original and the negative image in an onscreen window. A PCX image file of an unknown size is loaded into memory and displayed in the top half of a graphics window on the screen. A negated version of the image is displayed in the bottom half of the window. The width and height of the image and the width and height of the window respectively are displayed in the upper-left corner of the window. For a particular file named starfish.pcx, the following output is superimposed on the original image: 321 327 324 654 I have determined experimentally that the width of the window MUST be a multiple of 4. I have also determined experimentally that the width must be at least 108 pixels. This second requirement seems to be a characteristic of Windows Vista because it is not possible to manually resize a window to make it narrower than approximately 108 pixels. If these two conditions aren't met, the program hangs up my Windows Vista Home Premium edition OS requiring me to log out and then log back in order to continue programming in Dev-C++. I have also determined experimentally that for PCX or BMP files with a color depth of 16, 24, or 32, you MUST create the onscreen window before you call load_bitmap to load the image file. Otherwise, the colors may not be correct. This makes it difficult to set the size of the window based solely on the dimensions of the clip rectangle of the image. The clip rectangle can't be obtained until after the image file is loaded. There may be a better solution to this problem than mine, but if so, I haven't discovered it yet. While my solution is not elegant, it works. My solution in this program is to perform the following sequence of operations: Load the image file into a bitmap. Get the height and width of the bitmap. Destroy the bitmap. Create the window of the correct size. Load the image file again into a second bitmap. Display the image in the top of the window. Negate the image in the bitmap. Display the negated image in the bottom of the window. Pressing any key causes the program to terminate. */ #include <allegro.h> #include <stdio.h>//required to call sprintf int main(){ int pixel = 0;//temporary storage for a pixel //Temporary storage for red, green, and blue int red = 0; int green = 0; int blue = 0; int width = 0;//image width int height = 0;//image height int windowWidth = 0;//must be a multiple of 4 && >= 108 int windowHeight = 0; //The addresses of the following variables are passed // in the call to get_clip_rect, where they are // populated with the coordinates of the diagonal // corners of the rectangular image. int upperLeftX = 0; int upperLeftY = 0; int lowerRightX = 0; int lowerRightY = 0; //Typical Allegro setup. allegro_init(); install_keyboard(); set_color_depth(32); //Declare a pointer variable capable of pointing to a // bitmap. BITMAP *picA = NULL; //Load an image file from the current directory. picA = load_bitmap("starfish.pcx", NULL); //Get the current clip rectangle for the image. This is // (one less than) the size of the image in both // dimensions. get_clip_rect(picA, &upperLeftX, &upperLeftY, &lowerRightX, &lowerRightY); //Compute the width and the height from the coordinates // of the diagonal corners of the clip rectangle. width = lowerRightX + 1; height = lowerRightY + 1; //Compute the window dimensions based on the width // and height of the bitmap. Guarantee that the width // is a multiple of 4 large enough to contain the // image and is not less than 108 pixels. if(width % 4 == 0){ windowWidth = width; }else{ windowWidth = (width/4)*4 + 4; }//end else if(windowWidth < 108){ windowWidth = 108; }//end if //Make the height sufficient to contain two copies of // the image, one above the other. windowHeight = 2 * height; //Destroy the bitmap, create the display window, and // reload the bitmap. destroy_bitmap(picA); set_gfx_mode(GFX_AUTODETECT_WINDOWED, windowWidth, windowHeight, 0, 0); picA = load_bitmap("starfish.pcx", NULL); //Copy the image to the upper-left corner of the // onscreen window. blit(picA, screen, 0,0,0,0,width,height); //Display the width and height of the bitmap and the // window in the upper-left corner of the window. char charArray[20]; sprintf(charArray, "%d", width); textout_ex(screen,font,charArray,10,10, makecol(255,255,255),-1); sprintf(charArray, "%d", height); textout_ex(screen,font,charArray,10,20, makecol(255,255,255),-1); sprintf(charArray, "%d", windowWidth); textout_ex(screen,font,charArray,10,30, makecol(255,255,255),-1); sprintf(charArray, "%d", windowHeight); textout_ex(screen,font,charArray,10,40, makecol(255,255,255),-1); //Cycle through the bitmap negating each pixel. for(int row = 0;row < height;row++){ for(int column = 0;column < width;column++){ pixel = getpixel(picA,column,row); red = getr(pixel); green = getg(pixel); blue = getb(pixel); putpixel(picA,column,row,makecol( 255-red,255-green,255-blue)); }//end loop row }//end loop on column //Copy the modified bitmap to the onscreen window // immediately below the original image. blit(picA, screen, 0,0,0,height,width,height); //Block and wait until the user presses a key. readkey(); //Destroy bitmap to avoid memory leaks. destroy_bitmap(picA); return 0;//Return 0 to indicate a successful run. }//end main function END_OF_MAIN() |