Christophe Dumez
16 years ago
10 changed files with 677 additions and 252 deletions
@ -0,0 +1,470 @@ |
|||||||
|
/*
|
||||||
|
* kimgio import filter for MS Windows .ico files |
||||||
|
* |
||||||
|
* Distributed under the terms of the LGPL |
||||||
|
* Copyright (c) 2000 Malte Starostik <malte@kde.org> |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
// remove when QImage::jumpTable is ported
|
||||||
|
#define QT3_SUPPORT |
||||||
|
#define QT3_SUPPORT_WARNINGS |
||||||
|
#ifdef __GNUC__ |
||||||
|
#warning TODO: remove QT3_SUPPORT |
||||||
|
#endif |
||||||
|
|
||||||
|
#include "ico.h" |
||||||
|
|
||||||
|
#include <cstring> |
||||||
|
#include <cstdlib> |
||||||
|
#include <algorithm> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include <QtGui/QImage> |
||||||
|
#include <QtGui/QBitmap> |
||||||
|
#include <QtGui/QApplication> |
||||||
|
#include <QtCore/QVector> |
||||||
|
#include <QtGui/QDesktopWidget> |
||||||
|
|
||||||
|
namespace |
||||||
|
{ |
||||||
|
// Global header (see http://www.daubnet.com/formats/ICO.html)
|
||||||
|
struct IcoHeader |
||||||
|
{ |
||||||
|
enum Type { Icon = 1, Cursor }; |
||||||
|
quint16 reserved; |
||||||
|
quint16 type; |
||||||
|
quint16 count; |
||||||
|
}; |
||||||
|
|
||||||
|
inline QDataStream& operator >>( QDataStream& s, IcoHeader& h ) |
||||||
|
{ |
||||||
|
return s >> h.reserved >> h.type >> h.count; |
||||||
|
} |
||||||
|
|
||||||
|
// Based on qt_read_dib et al. from qimage.cpp
|
||||||
|
// (c) 1992-2002 Trolltech AS.
|
||||||
|
struct BMP_INFOHDR |
||||||
|
{ |
||||||
|
static const quint32 Size = 40; |
||||||
|
quint32 biSize; // size of this struct
|
||||||
|
quint32 biWidth; // pixmap width
|
||||||
|
quint32 biHeight; // pixmap height
|
||||||
|
quint16 biPlanes; // should be 1
|
||||||
|
quint16 biBitCount; // number of bits per pixel
|
||||||
|
enum Compression { RGB = 0 }; |
||||||
|
quint32 biCompression; // compression method
|
||||||
|
quint32 biSizeImage; // size of image
|
||||||
|
quint32 biXPelsPerMeter; // horizontal resolution
|
||||||
|
quint32 biYPelsPerMeter; // vertical resolution
|
||||||
|
quint32 biClrUsed; // number of colors used
|
||||||
|
quint32 biClrImportant; // number of important colors
|
||||||
|
}; |
||||||
|
const quint32 BMP_INFOHDR::Size; |
||||||
|
|
||||||
|
QDataStream& operator >>( QDataStream &s, BMP_INFOHDR &bi ) |
||||||
|
{ |
||||||
|
s >> bi.biSize; |
||||||
|
if ( bi.biSize == BMP_INFOHDR::Size ) |
||||||
|
{ |
||||||
|
s >> bi.biWidth >> bi.biHeight >> bi.biPlanes >> bi.biBitCount; |
||||||
|
s >> bi.biCompression >> bi.biSizeImage; |
||||||
|
s >> bi.biXPelsPerMeter >> bi.biYPelsPerMeter; |
||||||
|
s >> bi.biClrUsed >> bi.biClrImportant; |
||||||
|
} |
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
#if 0 |
||||||
|
QDataStream &operator<<( QDataStream &s, const BMP_INFOHDR &bi ) |
||||||
|
{ |
||||||
|
s << bi.biSize; |
||||||
|
s << bi.biWidth << bi.biHeight; |
||||||
|
s << bi.biPlanes; |
||||||
|
s << bi.biBitCount; |
||||||
|
s << bi.biCompression; |
||||||
|
s << bi.biSizeImage; |
||||||
|
s << bi.biXPelsPerMeter << bi.biYPelsPerMeter; |
||||||
|
s << bi.biClrUsed << bi.biClrImportant; |
||||||
|
return s; |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
// Header for every icon in the file
|
||||||
|
struct IconRec |
||||||
|
{ |
||||||
|
unsigned char width; |
||||||
|
unsigned char height; |
||||||
|
quint16 colors; |
||||||
|
quint16 hotspotX; |
||||||
|
quint16 hotspotY; |
||||||
|
quint32 size; |
||||||
|
quint32 offset; |
||||||
|
}; |
||||||
|
|
||||||
|
inline QDataStream& operator >>( QDataStream& s, IconRec& r ) |
||||||
|
{ |
||||||
|
return s >> r.width >> r.height >> r.colors |
||||||
|
>> r.hotspotX >> r.hotspotY >> r.size >> r.offset; |
||||||
|
} |
||||||
|
|
||||||
|
struct LessDifference |
||||||
|
{ |
||||||
|
LessDifference( unsigned s, unsigned c ) |
||||||
|
: size( s ), colors( c ) {} |
||||||
|
|
||||||
|
bool operator ()( const IconRec& lhs, const IconRec& rhs ) const |
||||||
|
{ |
||||||
|
// closest size match precedes everything else
|
||||||
|
if ( std::abs( int( lhs.width - size ) ) < |
||||||
|
std::abs( int( rhs.width - size ) ) ) return true; |
||||||
|
else if ( std::abs( int( lhs.width - size ) ) > |
||||||
|
std::abs( int( rhs.width - size ) ) ) return false; |
||||||
|
else if ( colors == 0 ) |
||||||
|
{ |
||||||
|
// high/true color requested
|
||||||
|
if ( lhs.colors == 0 ) return true; |
||||||
|
else if ( rhs.colors == 0 ) return false; |
||||||
|
else return lhs.colors > rhs.colors; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
// indexed icon requested
|
||||||
|
if ( lhs.colors == 0 && rhs.colors == 0 ) return false; |
||||||
|
else if ( lhs.colors == 0 ) return false; |
||||||
|
else return std::abs( int( lhs.colors - colors ) ) < |
||||||
|
std::abs( int( rhs.colors - colors ) ); |
||||||
|
} |
||||||
|
} |
||||||
|
unsigned size; |
||||||
|
unsigned colors; |
||||||
|
}; |
||||||
|
|
||||||
|
bool loadFromDIB( QDataStream& stream, const IconRec& rec, QImage& icon ) |
||||||
|
{ |
||||||
|
BMP_INFOHDR header; |
||||||
|
stream >> header; |
||||||
|
if ( stream.atEnd() || header.biSize != BMP_INFOHDR::Size || |
||||||
|
header.biSize > rec.size || |
||||||
|
header.biCompression != BMP_INFOHDR::RGB || |
||||||
|
( header.biBitCount != 1 && header.biBitCount != 4 && |
||||||
|
header.biBitCount != 8 && header.biBitCount != 24 && |
||||||
|
header.biBitCount != 32 ) ) return false; |
||||||
|
|
||||||
|
unsigned paletteSize, paletteEntries; |
||||||
|
|
||||||
|
if (header.biBitCount > 8) |
||||||
|
{ |
||||||
|
paletteEntries = 0; |
||||||
|
paletteSize = 0; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
paletteSize = (1 << header.biBitCount); |
||||||
|
paletteEntries = paletteSize; |
||||||
|
if (header.biClrUsed && header.biClrUsed < paletteSize) |
||||||
|
paletteEntries = header.biClrUsed; |
||||||
|
} |
||||||
|
|
||||||
|
// Always create a 32-bit image to get the mask right
|
||||||
|
// Note: this is safe as rec.width, rec.height are bytes
|
||||||
|
icon = QImage( rec.width, rec.height, QImage::Format_ARGB32 ); |
||||||
|
if ( icon.isNull() ) return false; |
||||||
|
|
||||||
|
QVector< QRgb > colorTable( paletteSize ); |
||||||
|
|
||||||
|
colorTable.fill( QRgb( 0 ) ); |
||||||
|
for ( unsigned i = 0; i < paletteEntries; ++i ) |
||||||
|
{ |
||||||
|
unsigned char rgb[ 4 ]; |
||||||
|
stream.readRawData( reinterpret_cast< char* >( &rgb ), |
||||||
|
sizeof( rgb ) ); |
||||||
|
colorTable[ i ] = qRgb( rgb[ 2 ], rgb[ 1 ], rgb[ 0 ] ); |
||||||
|
} |
||||||
|
|
||||||
|
unsigned bpl = ( rec.width * header.biBitCount + 31 ) / 32 * 4; |
||||||
|
|
||||||
|
unsigned char* buf = new unsigned char[ bpl ]; |
||||||
|
unsigned char** lines = icon.jumpTable(); |
||||||
|
for ( unsigned y = rec.height; !stream.atEnd() && y--; ) |
||||||
|
{ |
||||||
|
stream.readRawData( reinterpret_cast< char* >( buf ), bpl ); |
||||||
|
unsigned char* pixel = buf; |
||||||
|
QRgb* p = reinterpret_cast< QRgb* >( lines[ y ] ); |
||||||
|
switch ( header.biBitCount ) |
||||||
|
{ |
||||||
|
case 1: |
||||||
|
for ( unsigned x = 0; x < rec.width; ++x ) |
||||||
|
*p++ = colorTable[ |
||||||
|
( pixel[ x / 8 ] >> ( 7 - ( x & 0x07 ) ) ) & 1 ]; |
||||||
|
break; |
||||||
|
case 4: |
||||||
|
for ( unsigned x = 0; x < rec.width; ++x ) |
||||||
|
if ( x & 1 ) *p++ = colorTable[ pixel[ x / 2 ] & 0x0f ]; |
||||||
|
else *p++ = colorTable[ pixel[ x / 2 ] >> 4 ]; |
||||||
|
break; |
||||||
|
case 8: |
||||||
|
for ( unsigned x = 0; x < rec.width; ++x ) |
||||||
|
*p++ = colorTable[ pixel[ x ] ]; |
||||||
|
break; |
||||||
|
case 24: |
||||||
|
for ( unsigned x = 0; x < rec.width; ++x ) |
||||||
|
*p++ = qRgb( pixel[ 3 * x + 2 ], |
||||||
|
pixel[ 3 * x + 1 ], |
||||||
|
pixel[ 3 * x ] ); |
||||||
|
break; |
||||||
|
case 32: |
||||||
|
for ( unsigned x = 0; x < rec.width; ++x ) |
||||||
|
*p++ = qRgba( pixel[ 4 * x + 2 ], |
||||||
|
pixel[ 4 * x + 1 ], |
||||||
|
pixel[ 4 * x ], |
||||||
|
pixel[ 4 * x + 3] ); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
delete[] buf; |
||||||
|
|
||||||
|
if ( header.biBitCount < 32 ) |
||||||
|
{ |
||||||
|
// Traditional 1-bit mask
|
||||||
|
bpl = ( rec.width + 31 ) / 32 * 4; |
||||||
|
buf = new unsigned char[ bpl ]; |
||||||
|
for ( unsigned y = rec.height; y--; ) |
||||||
|
{ |
||||||
|
stream.readRawData( reinterpret_cast< char* >( buf ), bpl ); |
||||||
|
QRgb* p = reinterpret_cast< QRgb* >( lines[ y ] ); |
||||||
|
for ( unsigned x = 0; x < rec.width; ++x, ++p ) |
||||||
|
if ( ( ( buf[ x / 8 ] >> ( 7 - ( x & 0x07 ) ) ) & 1 ) ) |
||||||
|
*p &= RGB_MASK; |
||||||
|
} |
||||||
|
delete[] buf; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ICOHandler::ICOHandler() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
bool ICOHandler::canRead() const |
||||||
|
{ |
||||||
|
if (canRead(device())) { |
||||||
|
setFormat("ico"); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool ICOHandler::read(QImage *outImage) |
||||||
|
{ |
||||||
|
|
||||||
|
qint64 offset = device()->pos(); |
||||||
|
|
||||||
|
QDataStream stream( device() ); |
||||||
|
stream.setByteOrder( QDataStream::LittleEndian ); |
||||||
|
IcoHeader header; |
||||||
|
stream >> header; |
||||||
|
if ( stream.atEnd() || !header.count || |
||||||
|
( header.type != IcoHeader::Icon && header.type != IcoHeader::Cursor) ) |
||||||
|
return false; |
||||||
|
|
||||||
|
unsigned requestedSize = 32; |
||||||
|
unsigned requestedColors = QApplication::desktop()->depth() > 8 ? 0 : QApplication::desktop()->depth(); |
||||||
|
int requestedIndex = -1; |
||||||
|
#if 0 |
||||||
|
if ( io->parameters() ) |
||||||
|
{ |
||||||
|
QStringList params = QString(io->parameters()).split( ';', QString::SkipEmptyParts ); |
||||||
|
QMap< QString, QString > options; |
||||||
|
for ( QStringList::ConstIterator it = params.begin(); |
||||||
|
it != params.end(); ++it ) |
||||||
|
{ |
||||||
|
QStringList tmp = (*it).split( '=', QString::SkipEmptyParts ); |
||||||
|
if ( tmp.count() == 2 ) options[ tmp[ 0 ] ] = tmp[ 1 ]; |
||||||
|
} |
||||||
|
if ( options[ "index" ].toUInt() ) |
||||||
|
requestedIndex = options[ "index" ].toUInt(); |
||||||
|
if ( options[ "size" ].toUInt() ) |
||||||
|
requestedSize = options[ "size" ].toUInt(); |
||||||
|
if ( options[ "colors" ].toUInt() ) |
||||||
|
requestedColors = options[ "colors" ].toUInt(); |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
typedef std::vector< IconRec > IconList; |
||||||
|
IconList icons; |
||||||
|
for ( unsigned i = 0; i < header.count; ++i ) |
||||||
|
{ |
||||||
|
if ( stream.atEnd() ) |
||||||
|
return false; |
||||||
|
IconRec rec; |
||||||
|
stream >> rec; |
||||||
|
icons.push_back( rec ); |
||||||
|
} |
||||||
|
IconList::const_iterator selected; |
||||||
|
if (requestedIndex >= 0) { |
||||||
|
selected = std::min( icons.begin() + requestedIndex, icons.end() ); |
||||||
|
} else { |
||||||
|
selected = std::min_element( icons.begin(), icons.end(), |
||||||
|
LessDifference( requestedSize, requestedColors ) ); |
||||||
|
} |
||||||
|
if ( stream.atEnd() || selected == icons.end() || |
||||||
|
offset + selected->offset > device()->size() ) |
||||||
|
return false; |
||||||
|
|
||||||
|
device()->seek( offset + selected->offset ); |
||||||
|
QImage icon; |
||||||
|
if ( loadFromDIB( stream, *selected, icon ) ) |
||||||
|
{ |
||||||
|
icon.setText( "X-Index", 0, QString::number( selected - icons.begin() ) ); |
||||||
|
if ( header.type == IcoHeader::Cursor ) |
||||||
|
{ |
||||||
|
icon.setText( "X-HotspotX", 0, QString::number( selected->hotspotX ) ); |
||||||
|
icon.setText( "X-HotspotY", 0, QString::number( selected->hotspotY ) ); |
||||||
|
} |
||||||
|
|
||||||
|
*outImage = icon; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool ICOHandler::write(const QImage &/*image*/) |
||||||
|
{ |
||||||
|
#if 0 |
||||||
|
if (image.isNull()) |
||||||
|
return; |
||||||
|
|
||||||
|
QByteArray dibData; |
||||||
|
QDataStream dib(dibData, QIODevice::ReadWrite); |
||||||
|
dib.setByteOrder(QDataStream::LittleEndian); |
||||||
|
|
||||||
|
QImage pixels = image; |
||||||
|
QImage mask; |
||||||
|
if (io->image().hasAlphaBuffer()) |
||||||
|
mask = image.createAlphaMask(); |
||||||
|
else |
||||||
|
mask = image.createHeuristicMask(); |
||||||
|
mask.invertPixels(); |
||||||
|
for ( int y = 0; y < pixels.height(); ++y ) |
||||||
|
for ( int x = 0; x < pixels.width(); ++x ) |
||||||
|
if ( mask.pixel( x, y ) == 0 ) pixels.setPixel( x, y, 0 ); |
||||||
|
|
||||||
|
if (!qt_write_dib(dib, pixels)) |
||||||
|
return; |
||||||
|
|
||||||
|
uint hdrPos = dib.device()->at(); |
||||||
|
if (!qt_write_dib(dib, mask)) |
||||||
|
return; |
||||||
|
memmove(dibData.data() + hdrPos, dibData.data() + hdrPos + BMP_WIN + 8, dibData.size() - hdrPos - BMP_WIN - 8); |
||||||
|
dibData.resize(dibData.size() - BMP_WIN - 8); |
||||||
|
|
||||||
|
QDataStream ico(device()); |
||||||
|
ico.setByteOrder(QDataStream::LittleEndian); |
||||||
|
IcoHeader hdr; |
||||||
|
hdr.reserved = 0; |
||||||
|
hdr.type = Icon; |
||||||
|
hdr.count = 1; |
||||||
|
ico << hdr.reserved << hdr.type << hdr.count; |
||||||
|
IconRec rec; |
||||||
|
rec.width = image.width(); |
||||||
|
rec.height = image.height(); |
||||||
|
if (image.numColors() <= 16) |
||||||
|
rec.colors = 16; |
||||||
|
else if (image.depth() <= 8) |
||||||
|
rec.colors = 256; |
||||||
|
else |
||||||
|
rec.colors = 0; |
||||||
|
rec.hotspotX = 0; |
||||||
|
rec.hotspotY = 0; |
||||||
|
rec.dibSize = dibData.size(); |
||||||
|
ico << rec.width << rec.height << rec.colors |
||||||
|
<< rec.hotspotX << rec.hotspotY << rec.dibSize; |
||||||
|
rec.dibOffset = ico.device()->at() + sizeof(rec.dibOffset); |
||||||
|
ico << rec.dibOffset; |
||||||
|
|
||||||
|
BMP_INFOHDR dibHeader; |
||||||
|
dib.device()->at(0); |
||||||
|
dib >> dibHeader; |
||||||
|
dibHeader.biHeight = image.height() << 1; |
||||||
|
dib.device()->at(0); |
||||||
|
dib << dibHeader; |
||||||
|
|
||||||
|
ico.writeRawBytes(dibData.data(), dibData.size()); |
||||||
|
return true; |
||||||
|
#endif |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
QByteArray ICOHandler::name() const |
||||||
|
{ |
||||||
|
return "ico"; |
||||||
|
} |
||||||
|
|
||||||
|
bool ICOHandler::canRead(QIODevice *device) |
||||||
|
{ |
||||||
|
if (!device) { |
||||||
|
qWarning("ICOHandler::canRead() called with no device"); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
const qint64 oldPos = device->pos(); |
||||||
|
|
||||||
|
char head[8]; |
||||||
|
qint64 readBytes = device->read(head, sizeof(head)); |
||||||
|
const bool readOk = readBytes == sizeof(head); |
||||||
|
|
||||||
|
if (device->isSequential()) { |
||||||
|
while (readBytes > 0) |
||||||
|
device->ungetChar(head[readBytes-- - 1]); |
||||||
|
} else { |
||||||
|
device->seek(oldPos); |
||||||
|
} |
||||||
|
|
||||||
|
if ( !readOk ) |
||||||
|
return false; |
||||||
|
|
||||||
|
return head[2] == '\001' && head[3] == '\000' && // type should be 1
|
||||||
|
( head[6] == 16 || head[6] == 32 || head[6] == 64 ) && // width can only be one of those
|
||||||
|
( head[7] == 16 || head[7] == 32 || head[7] == 64 ); // same for height
|
||||||
|
} |
||||||
|
|
||||||
|
class ICOPlugin : public QImageIOPlugin |
||||||
|
{ |
||||||
|
public: |
||||||
|
QStringList keys() const; |
||||||
|
Capabilities capabilities(QIODevice *device, const QByteArray &format) const; |
||||||
|
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const; |
||||||
|
}; |
||||||
|
|
||||||
|
QStringList ICOPlugin::keys() const |
||||||
|
{ |
||||||
|
return QStringList() << "ico" << "ICO"; |
||||||
|
} |
||||||
|
|
||||||
|
QImageIOPlugin::Capabilities ICOPlugin::capabilities(QIODevice *device, const QByteArray &format) const |
||||||
|
{ |
||||||
|
if (format == "ico" || format == "ICO") |
||||||
|
return Capabilities(CanRead); |
||||||
|
if (!format.isEmpty()) |
||||||
|
return 0; |
||||||
|
if (!device->isOpen()) |
||||||
|
return 0; |
||||||
|
|
||||||
|
Capabilities cap; |
||||||
|
if (device->isReadable() && ICOHandler::canRead(device)) |
||||||
|
cap |= CanRead; |
||||||
|
return cap; |
||||||
|
} |
||||||
|
|
||||||
|
QImageIOHandler *ICOPlugin::create(QIODevice *device, const QByteArray &format) const |
||||||
|
{ |
||||||
|
QImageIOHandler *handler = new ICOHandler; |
||||||
|
handler->setDevice(device); |
||||||
|
handler->setFormat(format); |
||||||
|
return handler; |
||||||
|
} |
||||||
|
|
||||||
|
Q_EXPORT_STATIC_PLUGIN(ICOPlugin) |
||||||
|
Q_EXPORT_PLUGIN2(ico, ICOPlugin) |
@ -0,0 +1,52 @@ |
|||||||
|
/*
|
||||||
|
* ico.h - kimgio import filter for MS Windows .ico files |
||||||
|
* |
||||||
|
* Distributed under the terms of the LGPL |
||||||
|
* Copyright (c) 2000 Malte Starostik <malte@kde.org> |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
// You can use QImageIO::setParameters() to request a specific
|
||||||
|
// Icon out of an .ico file:
|
||||||
|
//
|
||||||
|
// Options consist of a name=value pair and are separated by a semicolon.
|
||||||
|
// Available options are:
|
||||||
|
// size=<size> select the icon that most closely matches <size> (pixels)
|
||||||
|
// default: 32
|
||||||
|
// colors=<num> select the icon that has <num> colors (or comes closest)
|
||||||
|
// default: 1 << display depth or 0 (RGB) if display depth > 8
|
||||||
|
// index=<index> select the indexth icon from the file. If this option
|
||||||
|
// is present, the size and colors options will be ignored.
|
||||||
|
// default: none
|
||||||
|
// If both size and colors are given, size takes precedence.
|
||||||
|
//
|
||||||
|
// The old format is still supported:
|
||||||
|
// the parameters consist of a single string in the form
|
||||||
|
// "<size>[:<colors>]" which correspond to the options above
|
||||||
|
//
|
||||||
|
// If an icon was returned (i.e. the file is valid and the index option
|
||||||
|
// if present was not out of range), the icon's index within the .ico
|
||||||
|
// file is returned in the text tag "X-Index" of the image.
|
||||||
|
// If the icon is in fact a cursor, its hotspot coordinates are returned
|
||||||
|
// in the text tags "X-HotspotX" and "X-HotspotY".
|
||||||
|
|
||||||
|
#ifndef _ICO_H_ |
||||||
|
#define _ICO_H_ |
||||||
|
|
||||||
|
#include <QtGui/QImageIOPlugin> |
||||||
|
|
||||||
|
class ICOHandler : public QImageIOHandler |
||||||
|
{ |
||||||
|
public: |
||||||
|
ICOHandler(); |
||||||
|
|
||||||
|
bool canRead() const; |
||||||
|
bool read(QImage *image); |
||||||
|
bool write(const QImage &image); |
||||||
|
|
||||||
|
QByteArray name() const; |
||||||
|
|
||||||
|
static bool canRead(QIODevice *device); |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue