• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kviewshell

GScaler.cpp

Go to the documentation of this file.
00001 //C-  -*- C++ -*-
00002 //C- -------------------------------------------------------------------
00003 //C- DjVuLibre-3.5
00004 //C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
00005 //C- Copyright (c) 2001  AT&T
00006 //C-
00007 //C- This software is subject to, and may be distributed under, the
00008 //C- GNU General Public License, Version 2. The license should have
00009 //C- accompanied the software or you may obtain a copy of the license
00010 //C- from the Free Software Foundation at http://www.fsf.org .
00011 //C-
00012 //C- This program is distributed in the hope that it will be useful,
00013 //C- but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //C- GNU General Public License for more details.
00016 //C- 
00017 //C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
00018 //C- distributed by Lizardtech Software.  On July 19th 2002, Lizardtech 
00019 //C- Software authorized us to replace the original DjVu(r) Reference 
00020 //C- Library notice by the following text (see doc/lizard2002.djvu):
00021 //C-
00022 //C-  ------------------------------------------------------------------
00023 //C- | DjVu (r) Reference Library (v. 3.5)
00024 //C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
00025 //C- | The DjVu Reference Library is protected by U.S. Pat. No.
00026 //C- | 6,058,214 and patents pending.
00027 //C- |
00028 //C- | This software is subject to, and may be distributed under, the
00029 //C- | GNU General Public License, Version 2. The license should have
00030 //C- | accompanied the software or you may obtain a copy of the license
00031 //C- | from the Free Software Foundation at http://www.fsf.org .
00032 //C- |
00033 //C- | The computer code originally released by LizardTech under this
00034 //C- | license and unmodified by other parties is deemed "the LIZARDTECH
00035 //C- | ORIGINAL CODE."  Subject to any third party intellectual property
00036 //C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
00037 //C- | non-exclusive license to make, use, sell, or otherwise dispose of 
00038 //C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
00039 //C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
00040 //C- | General Public License.   This grant only confers the right to 
00041 //C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
00042 //C- | the extent such infringement is reasonably necessary to enable 
00043 //C- | recipient to make, have made, practice, sell, or otherwise dispose 
00044 //C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
00045 //C- | any greater extent that may be necessary to utilize further 
00046 //C- | modifications or combinations.
00047 //C- |
00048 //C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
00049 //C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
00050 //C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
00051 //C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
00052 //C- +------------------------------------------------------------------
00053 // 
00054 // $Id: GScaler.cpp,v 1.11 2004/06/03 14:15:18 leonb Exp $
00055 
00056 #ifdef HAVE_CONFIG_H
00057 # include "config.h"
00058 #endif
00059 #if NEED_GNUG_PRAGMAS
00060 # pragma implementation
00061 #endif
00062 
00063 // Rescale images with fast bilinear interpolation
00064 // From: Leon Bottou, 1/31/2002
00065 // Almost equal to my initial code.
00066 
00067 #include "GScaler.h"
00068 
00069 
00070 #ifdef HAVE_NAMESPACES
00071 namespace DJVU {
00072 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00073 }
00074 #endif
00075 #endif
00076 
00077 
00079 // CONSTANTS
00080 
00081 
00082 #define FRACBITS  4
00083 #define FRACSIZE  (1<<FRACBITS)
00084 #define FRACSIZE2 (FRACSIZE>>1)
00085 #define FRACMASK  (FRACSIZE-1)
00086 
00087 
00088 
00089 
00090 
00091 
00093 // UTILITIES
00094 
00095 
00096 static int interp_ok = 0;
00097 static short interp[FRACSIZE][512];
00098 
00099 static void
00100 prepare_interp()
00101 {
00102   if (! interp_ok)
00103     {
00104       interp_ok = 1;
00105       for (int i=0; i<FRACSIZE; i++)
00106         {
00107           short *deltas = & interp[i][256];
00108           for (int j = -255; j <= 255; j++)
00109             deltas[j] = ( j*i + FRACSIZE2 ) >> FRACBITS;
00110         }
00111     }
00112 }
00113 
00114 
00115 static inline int
00116 mini(int x, int y) 
00117 { 
00118   return (x < y ? x : y);
00119 }
00120 
00121 
00122 static inline int
00123 maxi(int x, int y) 
00124 { 
00125   return (x > y ? x : y);
00126 }
00127 
00128 
00129 
00130 
00131 
00132 
00134 // GSCALER
00135 
00136 
00137 GScaler::GScaler()
00138   : inw(0), inh(0), 
00139     xshift(0), yshift(0), redw(0), redh(0), 
00140     outw(0), outh(0),
00141     gvcoord(vcoord,0), ghcoord(hcoord,0)
00142 {
00143 }
00144 
00145 
00146 GScaler::~GScaler()
00147 {
00148 }
00149 
00150 
00151 void
00152 GScaler::set_input_size(int w, int h)
00153 { 
00154   inw = w;
00155   inh = h;
00156   if (vcoord)
00157   {
00158     gvcoord.resize(0);
00159   }
00160   if (hcoord)
00161   {
00162     ghcoord.resize(0);
00163   }
00164 }
00165 
00166 
00167 void
00168 GScaler::set_output_size(int w, int h)
00169 { 
00170   outw = w;
00171   outh = h;
00172   if (vcoord)
00173   {
00174     gvcoord.resize(0);
00175   }
00176   if (hcoord)
00177   {
00178     ghcoord.resize(0);
00179   }
00180 }
00181 
00182 
00183 static void
00184 prepare_coord(int *coord, int inmax, int outmax, int in, int out)
00185 {
00186   int len = (in*FRACSIZE);
00187   int beg = (len+out)/(2*out) - FRACSIZE2;
00188   // Bresenham algorithm
00189   int y = beg;
00190   int z = out/2;
00191   int inmaxlim = (inmax-1)*FRACSIZE;
00192   for  (int x=0; x<outmax; x++)
00193     {
00194       coord[x] = mini(y,inmaxlim);
00195       z = z + len;
00196       y = y + z / out;  
00197       z = z % out;
00198     }
00199   // Result must fit exactly
00200   if (out==outmax && y!=beg+len)
00201     G_THROW( ERR_MSG("GScaler.assertion") );
00202 }
00203 
00204 
00205 void 
00206 GScaler::set_horz_ratio(int numer, int denom)
00207 {
00208   if (! (inw>0 && inh>0 && outw>0 && outh>0))
00209     G_THROW( ERR_MSG("GScaler.undef_size") );
00210   // Implicit ratio (determined by the input/output sizes)
00211   if (numer==0 && denom==0) {
00212     numer = outw;
00213     denom = inw;
00214   } else if (numer<=0 || denom<=0)
00215     G_THROW( ERR_MSG("GScaler.ratios") );
00216   // Compute horz reduction
00217   xshift = 0;
00218   redw = inw;
00219   while (numer+numer < denom) {
00220     xshift += 1;
00221     redw = (redw + 1) >> 1;
00222    numer = numer << 1;
00223   }
00224   // Compute coordinate table
00225   if (! hcoord)
00226     ghcoord.resize(outw);
00227   prepare_coord(hcoord, redw, outw, denom, numer);
00228 }
00229 
00230 
00231 void 
00232 GScaler::set_vert_ratio(int numer, int denom)
00233 {
00234   if (! (inw>0 && inh>0 && outw>0 && outh>0))
00235     G_THROW( ERR_MSG("GScaler.undef_size") );
00236   // Implicit ratio (determined by the input/output sizes)
00237   if (numer==0 && denom==0) {
00238     numer = outh;
00239     denom = inh;
00240   } else if (numer<=0 || denom<=0)
00241     G_THROW( ERR_MSG("GScaler.ratios") );
00242   // Compute horz reduction
00243   yshift = 0;
00244   redh = inh;
00245   while (numer+numer < denom) {
00246     yshift += 1;
00247     redh = (redh + 1) >> 1;
00248     numer = numer << 1;
00249   }
00250   // Compute coordinate table
00251   if (! vcoord)
00252   {
00253     gvcoord.resize(outh);
00254   }
00255   prepare_coord(vcoord, redh, outh, denom, numer);
00256 }
00257 
00258 
00259 void
00260 GScaler::make_rectangles(const GRect &desired, GRect &red, GRect &inp)
00261 {
00262   // Parameter validation
00263   if (desired.xmin<0 || desired.ymin<0 ||
00264       desired.xmax>outw || desired.ymax>outh )
00265     G_THROW( ERR_MSG("GScaler.too_big") );
00266   // Compute ratio (if not done yet)
00267   if (!vcoord) 
00268     set_vert_ratio(0,0);
00269   if (!hcoord) 
00270     set_horz_ratio(0,0);
00271   // Compute reduced bounds
00272   red.xmin = (hcoord[desired.xmin]) >> FRACBITS;
00273   red.ymin = (vcoord[desired.ymin]) >> FRACBITS;
00274   red.xmax = (hcoord[desired.xmax-1]+FRACSIZE-1) >> FRACBITS;
00275   red.ymax = (vcoord[desired.ymax-1]+FRACSIZE-1) >> FRACBITS;
00276   // Borders
00277   red.xmin = maxi(red.xmin, 0);
00278   red.xmax = mini(red.xmax+1, redw);
00279   red.ymin = maxi(red.ymin, 0);
00280   red.ymax = mini(red.ymax+1, redh);
00281   // Input
00282   inp.xmin = maxi(red.xmin<<xshift, 0); 
00283   inp.xmax = mini(red.xmax<<xshift, inw); 
00284   inp.ymin = maxi(red.ymin<<yshift, 0); 
00285   inp.ymax = mini(red.ymax<<yshift, inh); 
00286 }
00287 
00288 
00289 void 
00290 GScaler::get_input_rect( const GRect &desired_output, GRect &required_input )
00291 {
00292   GRect red;
00293   make_rectangles(desired_output, red, required_input);
00294 }
00295 
00296 
00297 
00298 
00299 
00300 
00302 // GBITMAPSCALER
00303 
00304 
00305 GBitmapScaler::GBitmapScaler()
00306   : glbuffer(lbuffer,0), gconv(conv,0), gp1(p1,0), gp2(p2,0)
00307 {
00308 }
00309 
00310 
00311 GBitmapScaler::GBitmapScaler(int inw, int inh, int outw, int outh)
00312   : glbuffer(lbuffer,0), gconv(conv,0), gp1(p1,0), gp2(p2,0)
00313 {
00314   set_input_size(inw, inh);
00315   set_output_size(outw, outh);
00316 }
00317 
00318 
00319 GBitmapScaler::~GBitmapScaler()
00320 {
00321 }
00322 
00323 
00324 unsigned char *
00325 GBitmapScaler::get_line(int fy, 
00326                         const GRect &required_red, 
00327                         const GRect &provided_input,
00328                         const GBitmap &input )
00329 {
00330   if (fy < required_red.ymin)
00331     fy = required_red.ymin; 
00332   else if (fy >= required_red.ymax)
00333     fy = required_red.ymax - 1;
00334   // Cached line
00335   if (fy == l2)
00336     return p2;
00337   if (fy == l1)
00338     return p1;
00339   // Shift
00340   unsigned char *p = p1;
00341   p1 = p2;
00342   l1 = l2;
00343   p2 = p;
00344   l2 = fy;
00345   if (xshift==0 && yshift==0)
00346     {
00347       // Fast mode
00348       int dx = required_red.xmin-provided_input.xmin;
00349       int dx1 = required_red.xmax-provided_input.xmin;
00350       const unsigned char *inp1 = input[fy-provided_input.ymin] + dx;
00351       while (dx++ < dx1)
00352         *p++ = conv[*inp1++];
00353       return p2;
00354     }
00355   else
00356     {
00357       // Compute location of line
00358       GRect line;
00359       line.xmin = required_red.xmin << xshift;
00360       line.xmax = required_red.xmax << xshift;
00361       line.ymin = fy << yshift;
00362       line.ymax = (fy+1) << yshift;
00363       line.intersect(line, provided_input);
00364       line.translate(-provided_input.xmin, -provided_input.ymin);
00365       // Prepare variables
00366       const unsigned char *botline = input[line.ymin];
00367       int rowsize = input.rowsize();
00368       int sw = 1<<xshift;
00369       int div = xshift+yshift;
00370       int rnd = 1<<(div-1);
00371       // Compute averages
00372       for (int x=line.xmin; x<line.xmax; x+=sw,p++)
00373         {
00374           int g=0, s=0;
00375           const unsigned char *inp0 = botline + x;
00376           int sy1 = mini(line.height(), (1<<yshift));
00377           for (int sy=0; sy<sy1; sy++,inp0+=rowsize)
00378         {
00379           const unsigned char *inp1;
00380           const unsigned char *inp2 = inp0 + mini(x+sw, line.xmax) - x;
00381           for (inp1=inp0; inp1<inp2; inp1++)
00382         {
00383           g += conv[*inp1];
00384           s += 1;
00385         }
00386         }
00387           if (s == rnd+rnd)
00388             *p = (g+rnd)>>div;
00389           else
00390             *p = (g+s/2)/s;
00391         }
00392       // Return
00393       return p2;
00394     }
00395 }
00396 
00397 
00398 void 
00399 GBitmapScaler::scale( const GRect &provided_input, const GBitmap &input,
00400                       const GRect &desired_output, GBitmap &output )
00401 {
00402   // Compute rectangles
00403   GRect required_input; 
00404   GRect required_red;
00405   make_rectangles(desired_output, required_red, required_input);
00406   // Parameter validation
00407   if (provided_input.width() != (int)input.columns() ||
00408       provided_input.height() != (int)input.rows() )
00409     G_THROW( ERR_MSG("GScaler.no_match") );
00410   if (provided_input.xmin > required_input.xmin ||
00411       provided_input.ymin > required_input.ymin ||
00412       provided_input.xmax < required_input.xmax ||
00413       provided_input.ymax < required_input.ymax  )
00414     G_THROW( ERR_MSG("GScaler.too_small") );
00415   // Adjust output pixmap
00416   if (desired_output.width() != (int)output.columns() ||
00417       desired_output.height() != (int)output.rows() )
00418     output.init(desired_output.height(), desired_output.width());
00419   output.set_grays(256);
00420   // Prepare temp stuff
00421   gp1.resize(0);
00422   gp2.resize(0);
00423   glbuffer.resize(0);
00424   prepare_interp();
00425   const int bufw = required_red.width();
00426   glbuffer.resize(bufw+2);
00427   gp1.resize(bufw);
00428   gp2.resize(bufw);
00429   l1 = l2 = -1;
00430   // Prepare gray conversion array (conv)
00431   gconv.resize(0);
00432   gconv.resize(256);
00433   int maxgray = input.get_grays()-1;
00434   for (int i=0; i<256; i++) 
00435     {
00436       conv[i]=(i<= maxgray)
00437         ?(((i*255) + (maxgray>>1)) / maxgray)
00438         :255;
00439     }
00440   // Loop on output lines
00441   for (int y=desired_output.ymin; y<desired_output.ymax; y++)
00442     {
00443       // Perform vertical interpolation
00444       {
00445         int fy = vcoord[y];
00446         int fy1 = fy>>FRACBITS;
00447         int fy2 = fy1+1;
00448         const unsigned char *lower, *upper;
00449         // Obtain upper and lower line in reduced image
00450         lower = get_line(fy1, required_red, provided_input, input);
00451         upper = get_line(fy2, required_red, provided_input, input);
00452         // Compute line
00453         unsigned char *dest = lbuffer+1;
00454         const short *deltas = & interp[fy&FRACMASK][256];
00455         for(unsigned char const * const edest=(unsigned char const *)dest+bufw;
00456           dest<edest;upper++,lower++,dest++)
00457         {
00458           const int l = *lower;
00459           const int u = *upper;
00460           *dest = l + deltas[u-l];
00461         }
00462       }
00463       // Perform horizontal interpolation
00464       {
00465         // Prepare for side effects
00466         lbuffer[0]   = lbuffer[1];
00467         lbuffer[bufw] = lbuffer[bufw];
00468         unsigned char *line = lbuffer+1-required_red.xmin;
00469         unsigned char *dest  = output[y-desired_output.ymin];
00470         // Loop horizontally
00471         for (int x=desired_output.xmin; x<desired_output.xmax; x++)
00472           {
00473             int n = hcoord[x];
00474             const unsigned char *lower = line + (n>>FRACBITS);
00475             const short *deltas = &interp[n&FRACMASK][256];
00476             int l = lower[0];
00477             int u = lower[1];
00478             *dest = l + deltas[u-l];
00479             dest++;
00480           }
00481       }
00482     }
00483   // Free temporaries
00484   gp1.resize(0);
00485   gp2.resize(0);
00486   glbuffer.resize(0);
00487   gconv.resize(0);
00488 }
00489 
00490 
00491 
00492 
00493 
00494 
00496 // GPIXMAPSCALER
00497 
00498 
00499 GPixmapScaler::GPixmapScaler()
00500   : glbuffer((void *&)lbuffer,0,sizeof(GPixel)), 
00501     gp1((void *&)p1,0,sizeof(GPixel)), 
00502     gp2((void *&)p2,0,sizeof(GPixel))
00503 {
00504 }
00505 
00506 
00507 GPixmapScaler::GPixmapScaler(int inw, int inh, int outw, int outh)
00508   : glbuffer((void *&)lbuffer,0,sizeof(GPixel)), 
00509     gp1((void *&)p1,0,sizeof(GPixel)), 
00510     gp2((void *&)p2,0,sizeof(GPixel))
00511 {
00512   set_input_size(inw, inh);
00513   set_output_size(outw, outh);
00514 }
00515 
00516 
00517 GPixmapScaler::~GPixmapScaler()
00518 {
00519 }
00520 
00521 
00522 GPixel *
00523 GPixmapScaler::get_line(int fy, 
00524                         const GRect &required_red, 
00525                         const GRect &provided_input,
00526                         const GPixmap &input )
00527 {
00528   if (fy < required_red.ymin)
00529     fy = required_red.ymin; 
00530   else if (fy >= required_red.ymax)
00531     fy = required_red.ymax - 1;
00532   // Cached line
00533   if (fy == l2)
00534     return p2;
00535   if (fy == l1)
00536     return p1;
00537   // Shift
00538   GPixel *p=p1;
00539   p1 = p2;
00540   l1 = l2;
00541   p2 = p;
00542   l2 = fy;
00543   // Compute location of line
00544   GRect line;
00545   line.xmin = required_red.xmin << xshift;
00546   line.xmax = required_red.xmax << xshift;
00547   line.ymin = fy << yshift;
00548   line.ymax = (fy+1) << yshift;
00549   line.intersect(line, provided_input);
00550   line.translate(-provided_input.xmin, -provided_input.ymin);
00551   // Prepare variables
00552   const GPixel *botline = input[line.ymin];
00553   int rowsize = input.rowsize();
00554   int sw = 1<<xshift;
00555   int div = xshift+yshift;
00556   int rnd = 1<<(div-1);
00557   // Compute averages
00558   for (int x=line.xmin; x<line.xmax; x+=sw,p++)
00559     {
00560       int r=0, g=0, b=0, s=0;
00561       const GPixel *inp0 = botline + x;
00562       int sy1 = mini(line.height(), (1<<yshift));
00563       for (int sy=0; sy<sy1; sy++,inp0+=rowsize)
00564         {
00565       const GPixel *inp1;
00566       const GPixel *inp2 = inp0 + mini(x+sw, line.xmax) - x;
00567           for (inp1 = inp0; inp1<inp2; inp1++)
00568             {
00569               r += inp1->r;  
00570               g += inp1->g;  
00571               b += inp1->b; 
00572               s += 1;
00573             }
00574         }
00575       if (s == rnd+rnd)
00576         {
00577           p->r = (r+rnd) >> div;
00578           p->g = (g+rnd) >> div;
00579           p->b = (b+rnd) >> div;
00580         }
00581       else
00582         {
00583           p->r = (r+s/2)/s;
00584           p->g = (g+s/2)/s;
00585           p->b = (b+s/2)/s;
00586         }
00587     }
00588   // Return
00589   return (GPixel *)p2;
00590 }
00591 
00592 
00593 void 
00594 GPixmapScaler::scale( const GRect &provided_input, const GPixmap &input,
00595                       const GRect &desired_output, GPixmap &output )
00596 {
00597   // Compute rectangles
00598   GRect required_input; 
00599   GRect required_red;
00600   make_rectangles(desired_output, required_red, required_input);
00601   // Parameter validation
00602   if (provided_input.width() != (int)input.columns() ||
00603       provided_input.height() != (int)input.rows() )
00604     G_THROW( ERR_MSG("GScaler.no_match") );
00605   if (provided_input.xmin > required_input.xmin ||
00606       provided_input.ymin > required_input.ymin ||
00607       provided_input.xmax < required_input.xmax ||
00608       provided_input.ymax < required_input.ymax  )
00609     G_THROW( ERR_MSG("GScaler.too_small") );
00610   // Adjust output pixmap
00611   if (desired_output.width() != (int)output.columns() ||
00612       desired_output.height() != (int)output.rows() )
00613     output.init(desired_output.height(), desired_output.width());
00614   // Prepare temp stuff 
00615   gp1.resize(0,sizeof(GPixel));
00616   gp2.resize(0,sizeof(GPixel));
00617   glbuffer.resize(0,sizeof(GPixel));
00618   prepare_interp();
00619   const int bufw = required_red.width();
00620   glbuffer.resize(bufw+2,sizeof(GPixel));
00621   if (xshift>0 || yshift>0)
00622     {
00623       gp1.resize(bufw,sizeof(GPixel));
00624       gp2.resize(bufw,sizeof(GPixel));
00625       l1 = l2 = -1;
00626     }
00627   // Loop on output lines
00628   for (int y=desired_output.ymin; y<desired_output.ymax; y++)
00629     {
00630       // Perform vertical interpolation
00631       {
00632         int fy = vcoord[y];
00633         int fy1 = fy>>FRACBITS;
00634         int fy2 = fy1+1;
00635         const GPixel *lower, *upper;
00636         // Obtain upper and lower line in reduced image
00637         if (xshift>0 || yshift>0)
00638           {
00639             lower = get_line(fy1, required_red, provided_input, input);
00640             upper = get_line(fy2, required_red, provided_input, input);
00641           }
00642         else
00643           {
00644             int dx = required_red.xmin-provided_input.xmin;
00645             fy1 = maxi(fy1, required_red.ymin);
00646             fy2 = mini(fy2, required_red.ymax-1);
00647             lower = input[fy1-provided_input.ymin] + dx;
00648             upper = input[fy2-provided_input.ymin] + dx;
00649           }
00650         // Compute line
00651         GPixel *dest = lbuffer+1;
00652         const short *deltas = & interp[fy&FRACMASK][256];
00653         for(GPixel const * const edest = (GPixel const *)dest+bufw;
00654           dest<edest;upper++,lower++,dest++)
00655         {
00656           const int lower_r = lower->r;
00657           const int delta_r = deltas[(int)upper->r - lower_r];
00658           dest->r = lower_r + delta_r;
00659           const int lower_g = lower->g;
00660           const int delta_g = deltas[(int)upper->g - lower_g];
00661           dest->g = lower_g + delta_g;
00662           const int lower_b = lower->b;
00663           const int delta_b = deltas[(int)upper->b - lower_b];
00664           dest->b = lower_b + delta_b;
00665         }
00666       }
00667       // Perform horizontal interpolation
00668       {
00669         // Prepare for side effects
00670         lbuffer[0]   = lbuffer[1];
00671         lbuffer[bufw] = lbuffer[bufw];
00672         GPixel *line = lbuffer+1-required_red.xmin;
00673         GPixel *dest  = output[y-desired_output.ymin];
00674         // Loop horizontally
00675         for (int x=desired_output.xmin; x<desired_output.xmax; x++,dest++)
00676           {
00677             const int n = hcoord[x];
00678             const GPixel *lower = line + (n>>FRACBITS);
00679             const short *deltas = &interp[n&FRACMASK][256];
00680             const int lower_r = lower[0].r;
00681             const int delta_r = deltas[(int)lower[1].r - lower_r];
00682             dest->r = lower_r + delta_r;
00683             const int lower_g = lower[0].g;
00684             const int delta_g = deltas[(int)lower[1].g - lower_g];
00685             dest->g = lower_g + delta_g;
00686             const int lower_b = lower[0].b;
00687             const int delta_b = deltas[(int)lower[1].b - lower_b];
00688             dest->b = lower_b + delta_b;
00689           }
00690       }
00691     }
00692   // Free temporaries
00693   gp1.resize(0,sizeof(GPixel));
00694   gp2.resize(0,sizeof(GPixel));
00695   glbuffer.resize(0,sizeof(GPixel));
00696 }
00697 
00698 
00699 
00700 #ifdef HAVE_NAMESPACES
00701 }
00702 # ifndef NOT_USING_DJVU_NAMESPACE
00703 using namespace DJVU;
00704 # endif
00705 #endif
00706 

kviewshell

Skip menu "kviewshell"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • kviewshell
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal