/* * Description: * * Image scaling based on bilinear interpolation algorithm * * Arguments: * @d: GdkDrawable object * @xoff, @yoff: Background picture offset to screen * @bgfile: Background picture filename. Alpha channel is ignored. * @x, @y: Foregorund picture offset to background picture * @fgfile: Foreground picture filename. * @nx, @ny: New geometry of fgfile after scaling. * @threshod: If foreground picture carrys alpha channel, alpha values * exceed this threshold get displayed. */
static void draw_scale( GdkDrawable* d, int xoff, int yoff, const char* bgfile, int x, int y, const char* fgfile, int nx, int ny, unsigned char threshold) { GdkPixbuf* bgbuf = gdk_pixbuf_new_from_file(bgfile, NULL); GdkPixbuf* fgbuf = gdk_pixbuf_new_from_file(fgfile, NULL);
if(bgbuf == NULL || fgbuf == NULL) { g_print("Can not open %s or %s\n", bgfile, fgfile); return; }
int nbgchs = gdk_pixbuf_get_n_channels (bgbuf); int nfgchs = gdk_pixbuf_get_n_channels (fgbuf);
int bgrowsz = gdk_pixbuf_get_rowstride(bgbuf); int fgrowsz = gdk_pixbuf_get_rowstride(fgbuf);
int bgheight = gdk_pixbuf_get_height(bgbuf); int fgheight = gdk_pixbuf_get_height(fgbuf);
int bgwidth = gdk_pixbuf_get_width(bgbuf); int fgwidth = gdk_pixbuf_get_width(fgbuf);
#ifdef _DEBUG g_print("bg file=%s, fg file=%s\n", bgfile, fgfile); g_print("bg channels=%d, fg channels=%d\n", nbgchs, nfgchs); g_print("bg row_size=%d, fg row_size=%d\n", bgrowsz, fgrowsz); g_print("bg height=%d, fg height=%d\n", bgheight, fgheight); g_print("bg width=%d, fg width=%d\n", bgwidth, fgwidth); #endif
unsigned char* bp = gdk_pixbuf_get_pixels (bgbuf); unsigned char* fp = gdk_pixbuf_get_pixels (fgbuf);
float rx = (float)fgwidth/(float)nx; float ry = (float)fgheight/(float)ny;
int i,j, n; for(j=0; j<ny; j++) { float oy = j*ry; int iy = (int)oy; float v = oy - iy;
for(i=0; i<nx; i++) { float ox = i*rx; int ix = (int)ox; float u = ox - ix;
int soff = (j+y)*bgrowsz+(i+x)*nbgchs;
if( (ix+1 > fgwidth) || (iy+1 > fgheight) ) { for(n=0; n<3; n++) bp[soff+n] = 0xff; } else { int toff = iy*fgrowsz + ix*nfgchs; float nr = (1-u)*(1-v)*fp[toff]; float ng = (1-u)*(1-v)*fp[toff+1]; float nb = (1-u)*(1-v)*fp[toff+2];
toff = (iy+1)*fgrowsz + ix*nfgchs; nr += (1-u)*v*fp[toff]; ng += (1-u)*v*fp[toff+1]; nb += (1-u)*v*fp[toff+2];
toff = iy*fgrowsz + (ix+1)*nfgchs; nr += u*(1-v)*fp[toff]; ng += u*(1-v)*fp[toff+1]; nb += u*(1-v)*fp[toff+2];
toff = (iy+1)*fgrowsz + (ix+1)*nfgchs; nr += u*v*fp[toff]; ng += u*v*fp[toff+1]; nb += u*v*fp[toff+2];
bp[soff] = (unsigned char)nr; bp[soff+1] = (unsigned char)ng; bp[soff+2] = (unsigned char)nb; } } /* end for(i=...) */ } /* end for(j=...) */
gdk_draw_pixbuf(d, NULL, bgbuf, xoff, yoff, 0, 0, bgwidth, bgheight, GDK_RGB_DITHER_NONE, 0, 0);
g_object_unref(bgbuf); g_object_unref(fgbuf); }
|