git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10268 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
105c2b466a
commit
cce4cece01
@ -154,6 +154,14 @@ class FL_EXPORT Fl_Image {
|
||||
virtual void uncache();
|
||||
};
|
||||
|
||||
/// \enum Fl_RGB_Scaling
|
||||
/// The scaling algorithm to use.
|
||||
///
|
||||
enum Fl_RGB_Scaling {
|
||||
FL_SCALING_NEAREST = 0,
|
||||
FL_SCALING_BILINEAR
|
||||
};
|
||||
|
||||
/**
|
||||
The Fl_RGB_Image class supports caching and drawing
|
||||
of full-color images with 1 to 4 channels of color information.
|
||||
@ -170,6 +178,7 @@ class FL_EXPORT Fl_RGB_Image : public Fl_Image {
|
||||
friend class Fl_GDI_Graphics_Driver;
|
||||
friend class Fl_Xlib_Graphics_Driver;
|
||||
static size_t max_size_;
|
||||
static Fl_RGB_Scaling scaling_;
|
||||
public:
|
||||
|
||||
const uchar *array;
|
||||
@ -230,6 +239,14 @@ public:
|
||||
\sa void Fl_RGB_Image::max_size(size_t)
|
||||
*/
|
||||
static size_t max_size() {return max_size_;}
|
||||
|
||||
/** Sets the currently used scaling method.
|
||||
Applies to all RGB images, defaults to FL_SCALING_NEAREST.
|
||||
*/
|
||||
static void scaling(Fl_RGB_Scaling);
|
||||
|
||||
/** Returns the currently used scaling method. */
|
||||
static Fl_RGB_Scaling scaling();
|
||||
};
|
||||
|
||||
#endif // !Fl_Image_H
|
||||
|
@ -164,6 +164,7 @@ Fl_Image::measure(const Fl_Label *lo, // I - Label
|
||||
// RGB image class...
|
||||
//
|
||||
size_t Fl_RGB_Image::max_size_ = ~((size_t)0);
|
||||
Fl_RGB_Scaling Fl_RGB_Image::scaling_ = FL_SCALING_NEAREST;
|
||||
|
||||
int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg);
|
||||
|
||||
@ -260,25 +261,84 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) {
|
||||
new_image = new Fl_RGB_Image(new_array, W, H, d());
|
||||
new_image->alloc_array = 1;
|
||||
|
||||
// Scale the image using a nearest-neighbor algorithm...
|
||||
for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) {
|
||||
for (dx = W, xerr = W, old_ptr = array + sy * line_d; dx > 0; dx --) {
|
||||
for (c = 0; c < d(); c ++) *new_ptr++ = old_ptr[c];
|
||||
if (scaling_ == FL_SCALING_NEAREST) {
|
||||
// Scale the image using a nearest-neighbor algorithm...
|
||||
for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) {
|
||||
for (dx = W, xerr = W, old_ptr = array + sy * line_d; dx > 0; dx --) {
|
||||
for (c = 0; c < d(); c ++) *new_ptr++ = old_ptr[c];
|
||||
|
||||
old_ptr += xstep;
|
||||
xerr -= xmod;
|
||||
old_ptr += xstep;
|
||||
xerr -= xmod;
|
||||
|
||||
if (xerr <= 0) {
|
||||
xerr += W;
|
||||
old_ptr += d();
|
||||
if (xerr <= 0) {
|
||||
xerr += W;
|
||||
old_ptr += d();
|
||||
}
|
||||
}
|
||||
|
||||
sy += ystep;
|
||||
yerr -= ymod;
|
||||
if (yerr <= 0) {
|
||||
yerr += H;
|
||||
sy ++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Bilinear scaling
|
||||
const float xscale = (w() - 1) / (float) W;
|
||||
const float yscale = (h() - 1) / (float) H;
|
||||
for (dy = 0; dy < H; dy++) {
|
||||
float oldy = dy * yscale;
|
||||
if (oldy >= h())
|
||||
oldy = h() - 1;
|
||||
const float yfract = oldy - (unsigned) oldy;
|
||||
|
||||
sy += ystep;
|
||||
yerr -= ymod;
|
||||
if (yerr <= 0) {
|
||||
yerr += H;
|
||||
sy ++;
|
||||
for (dx = 0; dx < W; dx++) {
|
||||
new_ptr = new_array + dy * W * d() + dx * d();
|
||||
|
||||
float oldx = dx * xscale;
|
||||
if (oldx >= w())
|
||||
oldx = w() - 1;
|
||||
const float xfract = oldx - (unsigned) oldx;
|
||||
|
||||
const unsigned leftx = oldx;
|
||||
const unsigned lefty = oldy;
|
||||
const unsigned rightx = oldx + 1 >= w() ? oldx : oldx + 1;
|
||||
const unsigned righty = oldy;
|
||||
const unsigned dleftx = oldx;
|
||||
const unsigned dlefty = oldy + 1 >= h() ? oldy : oldy + 1;
|
||||
const unsigned drightx = rightx;
|
||||
const unsigned drighty = dlefty;
|
||||
|
||||
uchar left[4], right[4], downleft[4], downright[4];
|
||||
memcpy(left, array + lefty * line_d + leftx * d(), d());
|
||||
memcpy(right, array + righty * line_d + rightx * d(), d());
|
||||
memcpy(downleft, array + dlefty * line_d + dleftx * d(), d());
|
||||
memcpy(downright, array + drighty * line_d + drightx * d(), d());
|
||||
|
||||
// TODO: how to check if it's premultiplied alpha?
|
||||
int i;
|
||||
if (d() == 4) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
left[i] *= left[3] / 255.0f;
|
||||
right[i] *= right[3] / 255.0f;
|
||||
downleft[i] *= downleft[3] / 255.0f;
|
||||
downright[i] *= downright[3] / 255.0f;
|
||||
}
|
||||
}
|
||||
|
||||
const float leftf = 1 - xfract;
|
||||
const float rightf = xfract;
|
||||
const float upf = 1 - yfract;
|
||||
const float downf = yfract;
|
||||
|
||||
for (i = 0; i < d(); i++) {
|
||||
new_ptr[i] = (left[i] * leftf +
|
||||
right[i] * rightf) * upf +
|
||||
(downleft[i] * leftf +
|
||||
downright[i] * rightf) * downf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -614,6 +674,13 @@ void Fl_RGB_Image::label(Fl_Menu_Item* m) {
|
||||
m->label(_FL_IMAGE_LABEL, (const char*)this);
|
||||
}
|
||||
|
||||
void Fl_RGB_Image::scaling(Fl_RGB_Scaling method) {
|
||||
scaling_ = method;
|
||||
}
|
||||
|
||||
Fl_RGB_Scaling Fl_RGB_Image::scaling() {
|
||||
return scaling_;
|
||||
}
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
|
Loading…
x
Reference in New Issue
Block a user