Logo Search packages:      
Sourcecode: djvulibre version File versions

void GPixmapScaler::scale ( const GRect provided_input,
const GPixmap input,
const GRect desired_output,
GPixmap output 
)

Computes a segment of the rescaled output image. The pixmap output# is overwritten with the segment of the output image specified by the rectangle desired_output#. The rectangle provided_input# specifies which segment of the input image is provided in the pixmap input#. An exception {GException} is thrown if the rectangle provided_input# is smaller then the rectangle required_input# returned by function {GScaler::get_input_rect}.

Definition at line 594 of file GScaler.cpp.

References GPixel::b, GPixmap::columns(), GPixel::g, GRect::height(), GPixmap::init(), GPixel::r, GPixmap::rows(), GRect::width(), GRect::xmax, GRect::xmin, GRect::ymax, and GRect::ymin.

{
  // Compute rectangles
  GRect required_input; 
  GRect required_red;
  make_rectangles(desired_output, required_red, required_input);
  // Parameter validation
  if (provided_input.width() != (int)input.columns() ||
      provided_input.height() != (int)input.rows() )
    G_THROW( ERR_MSG("GScaler.no_match") );
  if (provided_input.xmin > required_input.xmin ||
      provided_input.ymin > required_input.ymin ||
      provided_input.xmax < required_input.xmax ||
      provided_input.ymax < required_input.ymax  )
    G_THROW( ERR_MSG("GScaler.too_small") );
  // Adjust output pixmap
  if (desired_output.width() != (int)output.columns() ||
      desired_output.height() != (int)output.rows() )
    output.init(desired_output.height(), desired_output.width());
  // Prepare temp stuff 
  gp1.resize(0,sizeof(GPixel));
  gp2.resize(0,sizeof(GPixel));
  glbuffer.resize(0,sizeof(GPixel));
  prepare_interp();
  const int bufw = required_red.width();
  glbuffer.resize(bufw+2,sizeof(GPixel));
  if (xshift>0 || yshift>0)
    {
      gp1.resize(bufw,sizeof(GPixel));
      gp2.resize(bufw,sizeof(GPixel));
      l1 = l2 = -1;
    }
  // Loop on output lines
  for (int y=desired_output.ymin; y<desired_output.ymax; y++)
    {
      // Perform vertical interpolation
      {
        int fy = vcoord[y];
        int fy1 = fy>>FRACBITS;
        int fy2 = fy1+1;
        const GPixel *lower, *upper;
        // Obtain upper and lower line in reduced image
        if (xshift>0 || yshift>0)
          {
            lower = get_line(fy1, required_red, provided_input, input);
            upper = get_line(fy2, required_red, provided_input, input);
          }
        else
          {
            int dx = required_red.xmin-provided_input.xmin;
            fy1 = maxi(fy1, required_red.ymin);
            fy2 = mini(fy2, required_red.ymax-1);
            lower = input[fy1-provided_input.ymin] + dx;
            upper = input[fy2-provided_input.ymin] + dx;
          }
        // Compute line
        GPixel *dest = lbuffer+1;
        const short *deltas = & interp[fy&FRACMASK][256];
        for(GPixel const * const edest = (GPixel const *)dest+bufw;
          dest<edest;upper++,lower++,dest++)
        {
          const int lower_r = lower->r;
          const int delta_r = deltas[(int)upper->r - lower_r];
          dest->r = lower_r + delta_r;
          const int lower_g = lower->g;
          const int delta_g = deltas[(int)upper->g - lower_g];
          dest->g = lower_g + delta_g;
          const int lower_b = lower->b;
          const int delta_b = deltas[(int)upper->b - lower_b];
          dest->b = lower_b + delta_b;
        }
      }
      // Perform horizontal interpolation
      {
        // Prepare for side effects
        lbuffer[0]   = lbuffer[1];
        lbuffer[bufw] = lbuffer[bufw];
        GPixel *line = lbuffer+1-required_red.xmin;
        GPixel *dest  = output[y-desired_output.ymin];
        // Loop horizontally
        for (int x=desired_output.xmin; x<desired_output.xmax; x++,dest++)
          {
            const int n = hcoord[x];
            const GPixel *lower = line + (n>>FRACBITS);
            const short *deltas = &interp[n&FRACMASK][256];
            const int lower_r = lower[0].r;
            const int delta_r = deltas[(int)lower[1].r - lower_r];
            dest->r = lower_r + delta_r;
            const int lower_g = lower[0].g;
            const int delta_g = deltas[(int)lower[1].g - lower_g];
            dest->g = lower_g + delta_g;
            const int lower_b = lower[0].b;
            const int delta_b = deltas[(int)lower[1].b - lower_b];
            dest->b = lower_b + delta_b;
          }
      }
    }
  // Free temporaries
  gp1.resize(0,sizeof(GPixel));
  gp2.resize(0,sizeof(GPixel));
  glbuffer.resize(0,sizeof(GPixel));
}


Generated by  Doxygen 1.6.0   Back to index