Fix inconsistent interpretation of ld() in image handling (STR #3308).

Documentation has been fixed and clarified, and ld() handling is now
consistent in Fl_(RGB_)Image, their subclasses and fl_draw_image()
and similar functions.


git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@12028 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Albrecht Schlosser 2016-10-14 16:35:44 +00:00
parent 5c19bf07bf
commit de80a36218
7 changed files with 94 additions and 61 deletions

View File

@ -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

View File

@ -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_;}
/**

View File

@ -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());
}

View File

@ -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);

View File

@ -238,23 +238,38 @@ 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<br>
If D=1, each uchar in bits[] is a grayscale pixel value.<br>
If D=2, each uchar pair in bits[] is a grayscale + alpha pixel value.<br>
If D=3, each uchar triplet in bits[] is an R/G/B pixel value<br>
If D=4, each uchar quad in bits[] is an R/G/B/A pixel value.
\param[in] LD Line data size (default=0).<br>
Line data is extra data that is included after each line
of color image data and is normally not present.
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),
@ -271,9 +286,12 @@ 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.
*/
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),
@ -289,7 +307,7 @@ 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.
*/
*/
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));
}
}
}

View File

@ -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;
}

View File

@ -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;