summaryrefslogtreecommitdiff
path: root/src/Fl_Image.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/Fl_Image.cxx')
-rw-r--r--src/Fl_Image.cxx176
1 files changed, 173 insertions, 3 deletions
diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx
index e2e7bd843..3663e4224 100644
--- a/src/Fl_Image.cxx
+++ b/src/Fl_Image.cxx
@@ -1,5 +1,5 @@
//
-// "$Id: Fl_Image.cxx,v 1.5.2.3.2.2 2001/11/18 20:52:28 easysw Exp $"
+// "$Id: Fl_Image.cxx,v 1.5.2.3.2.3 2001/11/19 01:06:45 easysw Exp $"
//
// Image drawing code for the Fast Light Tool Kit (FLTK).
//
@@ -39,6 +39,16 @@ Fl_Image::~Fl_Image() {
void Fl_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
}
+Fl_Image *Fl_Image::copy(int W, int H) {
+ return new Fl_Image(W, H);
+}
+
+void Fl_Image::color_average(Fl_Color c, float i) {
+}
+
+void Fl_Image::desaturate() {
+}
+
void Fl_Image::label(Fl_Widget* w) {
w->image(this);
}
@@ -48,6 +58,166 @@ void Fl_Image::label(Fl_Menu_Item* m) {
Fl_RGB_Image::~Fl_RGB_Image() {
if (id) fl_delete_offscreen((Fl_Offscreen)id);
+ if (alloc_array) delete[] array;
+}
+
+Fl_Image *Fl_RGB_Image::copy(int W, int H) {
+ // Optimize the simple copy where the width and height are the same...
+ if (W == w() && H == h()) return new Fl_RGB_Image(array, w(), h(), d, ld);
+
+ // OK, need to resize the image data; allocate memory and
+ Fl_RGB_Image *new_image; // New RGB image
+ uchar *new_array, // New array for image data
+ *new_ptr; // Pointer into new array
+ const uchar *old_ptr; // Pointer into old array
+ int c, // Channel number
+ sy, // Source coordinate
+ dx, dy, // Destination coordinates
+ xerr, yerr, // X & Y errors
+ xmod, ymod, // X & Y moduli
+ xstep, ystep; // X & Y step increments
+
+
+ // Figure out Bresenheim step/modulus values...
+ xmod = w() % W;
+ xstep = (w() / W) * d;
+ ymod = h() % H;
+ ystep = h() / H;
+
+ // Allocate memory for the new image...
+ new_array = new uchar [W * H * d];
+ 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 / 2, new_ptr = new_array; dy > 0; dy --) {
+ for (dx = w(), xerr = W / 2, old_ptr = array + sy * (w() * d + ld);
+ dx > 0;
+ dx --) {
+ for (c = 0; c < d; c ++) *new_ptr++ = old_ptr[c];
+
+ old_ptr += xstep;
+ xerr -= xmod;
+
+ if (xerr <= 0) {
+ xerr += W;
+ old_ptr += d;
+ }
+ }
+
+ sy += ystep;
+ yerr -= ymod;
+ if (yerr <= 0) {
+ yerr += H;
+ sy ++;
+ }
+ }
+
+ return new_image;
+}
+
+void Fl_RGB_Image::color_average(Fl_Color c, float i) {
+ // Delete any existing pixmap/mask objects...
+ if (id) {
+ fl_delete_offscreen(id);
+ id = 0;
+ }
+
+ if (mask) {
+ fl_delete_bitmask(mask);
+ mask = 0;
+ }
+
+ // Allocate memory as needed...
+ uchar *new_array,
+ *new_ptr;
+
+ if (!alloc_array) new_array = new uchar[h() * w() * d];
+ else new_array = (uchar *)array;
+
+ // Get the color to blend with...
+ uchar r, g, b;
+ unsigned ia, ir, ig, ib;
+
+ Fl::get_color(c, r, g, b);
+ if (i < 0.0f) i = 0.0f;
+ else if (i > 1.0f) i = 1.0f;
+
+ ia = (unsigned)(256 * i);
+ ir = r * (256 - ia);
+ ig = g * (256 - ia);
+ ib = b * (256 - ia);
+
+ // Update the image data to do the blend...
+ const uchar *old_ptr;
+ int x, y;
+
+ if (d < 3) {
+ ig = (r * 31 + g * 61 + b * 8) / 100 * (256 - ia);
+
+ for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += ld)
+ for (x = 0; x < w(); x ++) {
+ *new_ptr++ = (*old_ptr++ * ia + ig) >> 8;
+ if (d > 1) *new_ptr++ = *old_ptr++;
+ }
+ } else {
+ for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += ld)
+ for (x = 0; x < w(); x ++) {
+ *new_ptr++ = (*old_ptr++ * ia + ir) >> 8;
+ *new_ptr++ = (*old_ptr++ * ia + ig) >> 8;
+ *new_ptr++ = (*old_ptr++ * ia + ib) >> 8;
+ if (d > 3) *new_ptr++ = *old_ptr++;
+ }
+ }
+
+ // Set the new pointers/values as needed...
+ if (!alloc_array) {
+ array = new_array;
+ alloc_array = 1;
+ ld = 0;
+ }
+}
+
+void Fl_RGB_Image::desaturate() {
+ // Can only desaturate color images...
+ if (d < 3) return;
+
+ // Delete any existing pixmap/mask objects...
+ if (id) {
+ fl_delete_offscreen(id);
+ id = 0;
+ }
+
+ if (mask) {
+ fl_delete_bitmask(mask);
+ mask = 0;
+ }
+
+ // Allocate memory for a grayscale image...
+ uchar *new_array,
+ *new_ptr;
+ int new_d;
+
+ new_d = d - 2;
+ new_array = new uchar[h() * w() * new_d];
+
+ // Copy the image data, converting to grayscale...
+ const uchar *old_ptr;
+ int x, y;
+
+ for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += ld)
+ for (x = 0; x < w(); x ++, old_ptr += d) {
+ *new_ptr++ = (31 * old_ptr[0] + 61 * old_ptr[1] + 8 * old_ptr[2]) / 100;
+ if (d > 3) *new_ptr++ = old_ptr[3];
+ }
+
+ // Free the old array as needed, and then set the new pointers/values...
+ if (alloc_array) delete[] array;
+
+ array = new_array;
+ alloc_array = 1;
+ d = new_d;
+ ld = 0;
}
void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
@@ -113,7 +283,7 @@ void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
// definitely fast...
memset(bitmap, 0, bmw * h());
- for (dataptr = array + d - 1, y = 0; y < h(); y ++)
+ for (dataptr = array + d - 1, y = 0; y < h(); y ++, dataptr += ld)
for (bitptr = bitmap + y * bmw, bit = 128, x = 0; x < w(); x ++, dataptr += d) {
if (*dataptr > dither[x & 15][y & 15])
*bitptr |= bit;
@@ -224,5 +394,5 @@ void Fl_RGB_Image::label(Fl_Menu_Item* m) {
//
-// End of "$Id: Fl_Image.cxx,v 1.5.2.3.2.2 2001/11/18 20:52:28 easysw Exp $".
+// End of "$Id: Fl_Image.cxx,v 1.5.2.3.2.3 2001/11/19 01:06:45 easysw Exp $".
//