Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->系统管理 ->正文

GTK入门导引

来源:Linux-cn.com 作者:Webmaster 时间:2007-05-05 点击: [收藏] [投稿]

  Filling In a Preview

  In order to familiarize ourselves with the basics of filling in previews, let's create the following pattern (contrived by trial and error):

  void


my_preview_rendering_function(GtkWidget *preview)
{
#define SIZE 100
#define HALF (SIZE/2)
guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
gint i, j; /* Coordinates*/
double r, alpha, x, y;
if (preview==NULL) return; /* I usually add this when I want */
 /* to avoid silly crashes. You*/
 /* should probably make sure that */
 /* everything has been nicely */
 /* initialized!*/
for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?*/
 /* glib.h contains ABS(x).*/
row[i*3+0] = sqrt(1-r)*255;/* Define Red*/
row[i*3+1] = 128;/* Define Green*/
row[i*3+2] = 224;/* Define Blue*/
}/* "+0" is for alignment!*/
else {
row[i*3+0] = r*255;
row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
}
}
gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
/* Insert "row" into "preview" starting at the point with*/
/* coordinates (0,j) first column, j_th row extending SIZE */
/* pixels to the right */
}
free(row); /* save some space */
gtk_widget_draw(preview,NULL); /* what does this do? */
gdk_flush(); /* or this? */
}

  Non-GIMP users can have probably seen enough to do a lot of things already.

  For the GIMP users I have a few pointers to add.

  Image Preview

  It is probably wize to keep a reduced version of the image around with just enough pixels to fill the preview. This is done by selecting every n'th pixel where n is the ratio of the size of the image to the size of the preview. All further operations (including filling in the previews) are then performed on the reduced number of pixels only. The following is my implementation of reducing the image. (Keep in mind that I've had only basic C!)


