mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-07-18 20:04:16 -04:00
TGA: add indexed write support
Indexed images are saved as uncompressed TGA with color map. Closes #30
This commit is contained in:
Binary file not shown.
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 10 KiB |
@ -99,7 +99,8 @@ static bool IsSupported(const TgaHeader &head)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (head.image_type == TGA_TYPE_INDEXED || head.image_type == TGA_TYPE_RLE_INDEXED) {
|
if (head.image_type == TGA_TYPE_INDEXED || head.image_type == TGA_TYPE_RLE_INDEXED) {
|
||||||
if (head.colormap_length > 256 || head.colormap_type != 1) {
|
// GIMP saves TGAs with palette size of 257 (but 256 used) so, I need to check the pixel size only.
|
||||||
|
if (head.pixel_size > 8 || head.colormap_type != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// colormap_size == 16 would be ARRRRRGG GGGBBBBB but we don't support that.
|
// colormap_size == 16 would be ARRRRRGG GGGBBBBB but we don't support that.
|
||||||
@ -500,6 +501,59 @@ bool TGAHandler::read(QImage *outImage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TGAHandler::write(const QImage &image)
|
bool TGAHandler::write(const QImage &image)
|
||||||
|
{
|
||||||
|
if (image.format() == QImage::Format_Indexed8)
|
||||||
|
return writeIndexed(image);
|
||||||
|
return writeRGBA(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TGAHandler::writeIndexed(const QImage &image)
|
||||||
|
{
|
||||||
|
QDataStream s(device());
|
||||||
|
s.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
|
||||||
|
QImage img(image);
|
||||||
|
auto ct = img.colorTable();
|
||||||
|
|
||||||
|
s << quint8(0); // ID Length
|
||||||
|
s << quint8(1); // Color Map Type
|
||||||
|
s << quint8(TGA_TYPE_INDEXED); // Image Type
|
||||||
|
s << quint16(0); // First Entry Index
|
||||||
|
s << quint16(ct.size()); // Color Map Length
|
||||||
|
s << quint8(32); // Color map Entry Size
|
||||||
|
s << quint16(0); // X-origin of Image
|
||||||
|
s << quint16(0); // Y-origin of Image
|
||||||
|
|
||||||
|
s << quint16(img.width()); // Image Width
|
||||||
|
s << quint16(img.height()); // Image Height
|
||||||
|
s << quint8(8); // Pixe Depth
|
||||||
|
s << quint8(TGA_ORIGIN_UPPER + TGA_ORIGIN_LEFT); // Image Descriptor
|
||||||
|
|
||||||
|
for (auto &&rgb : ct) {
|
||||||
|
s << quint8(qBlue(rgb));
|
||||||
|
s << quint8(qGreen(rgb));
|
||||||
|
s << quint8(qRed(rgb));
|
||||||
|
s << quint8(qAlpha(rgb));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.status() != QDataStream::Ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < img.height(); y++) {
|
||||||
|
auto ptr = img.constScanLine(y);
|
||||||
|
for (int x = 0; x < img.width(); x++) {
|
||||||
|
s << *(ptr + x);
|
||||||
|
}
|
||||||
|
if (s.status() != QDataStream::Ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TGAHandler::writeRGBA(const QImage &image)
|
||||||
{
|
{
|
||||||
QDataStream s(device());
|
QDataStream s(device());
|
||||||
s.setByteOrder(QDataStream::LittleEndian);
|
s.setByteOrder(QDataStream::LittleEndian);
|
||||||
@ -535,6 +589,10 @@ bool TGAHandler::write(const QImage &image)
|
|||||||
s << quint8(hasAlpha ? 32 : 24); // depth (24 bit RGB + 8 bit alpha)
|
s << quint8(hasAlpha ? 32 : 24); // depth (24 bit RGB + 8 bit alpha)
|
||||||
s << quint8(hasAlpha ? originTopLeft + alphaChannel8Bits : originTopLeft); // top left image (0x20) + 8 bit alpha (0x8)
|
s << quint8(hasAlpha ? originTopLeft + alphaChannel8Bits : originTopLeft); // top left image (0x20) + 8 bit alpha (0x8)
|
||||||
|
|
||||||
|
if (s.status() != QDataStream::Ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (int y = 0; y < img.height(); y++) {
|
for (int y = 0; y < img.height(); y++) {
|
||||||
auto ptr = reinterpret_cast<const QRgb *>(img.constScanLine(y));
|
auto ptr = reinterpret_cast<const QRgb *>(img.constScanLine(y));
|
||||||
for (int x = 0; x < img.width(); x++) {
|
for (int x = 0; x < img.width(); x++) {
|
||||||
@ -546,6 +604,9 @@ bool TGAHandler::write(const QImage &image)
|
|||||||
s << quint8(qAlpha(color));
|
s << quint8(qAlpha(color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (s.status() != QDataStream::Ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -27,6 +27,10 @@ public:
|
|||||||
static bool canRead(QIODevice *device);
|
static bool canRead(QIODevice *device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool writeIndexed(const QImage &image);
|
||||||
|
|
||||||
|
bool writeRGBA(const QImage &image);
|
||||||
|
|
||||||
const QScopedPointer<TGAHandlerPrivate> d;
|
const QScopedPointer<TGAHandlerPrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user