> Using .copy(width, height) to resize an Fl_JPEG_Image is very fast,
> but the resulting thumbnail is not as pretty as using "convert"
> utility of ImageMagick.
>
> Is there a way to resize jpegs in fltk that results in better looking
> thumbnails? Or to set the quality of the .copy?
>
> --
> Robert Arkiletian
> Eric Hamber Secondary, Vancouver, Canada
> Fl_TeacherTool http://www3.telus.net/public/robark/Fl_TeacherTool/
> C++ GUI tutorial http://www3.telus.net/public/robark/
>

Robert,

If you don't want to link an entire image manipulation library, then the 
following code will produce a smoother image for you (much more evident when 
the original is small).  Note that there is room to improve the speed of this 
code significantly.

Don.


/******************************************************************************/
/******************************************************************************/


#include <FL/Fl.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>


/******************************************************************************/
/******************************************************************************/


inline void linear(uchar *src, int d, int lo, int hi, double frac, uchar *dst)
{
  int i;

  for(i=0; i<d; i++,lo++,hi++)
  {
    dst[i] = (uchar)(src[lo] + ((src[hi] - src[lo]) * frac) + 0.5);
  }
}


/******************************************************************************/
/******************************************************************************/


inline void bilinear(uchar *src, int d, int sw, int se, int nw, int ne, double 
fx, double fy, uchar *dst)
{
  double s, n;
  int i;

  for(i=0; i<d; i++,sw++,se++,nw++,ne++)
  {
    s = src[sw] + ((src[se] - src[sw]) * fx);
    n = src[nw] + ((src[ne] - src[nw]) * fx);
    dst[i] = (uchar)(s + ((n - s) * fy) + 0.5);
  }
}


/******************************************************************************/
/******************************************************************************/


void resample(uchar *src, int src_w, int src_h, int d, uchar *dst, int dst_w, 
int dst_h)
{
  double sx, sy, fx, fy, u, v;
  int i, j, k, sw, se, nw, ne, s, t, dx, dy, src_ex, src_ey, dst_ex, dst_ey;

  src_ex = (src_w - 1);
  src_ey = (src_h - 1);

  dst_ex = (dst_w - 1);
  dst_ey = (dst_h - 1);

  /* hack: ensures that sx/sy division produces 0 index when w/h are 1 pix
  */
  sx = (src_ex)? dst_ex/(double)src_ex : (double)dst_w;
  sy = (src_ey)? dst_ey/(double)src_ey : (double)dst_h;

  /* bottom row
  */
  k = 0;
  dy = 0; t = 0; fy = 0.0;

  /* left column
  */
  dx = 0; s = 0; fx = 0.0;
  sw = (t*src_w + s) * d; se = sw + dx;
  linear(src, d, sw, se, fx, &dst[k]);
  k+=d;

  /* interior columns
  */
  dx = (src_ex)? d : 0;
  for(i=1; i<dst_ex; i++)
  {
    u = i/sx; s = (int)u; fx = u - s;
    sw = (t*src_w + s) * d; se = sw + dx;
    linear(src, d, sw, se, fx, &dst[k]);
    k+=d;
  }

  /* right column
  */
  if(dst_ex)
  {
    dx = 0; s = src_ex; fx = 0.0;
    sw = (t*src_w + s) * d; se = sw + dx;
    linear(src, d, sw, se, fx, &dst[k]);
    k+=d;
  }

  /* interior rows
  */
  dy = (src_ey)? src_w * d : 0;
  for(j=1; j<dst_ey; j++)
  {
    v = j/sy; t = (int)v; fy = v - t;

    /* left column
    */
    dx = 0; s = 0; fx = 0.0;
    sw = (t*src_w + s) * d; nw = sw + dy;
    linear(src, d, sw, nw, fy, &dst[k]);
    k+=d;

    /* interior columns
    */
    dx = (src_ex)? d : 0;
    for(i=1; i<dst_ex; i++)
    {
      u = i/sx; s = (int)u; fx = u - s;
      sw = (t*src_w + s) * d; se = sw + dx; nw = sw + dy; ne = nw + dx;
      bilinear(src, d, sw, se, nw, ne, fx, fy, &dst[k]);
      k+=d;
    }

    /* right column
    */
    if(dst_ex)
    {
      dx = 0; s = src_ex; fx = 0.0;
      sw = (t*src_w + s) * d; nw = sw + dy;
      linear(src, d, sw, nw, fy, &dst[k]);
      k+=d;
    }
  }

  /* top row
  */
  if(dst_ey)
  {
    dy = 0; t = src_ey; fy = 0.0;

    /* left column
    */
    dx = 0; s = 0; fx = 0.0;
    sw = (t*src_w + s) * d; se = sw + dx;
    linear(src, d, sw, se, fx, &dst[k]);
    k+=d;

    /* interior columns
    */
    dx = (src_ex)? d : 0;
    for(i=1; i<dst_ex; i++)
    {
      u = i/sx; s = (int)u; fx = u - s;
      sw = (t*src_w + s) * d; se = sw + dx;
      linear(src, d, sw, se, fx, &dst[k]);
      k+=d;
    }

    /* right column
    */
    if(dst_ex)
    {
      dx = 0; s = src_ex; fx = 0.0;
      sw = (t*src_w + s) * d; se = sw + dx;
      linear(src, d, sw, se, fx, &dst[k]);
      k+=d;
    }
  }
}


/******************************************************************************/
/******************************************************************************/


class Fl_Img_Box : public Fl_Box
{
public:
  Fl_Img_Box(int x, int y, int w, int h, const char *l = 0) : Fl_Box(x, y, w, 
h, l)
  {
    img_ = 0;
    smooth_ = 0;
  }
  void resize(int x, int y, int w, int h)
  {
    if(img_ && img_->count())
    {
      Fl_Image *img = image();
      if(img) delete img;
      img = img_->copy(w-Fl::box_dw(box()), h-Fl::box_dh(box()));
      Fl_Box::image(img);

      if(smooth_ && img && (img->count() == 1) && (img->d() == 3 || img->d() == 
4) && (img->ld() == 0))
      {
        uchar **src = (uchar**)img_->data();
        uchar **dst = (uchar**)img->data();
        resample(src[0], img_->w(), img_->h(), img_->d(), dst[0], img->w(), 
img->h());
      }
    }
    Fl_Box::resize(x, y, w, h);
  }
  Fl_Image *image()
  {
    return Fl_Box::image();
  }
  void image(Fl_Image *img)
  {
    img_ = img;
    resize(x(), y(), w(), h());
  }
  void smooth(int b)
  {
    smooth_ = b;
  }
  Fl_Image *img_;
  int smooth_;
};


/******************************************************************************/
/******************************************************************************/


int main(int argc, char *argv[])
{
# define WW 400
# define HH 300

  fl_register_images();

  Fl_Image *img = Fl_Shared_Image::get("small.jpg");

  {
    Fl_Double_Window *w = new Fl_Double_Window(WW, HH, "Resize");
    Fl_Img_Box *o = new Fl_Img_Box(0, 0, WW, HH);
    o->smooth(0);
    o->image(img);
    w->end();
    w->resizable(o);
    w->show();
  }

  {
    Fl_Double_Window *w = new Fl_Double_Window(WW, HH, "Resample");
    Fl_Img_Box *o = new Fl_Img_Box(0, 0, WW, HH);
    o->smooth(1);
    o->image(img);
    w->end();
    w->resizable(o);
    w->show();
  }

  return Fl::run();
}


/******************************************************************************/
/******************************************************************************/





_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to