File indexing completed on 2024-06-09 04:27:49
0001 /* 0002 * SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_tga_import.h" 0008 0009 #include <QCheckBox> 0010 #include <QBuffer> 0011 #include <QSlider> 0012 #include <QApplication> 0013 0014 #include <kpluginfactory.h> 0015 #include <QFileInfo> 0016 0017 #include <KoColorSpace.h> 0018 #include <KoColorSpaceRegistry.h> 0019 0020 #include <kis_transaction.h> 0021 #include <kis_paint_device.h> 0022 #include <KisDocument.h> 0023 #include <kis_image.h> 0024 #include <kis_paint_layer.h> 0025 #include <kis_node.h> 0026 #include <kis_group_layer.h> 0027 0028 #include <tga.h> 0029 0030 K_PLUGIN_FACTORY_WITH_JSON(KisTGAImportFactory, "krita_tga_import.json", registerPlugin<KisTGAImport>();) 0031 0032 KisTGAImport::KisTGAImport(QObject *parent, const QVariantList &) 0033 : KisImportExportFilter(parent) 0034 { 0035 } 0036 0037 KisTGAImport::~KisTGAImport() 0038 { 0039 } 0040 0041 static QDataStream & operator>> (QDataStream & s, TgaHeader & head) 0042 { 0043 s >> head.id_length; 0044 s >> head.colormap_type; 0045 s >> head.image_type; 0046 s >> head.colormap_index; 0047 s >> head.colormap_length; 0048 s >> head.colormap_size; 0049 s >> head.x_origin; 0050 s >> head.y_origin; 0051 s >> head.width; 0052 s >> head.height; 0053 s >> head.pixel_size; 0054 s >> head.flags; 0055 0056 /*dbgKrita << "id_length: " << head.id_length << " - colormap_type: " << head.colormap_type << " - image_type: " << head.image_type; 0057 dbgKrita << "colormap_index: " << head.colormap_index << " - colormap_length: " << head.colormap_length << " - colormap_size: " << head.colormap_size; 0058 dbgKrita << "x_origin: " << head.x_origin << " - y_origin: " << head.y_origin << " - width:" << head.width << " - height:" << head.height << " - pixelsize: " << head.pixel_size << " - flags: " << head.flags;*/ 0059 0060 return s; 0061 } 0062 0063 0064 static bool isSupported(const TgaHeader & head) 0065 { 0066 if (head.image_type != TGA_TYPE_INDEXED && 0067 head.image_type != TGA_TYPE_RGB && 0068 head.image_type != TGA_TYPE_GREY && 0069 head.image_type != TGA_TYPE_RLE_INDEXED && 0070 head.image_type != TGA_TYPE_RLE_RGB && 0071 head.image_type != TGA_TYPE_RLE_GREY) { 0072 return false; 0073 } 0074 0075 if (head.image_type == TGA_TYPE_INDEXED || 0076 head.image_type == TGA_TYPE_RLE_INDEXED) { 0077 if (head.colormap_length > 256 || head.colormap_size != 24 || head.colormap_type != 1) { 0078 return false; 0079 } 0080 } 0081 0082 if (head.image_type == TGA_TYPE_RGB || 0083 head.image_type == TGA_TYPE_GREY || 0084 head.image_type == TGA_TYPE_RLE_RGB || 0085 head.image_type == TGA_TYPE_RLE_GREY) { 0086 if (head.colormap_type != 0) { 0087 return false; 0088 } 0089 } 0090 0091 if (head.width == 0 || head.height == 0) { 0092 return false; 0093 } 0094 0095 if (head.pixel_size != 8 && head.pixel_size != 16 && 0096 head.pixel_size != 24 && head.pixel_size != 32) { 0097 return false; 0098 } 0099 0100 return true; 0101 } 0102 0103 static bool loadTGA(QDataStream & s, const TgaHeader & tga, QImage &img) 0104 { 0105 // Create image. 0106 img = QImage(tga.width, tga.height, QImage::Format_RGB32); 0107 0108 TgaHeaderInfo info(tga); 0109 0110 /** 0111 * Theoretically, we should check alpha presence via the bits 0112 * in flags, but there are a lot of files in the wild that 0113 * have this flag unset. It contradicts TGA specification, 0114 * but we cannot do anything about it. 0115 */ 0116 const bool alphaFlag = tga.flags & 0xf; 0117 if (tga.pixel_size == 32 && !alphaFlag) { 0118 qWarning() << "WARNING: TGA image with 32-bit pixel size reports absence of alpha channel. It is not possible, fixing..."; 0119 } 0120 0121 if (tga.pixel_size == 32 || tga.pixel_size == 16) { 0122 img = QImage(tga.width, tga.height, QImage::Format_ARGB32); 0123 } 0124 0125 uint pixel_size = (tga.pixel_size / 8); 0126 uint size = tga.width * tga.height * pixel_size; 0127 0128 if (size < 1) { 0129 dbgFile << "This TGA file is broken with size " << size; 0130 return false; 0131 } 0132 0133 // Read palette. 0134 char palette[768]; 0135 if (info.pal) { 0136 // @todo Support palettes in other formats! 0137 s.readRawData(palette, 3 * tga.colormap_length); 0138 } 0139 0140 // Allocate image. 0141 uchar * const image = new uchar[size]; 0142 0143 if (info.rle) { 0144 // Decode image. 0145 char * dst = (char *)image; 0146 int num = size; 0147 0148 while (num > 0) { 0149 // Get packet header. 0150 uchar c; 0151 s >> c; 0152 0153 uint count = (c & 0x7f) + 1; 0154 num -= count * pixel_size; 0155 0156 if (c & 0x80) { 0157 // RLE pixels. 0158 Q_ASSERT(pixel_size <= 8); 0159 char pixel[8]; 0160 s.readRawData(pixel, pixel_size); 0161 do { 0162 memcpy(dst, pixel, pixel_size); 0163 dst += pixel_size; 0164 } while (--count); 0165 } else { 0166 // Raw pixels. 0167 count *= pixel_size; 0168 s.readRawData(dst, count); 0169 dst += count; 0170 } 0171 } 0172 } else { 0173 // Read raw image. 0174 s.readRawData((char *)image, size); 0175 } 0176 0177 // Convert image to internal format. 0178 int y_start, y_step, y_end; 0179 if (tga.flags & TGA_ORIGIN_UPPER) { 0180 y_start = 0; 0181 y_step = 1; 0182 y_end = tga.height; 0183 } else { 0184 y_start = tga.height - 1; 0185 y_step = -1; 0186 y_end = -1; 0187 } 0188 0189 uchar* src = image; 0190 0191 bool hasAlpha = false; 0192 for (int y = y_start; y != y_end; y += y_step) { 0193 QRgb * scanline = (QRgb *) (void*) img.scanLine(y); 0194 0195 if (info.pal) { 0196 // Paletted. 0197 for (int x = 0; x < tga.width; x++) { 0198 uchar idx = *src++; 0199 scanline[x] = qRgb(palette[3 * idx + 2], palette[3 * idx + 1], palette[3 * idx + 0]); 0200 } 0201 } else if (info.grey) { 0202 // Greyscale. 0203 for (int x = 0; x < tga.width; x++) { 0204 scanline[x] = qRgb(*src, *src, *src); 0205 src++; 0206 } 0207 } else { 0208 // True Color. 0209 if (tga.pixel_size == 16) { 0210 for (int x = 0; x < tga.width; x++) { 0211 Color555 c = *reinterpret_cast<Color555 *>(src); 0212 scanline[x] = qRgb((c.r << 3) | (c.r >> 2), (c.g << 3) | (c.g >> 2), (c.b << 3) | (c.b >> 2)); 0213 src += 2; 0214 } 0215 } else if (tga.pixel_size == 24) { 0216 for (int x = 0; x < tga.width; x++) { 0217 scanline[x] = qRgb(src[2], src[1], src[0]); 0218 src += 3; 0219 } 0220 } else if (tga.pixel_size == 32) { 0221 for (int x = 0; x < tga.width; x++) { 0222 const uchar alpha = src[3]; 0223 scanline[x] = qRgba(src[2], src[1], src[0], alpha); 0224 src += 4; 0225 hasAlpha |= (alpha > 0); 0226 } 0227 } 0228 } 0229 } 0230 /* According to http://www.paulbourke.net/dataformats/tga/ 0231 * Targa 24 images are sometimes stored as Targa 32 images. 0232 * 0233 * In case all alpha information is transparent, we convert 0234 * image to 24 bits. 0235 */ 0236 if (!hasAlpha && tga.pixel_size == 32) { 0237 img.convertTo(QImage::Format_RGB32); 0238 qWarning() << "WARNING: TGA image with 32-bit has all pixels transparent, removing alpha information."; 0239 } 0240 0241 // Free image. 0242 delete []image; 0243 0244 return true; 0245 } 0246 0247 0248 0249 KisImportExportErrorCode KisTGAImport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration) 0250 { 0251 Q_UNUSED(configuration); 0252 QDataStream s(io); 0253 s.setByteOrder(QDataStream::LittleEndian); 0254 0255 TgaHeader tga; 0256 s >> tga; 0257 s.device()->seek(TgaHeader::SIZE + tga.id_length); 0258 0259 0260 // Check image file format. 0261 if (s.atEnd()) { 0262 return ImportExportCodes::FileFormatIncorrect; 0263 } 0264 0265 // Check supported file types. 0266 if (!isSupported(tga)) { 0267 return ImportExportCodes::FormatFeaturesUnsupported; 0268 } 0269 0270 QImage img; 0271 bool result = loadTGA(s, tga, img); 0272 0273 if (result == false) { 0274 return ImportExportCodes::FileFormatIncorrect; 0275 } 0276 0277 const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->rgb8(); 0278 KisImageSP image = new KisImage(document->createUndoStore(), img.width(), img.height(), colorSpace, "imported from tga"); 0279 0280 KisPaintLayerSP layer = new KisPaintLayer(image, image->nextLayerName(), 255); 0281 layer->paintDevice()->convertFromQImage(img, 0, 0, 0); 0282 image->addNode(layer.data(), image->rootLayer().data()); 0283 0284 document->setCurrentImage(image); 0285 return ImportExportCodes::OK; 0286 0287 } 0288 0289 #include "kis_tga_import.moc" 0290