(UNTESTED CODE ALERT!!!)
typedef struct {
gintwidth;
gintheight;
gintbbp;
guchar*rgb;
guchar*mask;
} ReducedImage;
enum {
SELECTION_ONLY,
SELCTION_IN_CONTEXT,
ENTIRE_IMAGE
};
ReducedImage *Reduce_The_Image(GDrawable *drawable,
GDrawable *mask,
gint LongerSize,
gint Selection)
{
/* This function reduced the image down to the the selected preview size */
/* The preview size is determine by LongerSize, i.e. the greater of the*/
/* two dimentions. Works for RGB images only!*/
gint RH, RW;/* Reduced height and reduced width*/
gint width, height;/* Width and Height of the area being reduced*/
gint bytes=drawable->bpp;
ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
gint i, j, whichcol, whichrow, x1, x2, y1, y2;
GPixelRgn srcPR, srcMask;
gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire*/
 /* image. */
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
width= x2-x1;
height = y2-y1;
/* If there's a SELECTION, we got its bounds!)
if (width != drawable->width && height != drawable->height)
NoSelectionMade=FALSE;
/* Become aware of whether the user has made an active selection*/
/* This will become important later, when creating a reduced mask. */

/* If we want to preview the entire image, overrule the above!*/
/* Of course, if no selection has been made, this does nothing! */
if (Selection==ENTIRE_IMAGE) {
x1=0;
x2=drawable->width;
y1=0;
y2=drawable->height;
}
/* If we want to preview a selection with some surronding area we */
/* have to expand it a little bit. Consider it a bit of a riddle. */
if (Selection==SELECTION_IN_CONTEXT) {
x1=MAX(0,x1-width/2.0);
x2=MIN(drawable->width,x2+width/2.0);
y1=MAX(0,y1-height/2.0);
y2=MIN(drawable->height, y2+height/2.0);
}
/* How we can determine the width and the height of the area being */
/* reduced.*/
width= x2-x1;
height = y2-y1;
/* The lines below determine which dimension is to be the longer*/
/* side. The idea borrowed from the supernova plug-in. I suspect I */
/* could've thought of it myself, but the truth must be told.*/
/* Plagiarism stinks!*/
if (width>height) {
RW=LongerSize;
RH=(float) height * (float) LongerSize/ (float) width;
}
else {
RH=LongerSize;
RW=(float)width * (float) LongerSize/ (float) height;
}
/* The intire image is stretched into a string! */
tempRGB= (guchar *) malloc(RW*RH*bytes);
tempmask= (guchar *) malloc(RW*RH);
gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, width, height, FALSE, FALSE);
gimp_pixel_rgn_init (&srcMask, mask, x1, y1, width, height, FALSE, FALSE);
/* Grab enough to save a row of image and a row of mask. */
src_row= (guchar *) malloc (width*bytes);
src_mask_row= (guchar *) malloc (width);
for (i=0; i < RH; i++) {
whichrow=(float)i*(float)height/(float)RH;
gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y1+whichrow, width);
gimp_pixel_rgn_get_row (&srcMask, src_mask_row, x1, y1+whichrow, width);
for (j=0; j < RW; j++) {
whichcol=(float)j*(float)width/(float)RW;
/* No selection made = each point is completely selected! */
if (NoSelectionMade)
tempmask[i*RW+j]=255;
else
tempmask[i*RW+j]=src_mask_row[whichcol];
/* Add the row to the one long string which now contains the image! */
tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
/* Hold on to the alpha as well */
if (bytes==4)
tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
}
}
temp->bpp=bytes;
temp->width=RW;
temp->height=RH;
temp->rgb=tempRGB;
temp->mask=tempmask;
return temp;
}
The following is a preview function which used the same ReducedImage type!
Note that it uses fakes transparancy (if one is present by means of
fake_transparancy which is defined as follows:
gint fake_transparency(gint i, gint j)
{
if ( ((i%20)- 10) * ((j%20)- 10)>0)
return 64;
else
return 196;
}
Now here's the preview function:
void
my_preview_render_function(GtkWidget *preview,
gintchangewhat,
gintchangewhich)
{
gint Inten, bytes=drawable->bpp;
gint i, j, k;
float partial;
gint RW=reduced->width;
gint RH=reduced->height;
guchar *row=malloc(bytes*RW);;
for (i=0; i < RH; i++) {
for (j=0; j < RW; j++) {
row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
if (bytes==4)
for (k=0; k<3; k++) {
float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
}
}
gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
}
free(a);
gtk_widget_draw(preview,NULL);
gdk_flush();
}
Applicable Routines
guintgtk_preview_get_type(void);
/* No idea */
voidgtk_preview_uninit (void);
/* No idea */
GtkWidget*gtk_preview_new(GtkPreviewTypetype);
/* Described above */
voidgtk_preview_size(GtkPreview*preview,
gint width,
gint height);
/* Allows you to resize an existing preview.*/
/* Apparantly there's a bug in GTK which makes*/
/* this process messy. A way to clean up a mess */
/* is to manually resize the window containing*/
/* the preview after resizing the preview.*/
voidgtk_preview_put(GtkPreview*preview,
GdkWindow*window,
GdkGC*gc,
gint srcx,
gint srcy,
gint destx,
gint desty,
gint width,
gint height);
/* No idea */
voidgtk_preview_put_row(GtkPreview*preview,
guchar*src,
guchar*dest,
gint x,
gint y,
gint w);
/* No idea */
voidgtk_preview_draw_row(GtkPreview*preview,
guchar*data,
gint x,
gint y,
gint w);
/* Described in the text */
voidgtk_preview_set_expand (GtkPreview*preview,
gint expand);
/* No idea */
/* No clue for any of the below but*/
/* should be standard for most widgets */
voidgtk_preview_set_gamma(doublegamma);
voidgtk_preview_set_color_cube (guintnred_shades,
guintngreen_shades,
guintnblue_shades,
guintngray_shades);
voidgtk_preview_set_install_cmap(gint install_cmap);
voidgtk_preview_set_reserved(gint nreserved);
GdkVisual*gtk_preview_get_visual (void);
GdkColormap*gtk_preview_get_cmap(void);
GtkPreviewInfo* gtk_preview_get_info(void);


 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:GTK+/Gnome应用开发   下一篇:GTK v1.2 Tutorial(英文)

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章