> 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