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)  

ps_image.cxx

Go to the documentation of this file.
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