New Fl_ICO_Image class to read Windows .ico icon files
Many thanks to @darealshinji for contributing all the code for this new FLTK image class (see branch Fl_ICO_Image of https://github.com/darealshinji/fltk).
This commit is contained in:
parent
0bb30d8f92
commit
36cd0a397c
@ -45,6 +45,7 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2022
|
||||
and Fl_Image::data_h() give the width and height of the image data.
|
||||
- New Fl_SVG_Image class: gives support of scalable vector graphics images
|
||||
to FLTK using the nanosvg software.
|
||||
- New Fl_ICO_Image class to read Windows .ico icon files.
|
||||
- New classes Fl_SVG_File_Surface and Fl_EPS_File_Surface to save any FLTK
|
||||
graphics to SVG or EPS files, respectively.
|
||||
- Windows platform: added support for using a manifest to set the
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// BMP image header file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2021 by Bill Spitzak and others.
|
||||
// Copyright 1998-2022 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
|
||||
@ -34,7 +34,7 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
void load_bmp_(class Fl_Image_Reader &rdr);
|
||||
void load_bmp_(class Fl_Image_Reader &rdr, int ico_height = 0, int ico_width = 0);
|
||||
|
||||
};
|
||||
|
||||
|
55
FL/Fl_ICO_Image.H
Normal file
55
FL/Fl_ICO_Image.H
Normal file
@ -0,0 +1,55 @@
|
||||
//
|
||||
// ICO image header file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2022 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
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
// https://en.wikipedia.org/wiki/ICO_(file_format)
|
||||
// http://www.daubnet.com/en/file-format-ico
|
||||
|
||||
#ifndef Fl_ICO_Image_H
|
||||
# define Fl_ICO_Image_H
|
||||
# include "Fl_BMP_Image.H"
|
||||
|
||||
/**
|
||||
The Fl_ICO_Image class supports loading, caching, and drawing of Windows icon (.ico) files.
|
||||
*/
|
||||
class FL_EXPORT Fl_ICO_Image : public Fl_BMP_Image {
|
||||
|
||||
public:
|
||||
/** Windows ICONDIRENTRY structure */
|
||||
struct IconDirEntry {
|
||||
int bWidth; ///< Image width
|
||||
int bHeight; ///< Image height
|
||||
int bColorCount; ///< Number of colors (0 if ≥ 8bpp)
|
||||
int bReserved; ///< Reserved
|
||||
int wPlanes; ///< Color Planes
|
||||
int wBitCount; ///< Bits per pixel
|
||||
int dwBytesInRes; ///< Resource size in bytes
|
||||
int dwImageOffset; ///< Offset to the image
|
||||
};
|
||||
|
||||
Fl_ICO_Image(const char *filename, int id = -1, const unsigned char *data = NULL, const size_t datasize = 0);
|
||||
~Fl_ICO_Image();
|
||||
/** Gives the number of icons of various resolutions present in the ICO object */
|
||||
int idcount() { return idcount_; }
|
||||
/** Returns the array of idcount() loaded IconDirEntry structures */
|
||||
IconDirEntry * const icondirentry() const { return icondirentry_; }
|
||||
|
||||
private:
|
||||
int idcount_;
|
||||
struct IconDirEntry *icondirentry_;
|
||||
void load_ico_(class Fl_Image_Reader &rdr, int id);
|
||||
};
|
||||
|
||||
#endif // Fl_ICO_Image_H
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// PNG image header file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2021 by Bill Spitzak and others.
|
||||
// Copyright 1998-2022 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
|
||||
@ -28,13 +28,14 @@
|
||||
and alpha-based transparency.
|
||||
*/
|
||||
class FL_EXPORT Fl_PNG_Image : public Fl_RGB_Image {
|
||||
|
||||
friend class Fl_ICO_Image;
|
||||
public:
|
||||
|
||||
Fl_PNG_Image(const char* filename);
|
||||
Fl_PNG_Image (const char *name_png, const unsigned char *buffer, int datasize);
|
||||
private:
|
||||
void load_png_(const char *name_png, const unsigned char *buffer_png, int datasize);
|
||||
Fl_PNG_Image(const char *filename, int offset); // used by Fl_ICO_Image
|
||||
void load_png_(const char *name_png, int offset, const unsigned char *buffer_png, int datasize);
|
||||
};
|
||||
|
||||
// Support functions to write PNG image files (since 1.4.0)
|
||||
|
@ -465,6 +465,7 @@ set (IMGCPPFILES
|
||||
Fl_File_Icon2.cxx
|
||||
Fl_GIF_Image.cxx
|
||||
Fl_Help_Dialog.cxx
|
||||
Fl_ICO_Image.cxx
|
||||
Fl_JPEG_Image.cxx
|
||||
Fl_PNG_Image.cxx
|
||||
Fl_PNM_Image.cxx
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Fl_BMP_Image class for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2011-2021 by Bill Spitzak and others.
|
||||
// Copyright 2011-2022 by Bill Spitzak and others.
|
||||
// Copyright 1997-2010 by Easy Software Products.
|
||||
// Image support by Matthias Melcher, Copyright 2000-2009.
|
||||
//
|
||||
@ -129,7 +129,7 @@ Fl_BMP_Image::Fl_BMP_Image(const char *imagename, const unsigned char *data, con
|
||||
format supports only 1 bit for alpha. To avoid code duplication, we use
|
||||
an Fl_Image_Reader that reads data from either a file or from memory.
|
||||
*/
|
||||
void Fl_BMP_Image::load_bmp_(Fl_Image_Reader &rdr)
|
||||
void Fl_BMP_Image::load_bmp_(Fl_Image_Reader &rdr, int ico_height, int ico_width)
|
||||
{
|
||||
int info_size, // Size of info header
|
||||
width, // Width of image (pixels)
|
||||
@ -147,7 +147,7 @@ void Fl_BMP_Image::load_bmp_(Fl_Image_Reader &rdr)
|
||||
row_order, // 1 = normal; -1 = flipped row order
|
||||
start_y, // Beginning Y
|
||||
end_y; // Ending Y
|
||||
long offbits; // Offset to image data
|
||||
long offbits = 0; // Offset to image data
|
||||
uchar bit, // Bit in image
|
||||
byte; // Byte in image
|
||||
uchar *ptr; // Pointer into pixels
|
||||
@ -163,17 +163,19 @@ void Fl_BMP_Image::load_bmp_(Fl_Image_Reader &rdr)
|
||||
w(0); h(0); d(0); ld(0); // make sure these are all zero
|
||||
|
||||
// Get the header...
|
||||
byte = rdr.read_byte(); // Check "BM" sync chars
|
||||
bit = rdr.read_byte();
|
||||
if (byte != 'B' || bit != 'M') {
|
||||
ld(ERR_FORMAT);
|
||||
return;
|
||||
}
|
||||
if (ico_height < 1) {
|
||||
byte = rdr.read_byte(); // Check "BM" sync chars
|
||||
bit = rdr.read_byte();
|
||||
if (byte != 'B' || bit != 'M') {
|
||||
ld(ERR_FORMAT);
|
||||
return;
|
||||
}
|
||||
|
||||
rdr.read_dword(); // Skip size
|
||||
rdr.read_word(); // Skip reserved stuff
|
||||
rdr.read_word();
|
||||
offbits = (long)rdr.read_dword();// Read offset to image data
|
||||
rdr.read_dword(); // Skip size
|
||||
rdr.read_word(); // Skip reserved stuff
|
||||
rdr.read_word();
|
||||
offbits = (long)rdr.read_dword();// Read offset to image data
|
||||
}
|
||||
|
||||
// Then the bitmap information...
|
||||
info_size = rdr.read_dword();
|
||||
@ -196,12 +198,20 @@ void Fl_BMP_Image::load_bmp_(Fl_Image_Reader &rdr)
|
||||
|
||||
repcount = info_size - 12;
|
||||
} else {
|
||||
// New BMP header...
|
||||
width = rdr.read_long();
|
||||
// If the height is negative, the row order is flipped
|
||||
temp = rdr.read_long();
|
||||
if (temp < 0) row_order = 1;
|
||||
height = abs(temp);
|
||||
if (ico_height > 0 && ico_width > 0) {
|
||||
rdr.read_long();
|
||||
rdr.read_long();
|
||||
width = ico_width;
|
||||
height = ico_height;
|
||||
} else {
|
||||
// New BMP header...
|
||||
w(rdr.read_long());
|
||||
// If the height is negative, the row order is flipped
|
||||
temp = rdr.read_long();
|
||||
if (temp < 0) row_order = 1;
|
||||
height = abs(temp);
|
||||
}
|
||||
|
||||
rdr.read_word();
|
||||
depth = rdr.read_word();
|
||||
compression = rdr.read_dword();
|
||||
|
202
src/Fl_ICO_Image.cxx
Normal file
202
src/Fl_ICO_Image.cxx
Normal file
@ -0,0 +1,202 @@
|
||||
//
|
||||
// Fl_ICO_Image class for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2022 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
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// https://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Include necessary header files...
|
||||
//
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include "config.h"
|
||||
#include "Fl_Image_Reader.h"
|
||||
#include <FL/Fl_ICO_Image.H>
|
||||
#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
|
||||
# include <FL/Fl_PNG_Image.H>
|
||||
#endif
|
||||
|
||||
/**
|
||||
Loads the named icon image from the given .ico filename or from memory
|
||||
\param filename Name of a .ico file, or of the in-memory image
|
||||
\param id When id is -1 (default), the highest-resolution icon is loaded;
|
||||
when id ≥ 0, load the icon with this ID;
|
||||
when id = -2, load all IconDirEntry structures but no image.
|
||||
\param data NULL, or in-memory icon data
|
||||
\param datasize Size in bytes of the \p data byte array (used when \p data is not NULL)
|
||||
*/
|
||||
Fl_ICO_Image::Fl_ICO_Image(const char *filename, int id, const unsigned char *data, const size_t datasize)
|
||||
: Fl_BMP_Image(0,0),
|
||||
idcount_(0),
|
||||
icondirentry_(0)
|
||||
{
|
||||
Fl_Image_Reader rdr;
|
||||
int r;
|
||||
|
||||
w(0); h(0); d(0); ld(0);
|
||||
alloc_array = 0;
|
||||
array = 0;
|
||||
|
||||
if (data) {
|
||||
r = rdr.open(filename, data, datasize);
|
||||
} else {
|
||||
r = rdr.open(filename);
|
||||
}
|
||||
|
||||
if (r == -1) {
|
||||
ld(ERR_FILE_ACCESS);
|
||||
} else {
|
||||
load_ico_(rdr, id);
|
||||
}
|
||||
}
|
||||
|
||||
/** Destructor */
|
||||
Fl_ICO_Image::~Fl_ICO_Image() {
|
||||
delete[] icondirentry_;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This method attempts to load the biggest image resource available
|
||||
inside a .ICO file (Windows Icon format).
|
||||
*/
|
||||
void Fl_ICO_Image::load_ico_(Fl_Image_Reader &rdr, int id)
|
||||
{
|
||||
int pickedID = -1;
|
||||
|
||||
// Check file header (ICONDIR, 6 bytes)
|
||||
|
||||
if (rdr.read_word() != 0 || rdr.read_word() != 1) {
|
||||
Fl::error("Fl_ICO_Image: %s is not an ICO file.\n", rdr.name());
|
||||
ld(ERR_FORMAT);
|
||||
return;
|
||||
}
|
||||
|
||||
idcount_ = rdr.read_word();
|
||||
|
||||
if (idcount() == 0) {
|
||||
Fl::error("Fl_ICO_Image: %s - no image resources found\n", rdr.name());
|
||||
ld(ERR_FORMAT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// read entries (IconDirEntry, 16 bytes each)
|
||||
|
||||
icondirentry_ = new IconDirEntry[idcount()];
|
||||
|
||||
for (int i = 0; i < idcount(); ++i) {
|
||||
icondirentry_[i].bWidth = (int)rdr.read_byte();
|
||||
icondirentry_[i].bHeight = (int)rdr.read_byte();
|
||||
icondirentry_[i].bColorCount = (int)rdr.read_byte();
|
||||
icondirentry_[i].bReserved = (int)rdr.read_byte();
|
||||
icondirentry_[i].wPlanes = (int)rdr.read_word();
|
||||
icondirentry_[i].wBitCount = (int)rdr.read_word();
|
||||
icondirentry_[i].dwBytesInRes = (int)rdr.read_dword();
|
||||
icondirentry_[i].dwImageOffset = (int)rdr.read_dword();
|
||||
|
||||
if (icondirentry_[i].bWidth == 0) icondirentry_[i].bWidth = 256;
|
||||
if (icondirentry_[i].bHeight == 0) icondirentry_[i].bHeight = 256;
|
||||
}
|
||||
|
||||
if (id <= -2) return;
|
||||
|
||||
if (!icondirentry_ || idcount() < 1 || id >= idcount()) {
|
||||
ld(ERR_FORMAT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == -1) {
|
||||
// pick icon with highest resolution + highest bitcount
|
||||
int highestRes = 0, bitcount = 0;
|
||||
for (int i = 0; i < idcount(); ++i) {
|
||||
int res = icondirentry_[i].bWidth * icondirentry_[i].bHeight;
|
||||
if (res > highestRes || (res == highestRes && icondirentry_[i].wBitCount > bitcount)) {
|
||||
highestRes = res;
|
||||
bitcount = icondirentry_[i].wBitCount;
|
||||
pickedID = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pickedID = id;
|
||||
}
|
||||
|
||||
if (pickedID < 0 ||
|
||||
icondirentry_[pickedID].bWidth <= 0 ||
|
||||
icondirentry_[pickedID].bHeight <= 0 ||
|
||||
icondirentry_[pickedID].dwImageOffset <= 0||
|
||||
icondirentry_[pickedID].dwBytesInRes <= 0)
|
||||
{
|
||||
ld(ERR_FORMAT);
|
||||
return;
|
||||
}
|
||||
|
||||
rdr.seek(icondirentry_[pickedID].dwImageOffset);
|
||||
|
||||
|
||||
// Check for a PNG image resource
|
||||
uchar b[8];
|
||||
for (int i=0; i<8; ++i) b[i] = rdr.read_byte();
|
||||
|
||||
if (b[0]==0x89 && b[1]=='P' && b[2]=='N' && b[3]=='G' &&
|
||||
b[4]=='\r' && b[5]=='\n' && b[6]==0x1A && b[7]=='\n')
|
||||
{
|
||||
#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
|
||||
Fl_PNG_Image *png = new Fl_PNG_Image(rdr.name(), icondirentry_[pickedID].dwImageOffset);
|
||||
|
||||
int loaded = png ? png->fail() : ERR_FILE_ACCESS;
|
||||
if (loaded < 0) {
|
||||
w(0); h(0); d(0);
|
||||
ld(loaded);
|
||||
if (png) delete png;
|
||||
return;
|
||||
}
|
||||
|
||||
w(png->w());
|
||||
h(png->h());
|
||||
d(png->d());
|
||||
|
||||
// take over pointer of Fl_PNG_Image's array
|
||||
array = png->array;
|
||||
alloc_array = 1;
|
||||
png->array = NULL;
|
||||
png->alloc_array = 0;
|
||||
|
||||
delete png;
|
||||
return;
|
||||
#else
|
||||
Fl::error("Fl_ICO_Image: %s - cannot decode PNG resource (no libpng support)!\n", rdr.name());
|
||||
w(0); h(0); d(0);
|
||||
ld(ERR_FORMAT);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Bitmap resource
|
||||
|
||||
w(icondirentry_[pickedID].bWidth);
|
||||
h(icondirentry_[pickedID].bHeight);
|
||||
d(4);
|
||||
|
||||
if (((size_t)w()) * h() * d() > max_size()) {
|
||||
Fl::warning("ICO file \"%s\" is too large!\n", rdr.name());
|
||||
w(0); h(0); d(0);
|
||||
ld(ERR_FORMAT);
|
||||
return;
|
||||
}
|
||||
|
||||
rdr.seek(icondirentry_[pickedID].dwImageOffset);
|
||||
load_bmp_(rdr, h(), w());
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
// Copyright 1997-2012 by Easy Software Products.
|
||||
// Image support by Matthias Melcher, Copyright 2000-2009.
|
||||
//
|
||||
// Copyright 2013-2021 by Bill Spitzak and others.
|
||||
// Copyright 2013-2022 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
|
||||
@ -87,9 +87,15 @@ extern "C" {
|
||||
*/
|
||||
Fl_PNG_Image::Fl_PNG_Image (const char *filename): Fl_RGB_Image(0,0,0)
|
||||
{
|
||||
load_png_(filename, NULL, 0);
|
||||
load_png_(filename, 0, NULL, 0);
|
||||
}
|
||||
|
||||
// private c'tor used by Fl_ICO_Image
|
||||
// \param offset Offset to seek for the begin of PNG data inside a .ICO file
|
||||
Fl_PNG_Image::Fl_PNG_Image (const char *filename, int offset): Fl_RGB_Image(0,0,0)
|
||||
{
|
||||
load_png_(filename, offset, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Constructor that reads a PNG image from memory.
|
||||
@ -106,11 +112,11 @@ Fl_PNG_Image::Fl_PNG_Image (const char *filename): Fl_RGB_Image(0,0,0)
|
||||
Fl_PNG_Image::Fl_PNG_Image (
|
||||
const char *name_png, const unsigned char *buffer, int maxsize): Fl_RGB_Image(0,0,0)
|
||||
{
|
||||
load_png_(name_png, buffer, maxsize);
|
||||
load_png_(name_png, 0, buffer, maxsize);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_png, int maxsize)
|
||||
void Fl_PNG_Image::load_png_(const char *name_png, int offset, const unsigned char *buffer_png, int maxsize)
|
||||
{
|
||||
#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
|
||||
int i; // Looping var
|
||||
@ -134,6 +140,12 @@ void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_p
|
||||
delete fp;
|
||||
return;
|
||||
}
|
||||
if (offset > 0 && fseek(*fp, (long)offset, SEEK_SET) == -1) {
|
||||
fclose(*fp);
|
||||
ld(ERR_FORMAT);
|
||||
delete fp;
|
||||
return;
|
||||
}
|
||||
}
|
||||
const char *display_name = (name_png ? name_png : "In-memory PNG data");
|
||||
|
||||
|
@ -228,6 +228,7 @@ IMGCPPFILES = \
|
||||
Fl_File_Icon2.cxx \
|
||||
Fl_GIF_Image.cxx \
|
||||
Fl_Help_Dialog.cxx \
|
||||
Fl_ICO_Image.cxx \
|
||||
Fl_JPEG_Image.cxx \
|
||||
Fl_PNG_Image.cxx \
|
||||
Fl_PNM_Image.cxx \
|
||||
|
@ -2,7 +2,7 @@
|
||||
// FLTK images library core.
|
||||
//
|
||||
// Copyright 1997-2010 by Easy Software Products.
|
||||
// Copyright 2011-2021 by Bill Spitzak and others.
|
||||
// Copyright 2011-2022 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
|
||||
@ -31,6 +31,7 @@
|
||||
#include <FL/Fl_PNG_Image.H>
|
||||
#include <FL/Fl_PNM_Image.H>
|
||||
#include <FL/Fl_SVG_Image.H>
|
||||
#include <FL/Fl_ICO_Image.H>
|
||||
#include <FL/fl_utf8.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -95,6 +96,9 @@ fl_check_images(const char *name, // I - Filename
|
||||
if (memcmp(header, "BM", 2) == 0) // BMP file
|
||||
return new Fl_BMP_Image(name);
|
||||
|
||||
if (memcmp(header, "\0\0\1\0", 4) == 0 && header[5] == 0) // ICO file
|
||||
return new Fl_ICO_Image(name);
|
||||
|
||||
// PNM
|
||||
|
||||
if (header[0] == 'P' && header[1] >= '1' && header[1] <= '7')
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// A shared image test program for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2015 by Bill Spitzak and others.
|
||||
// Copyright 1998-2022 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
|
||||
@ -77,7 +77,7 @@ void file_cb(const char *n) {
|
||||
|
||||
void button_cb(Fl_Widget *,void *) {
|
||||
fl_file_chooser_callback(file_cb);
|
||||
const char *fname = fl_file_chooser("Image file?","*.{bm,bmp,gif,jpg,pbm,pgm,png,ppm,xbm,xpm"
|
||||
const char *fname = fl_file_chooser("Image file?","*.{bm,bmp,gif,ico,jpg,pbm,pgm,png,ppm,xbm,xpm"
|
||||
#ifdef FLTK_USE_SVG
|
||||
",svg"
|
||||
#ifdef HAVE_LIBZ
|
||||
|
Loading…
Reference in New Issue
Block a user