struct pixel { unsigned char red; // 0 to 255 unsigned char green; // 0 to 255 unsigned char blue; // 0 to 255 };
Here the pixel is large enough to allow us represent some 16777216 [16 Million Colours] approximately, and small enough to represent it in 24 bits! An image is a thus, intuitively a collection of different colours arranged along different rows and columns. The colours are nothing but pixels; which follows that an image is a collection of pixels in rows and columns. A image to us is simply an 2-D array of pixels.
Now that you have understood what an image is, and how its represented in an array of pixels, various formats exist in the wide world of image processing to encode and store the images, so that they occupy the least amount of memory, to facilitate among other things faster downloads and quicker processing. These formats, which you may be familiar are the ones like jpeg, png, bmp, xpm etc. Now each format uses various techniques for encoding; for example jpeg use DCT [Discrete Cosine Transform], bmp can be RLE [Run Length Encoded], and PNG could use dictionary based compression. Whew so much for a 2-D array of pixels, that the weak hearted might consider quitting.Wait; thats why the GTK and GDK libraries are considered the panacea to this pain. GDK has function calls that loads from almost any image to the sought after 2-D array of pixels.And need I say more? Lets start.
GDK can load files using the function gdk_pixbuf_new_from_file and we can get various attributes of the image like width,height and pointer to pixel buffer(to manipulate it!),process the image next, and then we can make a GTK widget from it. The following section of commented code walks through a typical section.
/* Code for loading and image & displaying it. */ #include<gtk/gtk.h> gchar *filename="/usr/share/pixmaps/gnu_emacs.png"; //picture to load GdkPixbuf *pb; //pixbuf structure GtkImage *im; //gtk widget pb=gdk_pixbuf_new_from_file(filename,NULL); //load the image to pixbuf process_picture(pb); //process it the fun begins here! im=gtk_image_new_from_pixbuf(pb); //make it a widget gtk_widget_show(im); //display the image widget
I will assume that from this point onwards, we are working with a standard pixel, as defined above in section [see pixel] Of the many effets possible after befriending the pixel, the easiest ones are the pixel level or point filters.They consist of, but not limited to
A note of accessing the pixel array as returned by the GDK. As of writing the GDK supports image of the type RGBA or RGB only. Hence we are supposed to get the attributes of height,width and bytes per pixel, before we begin. The pointer to the pixel array is a 1-D array of pixels, which has to navigated like a 2-D array as show below. It has at offsets of 0,1,2 form the current pixel location, the values of the red, green, and blue values of the current pixel.
int ht,wt; int i=0,j=0; int rowstride=0; int bpp=0; gchar *pixel; if(gdk_pixbuf_get_bits_per_sample(pb)!=8) //we handle only 24 bit images. return; //look at 3 bytes per pixel. //getting attributes of height, ht=gdk_pixbuf_get_height(pb); //width, and bpp.Also get pointer wt=gdk_pixbuf_get_width(pb); //to pixels. pixel=gdk_pixbuf_get_pixels(pb); bpp=3; rowstride=wt*bpp; for(i=0;i<ht;i++) //iterate over the height of image. for(j=0;j<rowstride;j+=bpp) //read every pixel in the row.skip //bpp bytes { //access pixel[i][j] as // pixel[i*rowstride + j] //access red,green and blue as pixel[i*rowstride + j+0]=red pixel[i*rowstride + j+1]=green pixel[i*rowstride + j+2]=blue }
We will be using the figure of the kathakali dancer shown here in figure, for our image processing needs.