|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: image.cxx 4324 2005-05-09 21:47:22Z rokan $" 00003 // 00004 // Postscript image drawing implementation for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 1998-2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems on the following page: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 00028 #ifndef FL_DOXYGEN 00029 00030 #include <stdio.h> 00031 #include <math.h> 00032 #include <string.h> 00033 00034 #include <FL/Fl_PostScript.H> 00035 #include <FL/Fl.H> 00036 #include <FL/Fl_Pixmap.H> 00037 #include <FL/Fl_Bitmap.H> 00038 00039 int Fl_PostScript_Graphics_Driver::alpha_mask(const uchar * data, int w, int h, int D, int LD){ 00040 00041 mask = 0; 00042 if ((D/2)*2 != D){ //no mask info 00043 return 0; 00044 } 00045 int xx; 00046 int i,j, k, l; 00047 LD += w*D; 00048 int V255=0; 00049 int V0 =0; 00050 int V_=0; 00051 for (j=0;j<h;j++){ 00052 for (i=0;i<w;i++) 00053 switch(data[j*LD+D*i+D-1]){ 00054 case 255: V255 = 1; break; 00055 case 0: V0 = 1; break; 00056 default: V_= 1; 00057 } 00058 if (V_) break; 00059 }; 00060 if (!V_){ 00061 if (V0) 00062 if (V255){// not true alpha, only masking 00063 xx = (w+7)/8; 00064 mask = new uchar[h * xx]; 00065 for (i=0;i<h * xx;i++) mask[i]=0; 00066 for (j=0;j<h;j++) 00067 for (i=0;i<w;i++) 00068 if (data[j*LD+D*i+D-1]) 00069 mask[j*xx+i/8] |= 1 << (i % 8); 00070 mx = w; 00071 my = h; //mask imensions 00072 return 0; 00073 } else { 00074 mask=0; 00075 return 1; //everything masked 00076 } 00077 else 00078 return 0; 00079 } 00080 00081 00082 00085 00086 mask = new uchar[((w+1)/2) * h * 4]; 00087 00088 for (i = 0; i<((w+1)/2) * h * 4; i++) mask[i] = 0; //cleaning 00089 00090 00091 00092 mx= w*4; 00093 my=h*4; // mask dimensions 00094 00095 xx = (w+1)/2; // mask line width in bytes 00096 00097 short * errors1 = new short [w*4+2]; // two rows of dither errors 00098 short * errors2 = new short [w*4+2]; // two rows of dither errors 00099 00100 for (i=0; i<w*4+2; i++) errors2[i] = 0; // cleaning,after first swap will become current 00101 for (i=0; i<w*4+2; i++) errors1[i] = 0; // cleaning,after first swap will become current 00102 00103 short * current = errors1; 00104 short * next = errors2; 00105 short * swap; 00106 00107 for (j=0; j<h; j++){ 00108 for (l=0; l<4; ){ // generating 4 rows of mask lines for 1 RGB line 00109 int jj = j*4+l; 00110 00112 swap = next; 00113 next = current; 00114 current = swap; 00115 *(next+1) = 0; // must clean the first cell, next are overriden by *1 00116 for (i=0; i<w; i++){ 00117 for (k=0; k<4; k++){ // generating 4 x-pixels for 1 RGB 00118 short error, o1, o2, o3; 00119 int ii = i*4+k; // mask cell index 00120 short val = data[j*LD+D*i+D-1] + current[1+ii]; 00121 if (val>127){ 00122 mask[jj*xx+ii/8] |= 1 << (ii % 8); //set mask bit 00123 error = val-255; 00124 }else 00125 error = val; 00126 00128 if (error >0){ 00129 next[ii] += o1 = (error * 3 + 8)/16; 00130 current[ii+2] += o2 = (error * 7 + 8)/16; 00131 next[ii+2] = o3 =(error + 8)/16; // *1 - ok replacing (cleaning) 00132 } else { 00133 next[ii] += o1 = (error * 3 - 8)/16; 00134 current[ii+2] += o2 = (error * 7 - 8)/16; 00135 next[ii+2] = o3 = (error - 8)/16; 00136 } 00137 next[1+ii] += error - o1 - o2 - o3; 00138 } 00139 } 00140 l++; 00141 00143 00144 jj = j*4+l; 00145 swap = next; 00146 next = current; 00147 current = swap; 00148 *(next+1) = 0; // must clean the first cell, next are overriden by *1 00149 00150 for (i = w-1; i >= 0; i--){ 00151 00152 for (k=3; k>=0; k--){ // generating 4 x-pixels for 1 RGB 00153 short error, o1, o2, o3; 00154 00155 int ii = i*4+k; // mask cell index 00156 short val = data[j*LD+D*i+D-1] + current[1+ii]; 00157 if (val>127){ 00158 00159 mask[jj*xx+ii/8] |= 1 << (ii % 8); //set mask bit 00160 error = val-255; 00161 } else 00162 error = val; 00163 00165 if (error >0){ 00166 next[ii+2] += o1 = (error * 3 + 8)/16; 00167 current[ii] += o2 = (error * 7 + 8)/16; 00168 next[ii] = o3 =(error + 8)/16; // *1 - ok replacing (cleaning) 00169 } else { 00170 next[ii+2] += o1 = (error * 3 - 8)/16; 00171 00172 current[ii] += o2 = (error * 7 - 8)/16; 00173 next[ii] = o3 = (error - 8)/16; 00174 } 00175 next[1+ii] += error - o1 - o2 - o3; 00176 } 00177 } 00178 l++; 00179 } 00180 } 00181 delete[] errors1; 00182 delete[] errors2; 00183 return 0; 00184 } 00185 00186 // bitwise inversion of all 4-bit quantities 00187 static const unsigned char swapped[16] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; 00188 00189 // bitwise inversion of a byte 00190 static inline uchar swap_byte(const uchar b) { 00191 return (swapped[b & 0xF] << 4) | swapped[b >> 4]; 00192 } 00193 00194 00195 extern uchar **fl_mask_bitmap; 00196 00197 00198 void Fl_PostScript_Graphics_Driver::draw_scaled_image(const uchar *data, double x, double y, double w, double h, int iw, int ih, int D, int LD) { 00199 00200 00201 if (D<3){ //mono 00202 draw_scaled_image_mono(data, x, y, w, h, iw, ih, D, LD); 00203 return; 00204 } 00205 00206 00207 int i,j, k; 00208 00209 fprintf(output,"save\n"); 00210 00211 const char * interpol; 00212 if (lang_level_>1){ 00213 if (interpolate_) 00214 interpol="true"; 00215 else 00216 interpol="false"; 00217 if (mask && lang_level_>2) 00218 fprintf(output, "%g %g %g %g %i %i %i %i %s CIM\n", x , y+h , w , -h , iw , ih, mx, my, interpol); 00219 else 00220 fprintf(output, "%g %g %g %g %i %i %s CII\n", x , y+h , w , -h , iw , ih, interpol); 00221 } else 00222 fprintf(output , "%g %g %g %g %i %i CI", x , y+h , w , -h , iw , ih); 00223 00224 00225 if (!LD) LD = iw*D; 00226 uchar *curmask=mask; 00227 00228 for (j=0; j<ih;j++){ 00229 if (mask){ 00230 00231 for (k=0;k<my/ih;k++){ 00232 for (i=0; i<((mx+7)/8);i++){ 00233 if (!(i%80)) fprintf(output, "\n"); 00234 fprintf(output, "%.2x",swap_byte(*curmask)); 00235 curmask++; 00236 } 00237 fprintf(output,"\n"); 00238 } 00239 } 00240 const uchar *curdata=data+j*LD; 00241 for (i=0 ; i<iw ; i++) { 00242 uchar r = curdata[0]; 00243 uchar g = curdata[1]; 00244 uchar b = curdata[2]; 00245 if (lang_level_<3 && D>3) { //can do mixing using bg_* colors) 00246 unsigned int a2 = curdata[3]; //must be int 00247 unsigned int a = 255-a2; 00248 r = (a2 * r + bg_r * a)/255; 00249 g = (a2 * g + bg_g * a)/255; 00250 b = (a2 * b + bg_b * a)/255; 00251 } 00252 if (!(i%40)) fprintf(output, "\n"); 00253 fprintf(output, "%.2x%.2x%.2x", r, g, b); 00254 curdata +=D; 00255 } 00256 fprintf(output,"\n"); 00257 00258 } 00259 00260 fprintf(output," >\nrestore\n" ); 00261 00262 00263 } 00264 00265 void Fl_PostScript_Graphics_Driver::draw_scaled_image(Fl_Draw_Image_Cb call, void *data, double x, double y, double w, double h, int iw, int ih, int D) { 00266 00267 int level2_mask = 0; 00268 fprintf(output,"save\n"); 00269 int i,j,k; 00270 const char * interpol; 00271 if (lang_level_ > 1) { 00272 if (interpolate_) interpol="true"; 00273 else interpol="false"; 00274 if (mask && lang_level_ > 2) { 00275 fprintf(output, "%g %g %g %g %i %i %i %i %s CIM\n", x , y+h , w , -h , iw , ih, mx, my, interpol); 00276 } 00277 else if (mask && lang_level_ == 2) { 00278 level2_mask = 1; // use method for drawing masked color image with PostScript level 2 00279 fprintf(output, " %g %g %g %g %d %d pixmap_plot\n", x, y, w, h, iw, ih); 00280 } 00281 else { 00282 fprintf(output, "%g %g %g %g %i %i %s CII\n", x , y+h , w , -h , iw , ih, interpol); 00283 } 00284 } else { 00285 fprintf(output , "%g %g %g %g %i %i CI", x , y+h , w , -h , iw , ih); 00286 } 00287 00288 int LD=iw*D; 00289 uchar *rgbdata=new uchar[LD]; 00290 uchar *curmask=mask; 00291 00292 if (level2_mask) { 00293 for (j = ih - 1; j >= 0; j--) { // output full image data 00294 call(data, 0, j, iw, rgbdata); 00295 uchar *curdata = rgbdata; 00296 for (i=0 ; i<iw ; i++) { 00297 if (!(i%20)) fputs("\n", output); 00298 fprintf(output, "%.2x%.2x%.2x", curdata[0], curdata[1], curdata[2]); 00299 curdata += D; 00300 } 00301 fputs("\n", output); 00302 } 00303 fputs(">\n", output); 00304 for (j = ih - 1; j >= 0; j--) { // output mask data 00305 curmask = mask + j * (my/ih) * ((mx+7)/8); 00306 for (k=0; k < my/ih; k++) { 00307 for (i=0; i < ((mx+7)/8); i++) { 00308 if (!(i%40)) fputs("\n", output); 00309 fprintf(output, "%.2x",swap_byte(*curmask)); 00310 curmask++; 00311 } 00312 fputs("\n", output); 00313 } 00314 } 00315 fputs(">\n", output); 00316 } 00317 else { 00318 for (j=0; j<ih;j++) { 00319 if (mask && lang_level_ > 2) { // InterleaveType 2 mask data 00320 for (k=0; k<my/ih;k++) { //for alpha pseudo-masking 00321 for (i=0; i<((mx+7)/8);i++) { 00322 if (!(i%40)) fputs("\n", output); 00323 fprintf(output, "%.2x",swap_byte(*curmask)); 00324 curmask++; 00325 } 00326 fprintf(output,"\n"); 00327 } 00328 } 00329 call(data,0,j,iw,rgbdata); 00330 uchar *curdata=rgbdata; 00331 for (i=0 ; i<iw ; i++) { 00332 uchar r = curdata[0]; 00333 uchar g = curdata[1]; 00334 uchar b = curdata[2]; 00335 00336 if (!(i%40)) fputs("\n", output); 00337 fprintf(output, "%.2x%.2x%.2x", r, g, b); 00338 00339 curdata +=D; 00340 } 00341 fputs("\n", output); 00342 00343 } 00344 fputs(">\n", output); 00345 } 00346 00347 fprintf(output,"restore\n"); 00348 delete[] rgbdata; 00349 } 00350 00351 void Fl_PostScript_Graphics_Driver::draw_scaled_image_mono(const uchar *data, double x, double y, double w, double h, int iw, int ih, int D, int LD) { 00352 00353 fprintf(output,"save\n"); 00354 00355 int i,j, k; 00356 00357 const char * interpol; 00358 if (lang_level_>1){ 00359 if (interpolate_) 00360 interpol="true"; 00361 else 00362 interpol="false"; 00363 if (mask && lang_level_>2) 00364 fprintf(output, "%g %g %g %g %i %i %i %i %s GIM\n", x , y+h , w , -h , iw , ih, mx, my, interpol); 00365 else 00366 fprintf(output, "%g %g %g %g %i %i %s GII\n", x , y+h , w , -h , iw , ih, interpol); 00367 }else 00368 fprintf(output , "%g %g %g %g %i %i GI", x , y+h , w , -h , iw , ih); 00369 00370 00371 if (!LD) LD = iw*D; 00372 00373 00374 int bg = (bg_r + bg_g + bg_b)/3; 00375 00376 uchar *curmask=mask; 00377 for (j=0; j<ih;j++){ 00378 if (mask){ 00379 for (k=0;k<my/ih;k++){ 00380 for (i=0; i<((mx+7)/8);i++){ 00381 if (!(i%80)) fprintf(output, "\n"); 00382 fprintf(output, "%.2x",swap_byte(*curmask)); 00383 curmask++; 00384 } 00385 fprintf(output,"\n"); 00386 } 00387 } 00388 const uchar *curdata=data+j*LD; 00389 for (i=0 ; i<iw ; i++) { 00390 if (!(i%80)) fprintf(output, "\n"); 00391 uchar r = curdata[0]; 00392 if (lang_level_<3 && D>1) { //can do mixing 00393 00394 unsigned int a2 = curdata[1]; //must be int 00395 unsigned int a = 255-a2; 00396 r = (a2 * r + bg * a)/255; 00397 } 00398 if (!(i%120)) fprintf(output, "\n"); 00399 fprintf(output, "%.2x", r); 00400 curdata +=D; 00401 } 00402 fprintf(output,"\n"); 00403 00404 } 00405 00406 fprintf(output," >\nrestore\n" ); 00407 00408 } 00409 00410 00411 00412 void Fl_PostScript_Graphics_Driver::draw_scaled_image_mono(Fl_Draw_Image_Cb call, void *data, double x, double y, double w, double h, int iw, int ih, int D) { 00413 00414 fprintf(output,"save\n"); 00415 int i,j,k; 00416 const char * interpol; 00417 if (lang_level_>1){ 00418 if (interpolate_) interpol="true"; 00419 else interpol="false"; 00420 if (mask && lang_level_>2) 00421 fprintf(output, "%g %g %g %g %i %i %i %i %s GIM\n", x , y+h , w , -h , iw , ih, mx, my, interpol); 00422 else 00423 fprintf(output, "%g %g %g %g %i %i %s GII\n", x , y+h , w , -h , iw , ih, interpol); 00424 } else 00425 fprintf(output , "%g %g %g %g %i %i GI", x , y+h , w , -h , iw , ih); 00426 00427 int LD=iw*D; 00428 uchar *rgbdata=new uchar[LD]; 00429 uchar *curmask=mask; 00430 for (j=0; j<ih;j++){ 00431 00432 if (mask && lang_level_>2){ // InterleaveType 2 mask data 00433 for (k=0; k<my/ih;k++){ //for alpha pseudo-masking 00434 for (i=0; i<((mx+7)/8);i++){ 00435 if (!(i%40)) fprintf(output, "\n"); 00436 fprintf(output, "%.2x",swap_byte(*curmask)); 00437 curmask++; 00438 } 00439 fprintf(output,"\n"); 00440 } 00441 } 00442 call(data,0,j,iw,rgbdata); 00443 uchar *curdata=rgbdata; 00444 for (i=0 ; i<iw ; i++) { 00445 uchar r = curdata[0]; 00446 if (!(i%120)) fprintf(output, "\n"); 00447 fprintf(output, "%.2x", r); 00448 curdata +=D; 00449 } 00450 fprintf(output,"\n"); 00451 } 00452 fprintf(output,">\n"); 00453 fprintf(output,"restore\n"); 00454 delete[] rgbdata; 00455 } 00456 00457 00459 00460 00461 void Fl_PostScript_Graphics_Driver::draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy){ 00462 const char * const * di =pxm->data(); 00463 int w,h; 00464 if (!fl_measure_pixmap(di, w, h)) return; 00465 mask=0; 00466 fl_mask_bitmap=&mask; 00467 mx = WP; 00468 my = HP; 00469 push_clip(XP, YP, WP, HP); 00470 fl_draw_pixmap(di,XP -cx, YP -cy, FL_BLACK ); 00471 pop_clip(); 00472 delete[] mask; 00473 mask=0; 00474 fl_mask_bitmap=0; 00475 } 00476 00477 void Fl_PostScript_Graphics_Driver::draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy){ 00478 const uchar * di = rgb->array; 00479 int w = rgb->w(); 00480 int h = rgb->h(); 00481 mask=0; 00482 if (lang_level_>2) //when not true, not making alphamask, mixing colors instead... 00483 if (alpha_mask(di, w, h, rgb->d(),rgb->ld())) return; //everthing masked, no need for painting! 00484 push_clip(XP, YP, WP, HP); 00485 draw_scaled_image(di, XP + cx, YP + cy, w, h, w, h, rgb->d(), rgb->ld()); 00486 pop_clip(); 00487 delete[]mask; 00488 mask=0; 00489 } 00490 00491 void Fl_PostScript_Graphics_Driver::draw(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy){ 00492 const uchar * di = bitmap->array; 00493 int w,h; 00494 int LD=(bitmap->w()+7)/8; 00495 int xx; 00496 00497 if (WP> bitmap->w() - cx){// to assure that it does not go out of bounds; 00498 w = bitmap->w() - cx; 00499 xx = (bitmap->w()+7)/8 - cx/8; //length of mask in bytes 00500 }else{ 00501 w =WP; 00502 xx = (w+7)/8 - cx/8; 00503 } 00504 if ( HP > bitmap->h()-cy) 00505 h = bitmap->h() - cy; 00506 else 00507 h = HP; 00508 00509 di += cy*LD + cx/8; 00510 int si = cx % 8; // small shift to be clipped, it is simpler than shifting whole mask 00511 00512 int i,j; 00513 push_clip(XP, YP, WP, HP); 00514 fprintf(output , "%i %i %i %i %i %i MI", XP - si, YP + HP , WP , -HP , w , h); 00515 00516 for (j=0; j<HP; j++){ 00517 for (i=0; i<xx; i++){ 00518 if (!(i%80)) fprintf(output, "\n"); // not have lines longer than 255 chars 00519 fprintf(output, "%.2x", swap_byte(*di) ); 00520 di++; 00521 } 00522 fprintf(output,"\n"); 00523 } 00524 fprintf(output,">\n"); 00525 pop_clip(); 00526 } 00527 00528 #endif // FL_DOXYGEN 00529 00530 // 00531 // End of "$Id: image.cxx 4324 2005-05-09 21:47:22Z rokan $" 00532 // 00533 00534 00535 00536 00537 00538 00539 00540 00541 00542 00543 00544 00545 00546 00547 00548 00549 00550