STR #2873: new function Fl_Image::fail() that returns 0, ERR_NO_IMAGE, ERR_FORMAT, or ERR_FILE_ACCESS to make life easier when loading images.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10732 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher
2015-05-23 23:42:26 +00:00
parent 03f69c0dd5
commit 0539009c67
10 changed files with 235 additions and 123 deletions
+3 -3
View File
@@ -24,9 +24,9 @@
# include "Fl_Image.H"
/**
The Fl_BMP_Image class supports loading, caching,
and drawing of Windows Bitmap (BMP) image files.
*/
The Fl_BMP_Image class supports loading, caching,
and drawing of Windows Bitmap (BMP) image files.
*/
class FL_EXPORT Fl_BMP_Image : public Fl_RGB_Image {
public:
+4 -4
View File
@@ -24,10 +24,10 @@
# include "Fl_Pixmap.H"
/**
The Fl_GIF_Image class supports loading, caching,
and drawing of Compuserve GIF<SUP>SM</SUP> images. The class
loads the first image and supports transparency.
*/
The Fl_GIF_Image class supports loading, caching,
and drawing of Compuserve GIF<SUP>SM</SUP> images. The class
loads the first image and supports transparency.
*/
class FL_EXPORT Fl_GIF_Image : public Fl_Pixmap {
public:
+80 -82
View File
@@ -30,26 +30,36 @@ class Fl_Pixmap;
struct Fl_Menu_Item;
struct Fl_Label;
/** \enum Fl_RGB_Scaling
The scaling algorithm to use for RGB images.
The scaling algorithm to use for RGB images.
*/
enum Fl_RGB_Scaling {
FL_RGB_SCALING_NEAREST = 0, ///< default RGB image scaling algorithm
FL_RGB_SCALING_BILINEAR ///< more accurate, but slower RGB image scaling algorithm
FL_RGB_SCALING_NEAREST = 0, ///< default RGB image scaling algorithm
FL_RGB_SCALING_BILINEAR ///< more accurate, but slower RGB image scaling algorithm
};
/**
Fl_Image is the base class used for caching and
drawing all kinds of images in FLTK. This class keeps track of
common image data such as the pixels, colormap, width, height,
and depth. Virtual methods are used to provide type-specific
image handling.
\brief Base class for image caching and drawing.
Fl_Image is the base class used for caching and drawing all kinds of images
in FLTK. This class keeps track of common image data such as the pixels,
colormap, width, height, and depth. Virtual methods are used to provide
type-specific image handling.
Since the Fl_Image class does not support image
drawing by itself, calling the draw() method results in
a box with an X in it being drawn instead.
Since the Fl_Image class does not support image
drawing by itself, calling the draw() method results in
a box with an X in it being drawn instead.
*/
class FL_EXPORT Fl_Image {
public:
const int ERR_NO_IMAGE = -1;
const int ERR_FILE_ACCESS = -2;
const int ERR_FORMAT = -3;
private:
int w_, h_, d_, ld_, count_;
const char * const *data_;
static Fl_RGB_Scaling RGB_scaling_;
@@ -58,19 +68,19 @@ class FL_EXPORT Fl_Image {
Fl_Image & operator=(const Fl_Image &);
Fl_Image(const Fl_Image &);
protected:
protected:
/**
Sets the current image width in pixels.
*/
Sets the current image width in pixels.
*/
void w(int W) {w_ = W;}
/**
Sets the current image height in pixels.
*/
Sets the current image height in pixels.
*/
void h(int H) {h_ = H;}
/**
Sets the current image depth.
*/
Sets the current image depth.
*/
void d(int D) {d_ = D;}
/**
Sets the current line data size in bytes.
@@ -85,85 +95,88 @@ class FL_EXPORT Fl_Image {
static void labeltype(const Fl_Label *lo, int lx, int ly, int lw, int lh, Fl_Align la);
static void measure(const Fl_Label *lo, int &lw, int &lh);
public:
public:
/**
Returns the current image width in pixels.
*/
*/
int w() const {return w_;}
/** Returns the current image height in pixels.
/**
Returns the current image height in pixels.
*/
int h() const {return h_;}
/**
Returns the current image depth.
Returns the current image depth.
The return value will be 0 for bitmaps, 1 for
pixmaps, and 1 to 4 for color images.</P>
*/
pixmaps, and 1 to 4 for color images.</P>
*/
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.
*/
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.
*/
int ld() const {return ld_;}
/**
The count() method returns the number of data values
associated with the image. The value will be 0 for images with
no associated data, 1 for bitmap and color images, and greater
than 2 for pixmap images.
*/
The count() method returns the number of data values
associated with the image. The value will be 0 for images with
no associated data, 1 for bitmap and color images, and greater
than 2 for pixmap images.
*/
int count() const {return count_;}
/**
Returns a pointer to the current image data array.
Use the count() method to find the size of the data array.
*/
Returns a pointer to the current image data array.
Use the count() method to find the size of the data array.
*/
const char * const *data() const {return data_;}
/**
The constructor creates an empty image with the specified
width, height, and depth. The width and height are in pixels.
The depth is 0 for bitmaps, 1 for pixmap (colormap) images, and
1 to 4 for color images.
*/
Fl_Image(int W, int H, int D) {w_ = W; h_ = H; d_ = D; ld_ = 0; count_ = 0; data_ = 0;}
Returns a value that is not 0 if there is currently no image
available.
\return ERR_NO_IMAGE if no image was found
\return ERR_FILE_ACCESS if there was a file access related error (errno should be set)
\return ERR_FORMAT if image decoding failed.
*/
int fail();
Fl_Image(int W, int H, int D);
virtual ~Fl_Image();
virtual Fl_Image *copy(int W, int H);
/**
The copy() method creates a copy of the specified
image. If the width and height are provided, the image is
resized to the specified size. The image should be deleted (or in
the case of Fl_Shared_Image, released) when you are done
with it.
*/
The copy() method creates a copy of the specified
image. If the width and height are provided, the image is
resized to the specified size. The image should be deleted (or in
the case of Fl_Shared_Image, released) when you are done
with it.
*/
Fl_Image *copy() { return copy(w(), h()); }
virtual void color_average(Fl_Color c, float i);
/**
The inactive() method calls
color_average(FL_BACKGROUND_COLOR, 0.33f) to produce
an image that appears grayed out.
The inactive() method calls
color_average(FL_BACKGROUND_COLOR, 0.33f) to produce
an image that appears grayed out.
An internal copy is made of the original image before
changes are applied, to avoid modifying the original image.
*/
An internal copy is made of the original image before
changes are applied, to avoid modifying the original image.
*/
void inactive() { color_average(FL_GRAY, .33f); }
virtual void desaturate();
virtual void label(Fl_Widget*w);
virtual void label(Fl_Menu_Item*m);
/**
Draws the image with a bounding box.
Arguments <tt>X,Y,W,H</tt> specify
a bounding box for the image, with the origin
(upper-left corner) of the image offset by the \c cx
and \c cy arguments.\n
Draws the image with a bounding box.
Arguments <tt>X,Y,W,H</tt> specify
a bounding box for the image, with the origin
(upper-left corner) of the image offset by the \c cx
and \c cy arguments.
In other words: <tt>fl_push_clip(X,Y,W,H)</tt> is applied,
the image is drawn with its upper-left corner at <tt>X-cx,Y-cy</tt> and its own width and height,
<tt>fl_pop_clip</tt><tt>()</tt> is applied.
*/
*/
virtual void draw(int X, int Y, int W, int H, int cx=0, int cy=0); // platform dependent
/**
Draws the image.
This form specifies the upper-lefthand corner of the image.
*/
Draws the image.
This form specifies the upper-lefthand corner of the image.
*/
void draw(int X, int Y) {draw(X, Y, w(), h(), 0, 0);} // platform dependent
virtual void uncache();
@@ -174,6 +187,7 @@ class FL_EXPORT Fl_Image {
static Fl_RGB_Scaling RGB_scaling();
};
/**
The Fl_RGB_Image class supports caching and drawing
of full-color images with 1 to 4 channels of color information.
@@ -206,25 +220,9 @@ public:
unsigned mask_; // for internal use (mask bitmap)
#endif // __APPLE__ || WIN32
public:
public:
/**
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.
\see Fl_Image::data(), Fl_Image::w(), Fl_Image::h(), Fl_Image::d(), Fl_Image::ld()
*/
Fl_RGB_Image(const uchar *bits, int W, int H, int D=3, int LD=0) :
Fl_Image(W,H,D), array(bits), alloc_array(0), id_(0), mask_(0) {data((const char **)&array, 1); ld(LD);}
Fl_RGB_Image(const uchar *bits, int W, int H, int D=3, int LD=0);
Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg=FL_GRAY);
virtual ~Fl_RGB_Image();
virtual Fl_Image *copy(int W, int H);
+5 -5
View File
@@ -24,11 +24,11 @@
# include "Fl_Image.H"
/**
The Fl_JPEG_Image class supports loading, caching,
and drawing of Joint Photographic Experts Group (JPEG) File
Interchange Format (JFIF) images. The class supports grayscale
and color (RGB) JPEG image files.
*/
The Fl_JPEG_Image class supports loading, caching,
and drawing of Joint Photographic Experts Group (JPEG) File
Interchange Format (JFIF) images. The class supports grayscale
and color (RGB) JPEG image files.
*/
class FL_EXPORT Fl_JPEG_Image : public Fl_RGB_Image {
public:
+19 -7
View File
@@ -52,13 +52,19 @@
static int read_long(FILE *fp);
static unsigned short read_word(FILE *fp);
static unsigned int read_dword(FILE *fp);
/**
The constructor loads the named BMP image from the given bmp filename.
<P>The inherited destructor free all memory and server resources that are used by
the image.
<P>The destructor free all memory and server resources that are used by
the image
*/
The constructor loads the named BMP image from the given bmp filename.
The inherited destructor frees all memory and server resources that are
used by the image.
Use Fl_Image::fail() to check if Fl_BMP_Image failed to load. fail() returns
ERR_FILE_ACCESS if the file could not bo opened or read, ERR_FORMAT if the
BMP format could not be decoded, and ERR_NO_IMAGE if the image could not
be loaded for another reason.
*/
Fl_BMP_Image::Fl_BMP_Image(const char *bmp) // I - File to read
: Fl_RGB_Image(0,0,0) {
FILE *fp; // File pointer
@@ -86,13 +92,17 @@ Fl_BMP_Image::Fl_BMP_Image(const char *bmp) // I - File to read
// Open the file...
if ((fp = fl_fopen(bmp, "rb")) == NULL) return;
if ((fp = fl_fopen(bmp, "rb")) == NULL) {
ld(ERR_FILE_ACCESS);
return;
}
// Get the header...
byte = (uchar)getc(fp); // Check "BM" sync chars
bit = (uchar)getc(fp);
if (byte != 'B' || bit != 'M') {
fclose(fp);
ld(ERR_FORMAT);
return;
}
@@ -161,6 +171,7 @@ Fl_BMP_Image::Fl_BMP_Image(const char *bmp) // I - File to read
// Check header data...
if (!w() || !h() || !depth) {
fclose(fp);
w(0); h(0); d(0); ld(ERR_FORMAT);
return;
}
@@ -191,6 +202,7 @@ Fl_BMP_Image::Fl_BMP_Image(const char *bmp) // I - File to read
if (((size_t)w()) * h() * d() > max_size() ) {
Fl::warning("BMP file \"%s\" is too large!\n", bmp);
fclose(fp);
w(0); h(0); d(0); ld(ERR_FORMAT);
return;
}
array = new uchar[w() * h() * d()];
+14 -4
View File
@@ -71,27 +71,36 @@ typedef unsigned char uchar;
#define GETSHORT(var) var = NEXTBYTE; var += NEXTBYTE << 8
/**
The constructor loads the named GIF image.
<P>The inherited destructor free all memory and server resources that are used by
the image.
*/
The constructor loads the named GIF image.
The inherited destructor free all memory and server resources that are used
by the image.
Use Fl_Image::fail() to check if Fl_BMP_Image failed to load. fail() returns
ERR_FILE_ACCESS if the file could not bo opened or read, ERR_FORMAT if the
GIF format could not be decoded, and ERR_NO_IMAGE if the image could not
be loaded for another reason.
*/
Fl_GIF_Image::Fl_GIF_Image(const char *infname) : Fl_Pixmap((char *const*)0) {
FILE *GifFile; // File to read
char **new_data; // Data array
if ((GifFile = fl_fopen(infname, "rb")) == NULL) {
Fl::error("Fl_GIF_Image: Unable to open %s!", infname);
ld(ERR_FILE_ACCESS);
return;
}
{char b[6];
if (fread(b,1,6,GifFile)<6) {
fclose(GifFile);
ld(ERR_FILE_ACCESS);
return; /* quit on eof */
}
if (b[0]!='G' || b[1]!='I' || b[2] != 'F') {
fclose(GifFile);
Fl::error("Fl_GIF_Image: %s is not a GIF file.\n", infname);
ld(ERR_FORMAT);
return;
}
if (b[3]!='8' || b[4]>'9' || b[5]!= 'a')
@@ -135,6 +144,7 @@ Fl_GIF_Image::Fl_GIF_Image(const char *infname) : Fl_Pixmap((char *const*)0) {
if (i<0) {
fclose(GifFile);
Fl::error("Fl_GIF_Image: %s - unexpected EOF",infname);
w(0); h(0); d(0); ld(ERR_FORMAT);
return;
}
int blocklen;
+66 -5
View File
@@ -37,6 +37,17 @@ void fl_restore_clip(); // from fl_rect.cxx
Fl_RGB_Scaling Fl_Image::RGB_scaling_ = FL_RGB_SCALING_NEAREST;
/**
The constructor creates an empty image with the specified
width, height, and depth. The width and height are in pixels.
The depth is 0 for bitmaps, 1 for pixmap (colormap) images, and
1 to 4 for color images.
*/
Fl_Image::Fl_Image(int W, int H, int D) :
w_(W), h_(H), d_(D), ld_(0), count_(0), data_(0L)
{}
/**
The destructor is a virtual method that frees all memory used
by the image.
@@ -129,6 +140,18 @@ void Fl_Image::label(Fl_Menu_Item* m) {
m->label(_FL_IMAGE_LABEL, (const char*)this);
}
int Fl_Image::fail()
{
// if no image exists, ld_ may contain a simple error code
if ( (w_<=0) || (h_<=0) || (d_<=0) ) {
if (ld_==0)
return ERR_NO_IMAGE;
else
return ld_;
}
return 0;
}
void
Fl_Image::labeltype(const Fl_Label *lo, // I - Label
int lx, // I - X position
@@ -186,12 +209,44 @@ size_t Fl_RGB_Image::max_size_ = ~((size_t)0);
int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg);
/** The constructor creates a new RGBA image from the specified Fl_Pixmap.
/**
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.
\see Fl_Image::data(), Fl_Image::w(), Fl_Image::h(), Fl_Image::d(), Fl_Image::ld()
*/
Fl_RGB_Image::Fl_RGB_Image(const uchar *bits, int W, int H, int D, int LD) :
Fl_Image(W,H,D),
array(bits),
alloc_array(0),
id_(0),
mask_(0)
{
data((const char **)&array, 1);
ld(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 \par bg color with full transparency */
of the pixmap that is assigned the \par bg color with full transparency
*/
Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg):
Fl_Image(pxm->w(), pxm->h(), 4), id_(0), mask_(0)
Fl_Image(pxm->w(), pxm->h(), 4),
id_(0),
mask_(0)
{
array = new uchar[w() * h() * d()];
alloc_array = 1;
@@ -199,7 +254,11 @@ Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg):
data((const char **)&array, 1);
}
/** 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_);
@@ -258,7 +317,9 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) {
new_image->alloc_array = 1;
return new_image;
} else return new Fl_RGB_Image(array, w(), h(), d(), ld());
} else {
return new Fl_RGB_Image(array, w(), h(), d(), ld());
}
}
if (W <= 0 || H <= 0) return 0;
+9 -2
View File
@@ -111,7 +111,10 @@ Fl_JPEG_Image::Fl_JPEG_Image(const char *filename) // I - File to load
array = (uchar *)0;
// Open the image file...
if ((fp = fl_fopen(filename, "rb")) == NULL) return;
if ((fp = fl_fopen(filename, "rb")) == NULL) {
ld(ERR_FILE_ACCESS);
return;
}
// Setup the decompressor info and read the header...
dinfo.err = jpeg_std_error((jpeg_error_mgr *)&jerr);
@@ -150,6 +153,7 @@ Fl_JPEG_Image::Fl_JPEG_Image(const char *filename) // I - File to load
free(max_destroy_decompress_err);
free(max_finish_decompress_err);
ld(ERR_FORMAT);
return;
}
@@ -275,7 +279,10 @@ static void jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *data)
The inherited destructor frees all memory and server resources that are used
by the image.
There is no error function in this class. If the image has loaded correctly,
Use Fl_Image::fail() to check if Fl_BMP_Image failed to load. fail() returns
ERR_FILE_ACCESS if the file could not bo opened or read, ERR_FORMAT if the
JPEG format could not be decoded, and ERR_NO_IMAGE if the image could not
be loaded for another reason. If the image has loaded correctly,
w(), h(), and d() should return values greater zero.
\param name A unique name or NULL
+18 -6
View File
@@ -71,18 +71,24 @@ extern "C" {
/**
The constructor loads the named PNG image from the given png filename.
The constructor loads the named PNG image from the given png filename.
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.
\param[in] filename Name of PNG file to read
*/
Use Fl_Image::fail() to check if Fl_BMP_Image failed to load. fail() returns
ERR_FILE_ACCESS if the file could not bo opened or read, ERR_FORMAT if the
PNG format could not be decoded, and ERR_NO_IMAGE if the image could not
be loaded for another reason.
\param[in] filename Name of PNG file to read
*/
Fl_PNG_Image::Fl_PNG_Image (const char *filename): Fl_RGB_Image(0,0,0)
{
load_png_(filename, NULL, 0);
}
/**
\brief Constructor that reads a PNG image from memory.
@@ -101,6 +107,7 @@ Fl_PNG_Image::Fl_PNG_Image (
load_png_(name_png, buffer, maxsize);
}
void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_png, int maxsize)
{
#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
@@ -114,7 +121,10 @@ void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_p
int from_memory = (buffer_png != NULL); // true if reading image from memory
if (!from_memory) {
if ((fp = fl_fopen(name_png, "rb")) == NULL) return;
if ((fp = fl_fopen(name_png, "rb")) == NULL) {
ld(ERR_FILE_ACCESS);
return;
}
}
const char *display_name = (name_png ? name_png : "In-memory PNG data");
@@ -125,6 +135,7 @@ void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_p
if (pp) png_destroy_read_struct(&pp, NULL, NULL);
if (!from_memory) fclose(fp);
Fl::warning("Cannot allocate memory to read PNG file or data \"%s\".\n", display_name);
w(0); h(0); d(0); ld(ERR_FORMAT);
return;
}
@@ -133,6 +144,7 @@ void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_p
png_destroy_read_struct(&pp, &info, NULL);
if (!from_memory) fclose(fp);
Fl::warning("PNG file or data \"%s\" is too large or contains errors!\n", display_name);
w(0); h(0); d(0); ld(ERR_FORMAT);
return;
}
+17 -5
View File
@@ -37,11 +37,18 @@
// 'Fl_PNM_Image::Fl_PNM_Image()' - Load a PNM image...
//
/**
The constructor loads the named PNM image.
<P>The inherited destructor free all memory and server resources that are used by the image.
*/
/**
The constructor loads the named PNM image.
The inherited destructor free all memory and server resources that are used by
the image.
Use Fl_Image::fail() to check if Fl_BMP_Image failed to load. fail() returns
ERR_FILE_ACCESS if the file could not bo opened or read, ERR_FORMAT if the
PNM format could not be decoded, and ERR_NO_IMAGE if the image could not
be loaded for another reason.
*/
Fl_PNM_Image::Fl_PNM_Image(const char *name) // I - File to read
: Fl_RGB_Image(0,0,0) {
FILE *fp; // File pointer
@@ -56,7 +63,10 @@ Fl_PNM_Image::Fl_PNM_Image(const char *name) // I - File to read
maxval; // Maximum pixel value
if ((fp = fl_fopen(name, "rb")) == NULL) return;
if ((fp = fl_fopen(name, "rb")) == NULL) {
ld(ERR_FILE_ACCESS);
return;
}
//
// Read the file header in the format:
@@ -75,6 +85,7 @@ Fl_PNM_Image::Fl_PNM_Image(const char *name) // I - File to read
if (!lineptr) {
fclose(fp);
Fl::error("Early end-of-file in PNM file \"%s\"!", name);
ld(ERR_FILE_ACCESS);
return;
}
@@ -122,6 +133,7 @@ Fl_PNM_Image::Fl_PNM_Image(const char *name) // I - File to read
if (((size_t)w()) * h() * d() > max_size() ) {
Fl::warning("PNM file \"%s\" is too large!\n", name);
fclose(fp);
w(0); h(0); d(0); ld(ERR_FORMAT);
return;
}
array = new uchar[w() * h() * d()];