(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(英文)
【文章评论】
【收藏本文】
【推荐好友】
【打印本文】
【我要投稿】 【论坛讨论】
更多相关文章
|
|