diff --git a/CHANGES b/CHANGES index b8fa611d8..e537b4c72 100644 --- a/CHANGES +++ b/CHANGES @@ -132,6 +132,11 @@ CHANGES IN FLTK 1.3.4 RELEASED: ??? ?? 2016 - Several box types were not drawn correctly when deactivated. The background color for deactivated widgets is now correct: fl_inactive(color()) (STR #2907). + - Fix inconsistent interpretation of ld() in image handling + (STR #3308). This is a minor issue since ld() is usually 0 or + w()*d(). Documentation has been fixed, and ld() handling is now + consistent in Fl_(RGB_)Image and fl_draw_image() and friends. See + documentation of Fl_Image and Fl_RGB_Image for more information. - Fixed Fl_Pixmap (background) drawing to respect the clip region (STR #3206). - Reading of .pbm image files is fixed: 1 is now interpreted as diff --git a/FL/Fl_Image.H b/FL/Fl_Image.H index 37774ef1d..af0926146 100644 --- a/FL/Fl_Image.H +++ b/FL/Fl_Image.H @@ -3,7 +3,7 @@ // // Image header file for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2014 by Bill Spitzak and others. +// Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -84,6 +84,14 @@ protected: void d(int D) {d_ = D;} /** Sets the current line data size in bytes. + + Color images may contain extra data that is included after every + line of color image data and is normally not present. + + If \p LD is zero, then line data size is assumed to be w() * d() bytes. + + If \p LD is non-zero, then it must be positive and larger than w() * d() + to account for the extra data per line. */ void ld(int LD) {ld_ = LD;} /** @@ -113,8 +121,7 @@ public: int d() const {return d_;} /** Returns the current line data size in bytes. - Line data is extra data that is included - after each line of color image data and is normally not present. + \see ld(int) */ int ld() const {return ld_;} /** diff --git a/fluid/Fluid_Image.cxx b/fluid/Fluid_Image.cxx index bbaa423e0..653d45abc 100644 --- a/fluid/Fluid_Image.cxx +++ b/fluid/Fluid_Image.cxx @@ -3,7 +3,7 @@ // // Pixmap (and other images) label support for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2015 by Bill Spitzak and others. +// Copyright 1998-2016 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -123,7 +123,8 @@ void Fluid_Image::write_static() { image_header_written = write_number; } write_c("static const unsigned char %s[] =\n", idata_name); - write_cdata(img->data()[0], (img->w() * img->d() + img->ld()) * img->h()); + const int extra_data = img->ld() ? (img->ld()-img->w()*img->d()) : 0; + write_cdata(img->data()[0], (img->w() * img->d() + extra_data) * img->h()); write_c(";\n"); write_initializer("Fl_RGB_Image", "%s, %d, %d, %d, %d", idata_name, img->w(), img->h(), img->d(), img->ld()); } diff --git a/src/Fl_File_Icon2.cxx b/src/Fl_File_Icon2.cxx index bb6964c07..1f13e7372 100644 --- a/src/Fl_File_Icon2.cxx +++ b/src/Fl_File_Icon2.cxx @@ -353,9 +353,10 @@ int Fl_File_Icon::load_image(const char *ifile) // I - File to read from temp; // Temporary color const uchar *row; // Pointer into image + const int extra_data = img->ld() ? (img->ld()-img->w()*img->d()) : 0; // Loop through grayscale or RGB image... - for (y = 0, row = (const uchar *)(*(img->data())); y < img->h(); y ++, row += img->ld()) + for (y = 0, row = (const uchar *)(*(img->data())); y < img->h(); y ++, row += extra_data) { for (x = 0, startx = 0, c = (Fl_Color)-1; x < img->w(); @@ -427,7 +428,6 @@ int Fl_File_Icon::load_image(const char *ifile) // I - File to read from int x, y; // X & Y in image int startx; // Starting X coord - // Get the pixmap data... ptr = img->data(); sscanf(*ptr, "%*d%*d%d%d", &ncolors, &chars_per_color); diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx index 7407138d8..72c8506ce 100644 --- a/src/Fl_Image.cxx +++ b/src/Fl_Image.cxx @@ -237,24 +237,39 @@ int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg); /** - The constructor creates a new image from the specified data. - \param[in] bits The image data array. - \param[in] W The width of the image in pixels - \param[in] H The height of the image in pixels - \param[in] D The image depth, or 'number of channels'. Default=3
- If D=1, each uchar in bits[] is a grayscale pixel value.
- If D=2, each uchar pair in bits[] is a grayscale + alpha pixel value.
- If D=3, each uchar triplet in bits[] is an R/G/B pixel value
- If D=4, each uchar quad in bits[] is an R/G/B/A pixel value. - \param[in] LD Line data size (default=0).
- Line data is extra data that is included after each line - of color image data and is normally not present. - + The constructor creates a new image from the specified data. + + The data array \p bits must contain sufficient data to provide + \p W * \p H * \p D image bytes and optional line padding, see \p LD. + + \p W and \p H are the width and height of the image in pixels, resp. + + \p D is the image depth and can be: + - D=1: each uchar in \p bits[] is a grayscale pixel value + - D=2: each uchar pair in \p bits[] is a grayscale + alpha pixel value + - D=3: each uchar triplet in \p bits[] is an R/G/B pixel value + - D=4: each uchar quad in \p bits[] is an R/G/B/A pixel value + + \p LD specifies the line data size of the array, see Fl_Image::ld(int). + If \p LD is zero, then \p W * \p D is assumed, otherwise \p LD must be + greater than or equal to \p W * \p D to account for (unused) extra data + per line (padding). + + The caller is responsible that the image data array \p bits persists as + long as the image is used. + This constructor sets Fl_RGB_Image::alloc_array to 0. - To have the image object control the deallocation of the data array, - set alloc_array to non-zero after construction. - \see Fl_Image::data(), Fl_Image::w(), Fl_Image::h(), Fl_Image::d(), Fl_Image::ld() - */ + To have the image object control the deallocation of the data array + \p bits, set alloc_array to non-zero after construction. + + \param[in] bits The image data array. + \param[in] W The width of the image in pixels. + \param[in] H The height of the image in pixels. + \param[in] D The image depth, or 'number of channels' (default=3). + \param[in] LD Line data size (default=0). + + \see Fl_Image::data(), Fl_Image::w(), Fl_Image::h(), Fl_Image::d(), Fl_Image::ld(int) +*/ Fl_RGB_Image::Fl_RGB_Image(const uchar *bits, int W, int H, int D, int LD) : Fl_Image(W,H,D), array(bits), @@ -268,12 +283,15 @@ Fl_RGB_Image::Fl_RGB_Image(const uchar *bits, int W, int H, int D, int LD) : /** - The constructor creates a new RGBA image from the specified Fl_Pixmap. - - The RGBA image is built fully opaque except for the transparent area - of the pixmap that is assigned the \p bg color with full transparency - This constructor sets Fl_RGB_Image::alloc_array to 1. - */ + The constructor creates a new RGBA image from the specified Fl_Pixmap. + + The RGBA image is built fully opaque except for the transparent area + of the pixmap that is assigned the \p bg color with full transparency. + + This constructor creates a new internal data array and sets + Fl_RGB_Image::alloc_array to 1 so the data array is deleted when the + image is destroyed. +*/ Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg): Fl_Image(pxm->w(), pxm->h(), 4), id_(0), @@ -286,10 +304,10 @@ Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg): } -/** - The destructor frees all memory and server resources that are used by - the image. - */ +/** + The destructor frees all memory and server resources that are used by + the image. +*/ Fl_RGB_Image::~Fl_RGB_Image() { #ifdef __APPLE__ if (id_) CGImageRelease((CGImageRef)id_); @@ -409,7 +427,7 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) { for (dy = 0; dy < H; dy++) { float oldy = dy * yscale; if (oldy >= h()) - oldy = h() - 1; + oldy = float(h() - 1); const float yfract = oldy - (unsigned) oldy; for (dx = 0; dx < W; dx++) { @@ -417,17 +435,17 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) { float oldx = dx * xscale; if (oldx >= w()) - oldx = w() - 1; + oldx = float(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; + const unsigned leftx = (unsigned)oldx; + const unsigned lefty = (unsigned)oldy; + const unsigned rightx = (unsigned)(oldx + 1 >= w() ? oldx : oldx + 1); + const unsigned righty = (unsigned)oldy; + const unsigned dleftx = (unsigned)oldx; + const unsigned dlefty = (unsigned)(oldy + 1 >= h() ? oldy : oldy + 1); + const unsigned drightx = (unsigned)rightx; + const unsigned drighty = (unsigned)dlefty; uchar left[4], right[4], downleft[4], downright[4]; memcpy(left, array + lefty * line_d + leftx * d(), d()); @@ -438,10 +456,10 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) { 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; + left[i] = (uchar)(left[i] * left[3] / 255.0f); + right[i] = (uchar)(right[i] * right[3] / 255.0f); + downleft[i] = (uchar)(downleft[i] * downleft[3] / 255.0f); + downright[i] = (uchar)(downright[i] * downright[3] / 255.0f); } } @@ -451,15 +469,15 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) { const float downf = yfract; for (i = 0; i < d(); i++) { - new_ptr[i] = (left[i] * leftf + + new_ptr[i] = (uchar)((left[i] * leftf + right[i] * rightf) * upf + (downleft[i] * leftf + - downright[i] * rightf) * downf; + downright[i] * rightf) * downf); } if (d() == 4 && new_ptr[3]) { for (i = 0; i < 3; i++) { - new_ptr[i] /= new_ptr[3] / 255.0f; + new_ptr[i] = (uchar)(new_ptr[i] / (new_ptr[3] / 255.0f)); } } } diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index c3b2d4ef5..2de099543 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -2225,8 +2225,10 @@ static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon, return NULL; const uchar *i = (const uchar*)*image->data(); - for (int y = 0;y < image->h();y++) { - for (int x = 0;x < image->w();x++) { + const int extra_data = image->ld() ? (image->ld()-image->w()*image->d()) : 0; + + for (int y = 0; y < image->h(); y++) { + for (int x = 0; x < image->w(); x++) { switch (image->d()) { case 1: *bits = (0xff<<24) | (i[0]<<16) | (i[0]<<8) | i[0]; @@ -2244,7 +2246,7 @@ static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon, i += image->d(); bits++; } - i += image->ld(); + i += extra_data; } // A mask bitmap is still needed even though it isn't used @@ -2267,9 +2269,6 @@ static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon, DeleteObject(bitmap); DeleteObject(mask); - if (icon == NULL) - return NULL; - return icon; } diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index e0be1a0a6..df6ca4d5c 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -2727,9 +2727,11 @@ static void icons_to_property(const Fl_RGB_Image *icons[], int count, data[1] = image->h(); data += 2; + const int extra_data = image->ld() ? (image->ld()-image->w()*image->d()) : 0; + const uchar *in = (const uchar*)*image->data(); - for (int y = 0;y < image->h();y++) { - for (int x = 0;x < image->w();x++) { + for (int y = 0; y < image->h(); y++) { + for (int x = 0; x < image->w(); x++) { switch (image->d()) { case 1: *data = ( 0xff<<24) | (in[0]<<16) | (in[0]<<8) | in[0]; @@ -2747,7 +2749,7 @@ static void icons_to_property(const Fl_RGB_Image *icons[], int count, in += image->d(); data++; } - in += image->ld(); + in += extra_data; } } } @@ -2863,6 +2865,7 @@ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { if (!cursor) return 0; + const int extra_data = image->ld() ? (image->ld()-image->w()*image->d()) : 0; const uchar *i = (const uchar*)*image->data(); XcursorPixel *o = cursor->pixels; for (int y = 0;y < image->h();y++) { @@ -2884,7 +2887,7 @@ int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { i += image->d(); o++; } - i += image->ld(); + i += extra_data; } cursor->xhot = hotx;