From 9c6c0c01ae398ccecf31331ae75dad83b485eda2 Mon Sep 17 00:00:00 2001 From: Mirco Miranda Date: Sat, 23 Aug 2025 11:20:09 +0200 Subject: [PATCH] TGA: Support for TGA specification 2.0 Adds TGA 2.0 compliance: - Support for Extension Area, Developer Area and Footer (metadata support) - Support for 15-bit and 16-bit per pixel images (both RGB and Indexed) - Full support for rotation on reading (we cannot use Qt transformations because only a subset is part of the TGA specification) - When writing you can choose the supported version (subType) - Improved writing speed (approximately 10 times) and removed whole image conversions (significant memory savings) It pass the [TrueVision TGA 2.0 conformance suite](https://github.com/zigimg/test-suite/tree/master/fixtures/tga). Test changes: - Read test: added ability to skip a specific test on sequential devices (via JSON behavior file) - Write test: added the ability to set the subType when writing (via JSON properties file) Closes #37 --- README.md | 29 +- autotests/CMakeLists.txt | 2 +- autotests/README.md | 32 +- autotests/read/tga/bottom_left.tga | Bin 0 -> 230939 bytes autotests/read/tga/bottom_left.tga.json | 5 + autotests/read/tga/bottom_right.tga | Bin 0 -> 230939 bytes autotests/read/tga/bottom_right.tga.json | 5 + autotests/read/tga/devarea.tga | Bin 0 -> 81592 bytes autotests/read/tga/devarea.tga.json | 56 + autotests/read/tga/extarea.png | Bin 0 -> 21425 bytes autotests/read/tga/extarea.tga | Bin 0 -> 69192 bytes autotests/read/tga/extarea.tga.json | 32 + autotests/read/tga/orientation.png | Bin 0 -> 17999 bytes autotests/read/tga/rgb16.png | Bin 0 -> 2483 bytes autotests/read/tga/rgb16.tga | Bin 0 -> 18971 bytes autotests/read/tga/top_left.tga | Bin 0 -> 230939 bytes autotests/read/tga/top_left.tga.json | 5 + autotests/read/tga/top_right.tga | Bin 0 -> 230939 bytes autotests/read/tga/top_right.tga.json | 5 + autotests/readtest.cpp | 6 + autotests/templateimage.cpp | 9 + autotests/templateimage.h | 6 + autotests/write/basic/tga.json | 62 ++ autotests/write/format/tga/Format_RGB16.tga | Bin 27666 -> 18971 bytes autotests/write/format/tga/Format_RGB444.tga | Bin 27666 -> 18971 bytes autotests/write/format/tga/Format_RGB555.tga | Bin 27666 -> 18971 bytes .../write/format/tga/Format_RGBA16FPx4.tga | Bin 36882 -> 38207 bytes autotests/writetest.cpp | 12 + src/imageformats/CMakeLists.txt | 2 +- src/imageformats/tga.cpp | 979 ++++++++++++++---- src/imageformats/tga_p.h | 7 +- 31 files changed, 1054 insertions(+), 200 deletions(-) create mode 100644 autotests/read/tga/bottom_left.tga create mode 100644 autotests/read/tga/bottom_left.tga.json create mode 100644 autotests/read/tga/bottom_right.tga create mode 100644 autotests/read/tga/bottom_right.tga.json create mode 100644 autotests/read/tga/devarea.tga create mode 100644 autotests/read/tga/devarea.tga.json create mode 100644 autotests/read/tga/extarea.png create mode 100644 autotests/read/tga/extarea.tga create mode 100644 autotests/read/tga/extarea.tga.json create mode 100644 autotests/read/tga/orientation.png create mode 100644 autotests/read/tga/rgb16.png create mode 100644 autotests/read/tga/rgb16.tga create mode 100644 autotests/read/tga/top_left.tga create mode 100644 autotests/read/tga/top_left.tga.json create mode 100644 autotests/read/tga/top_right.tga create mode 100644 autotests/read/tga/top_right.tga.json create mode 100644 autotests/write/basic/tga.json diff --git a/README.md b/README.md index f65819c..8a9654a 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,17 @@ submit the plugin directly to the Qt Project. To be accepted, contributions must: - Contain the test images needed to verify that the changes work correctly. - Pass the tests successfully. +- Use Qt logging categories for Debug messages. For more info about tests, see also [Autotests README](autotests/README.md). ## Duplicated Plugins +> [!important] +> To ensure you are using the correct plugin, the unwanted one should be +renamed or deleted. If several plugins support the same capability, Qt will +select one arbitrarily. + ### The TGA plugin The TGA plugin supports more formats than Qt's own TGA plugin; @@ -340,10 +346,6 @@ The plugin supports the following image data: - FOR4 CIMG (Maya Image File Format): It supports 24/48-bit RGB and 32/64-bit RGBA images. -The plugin does not load images with non-standard SHAM/CTBL chunks due to the -lack of clear specifications. - - ### The JP2 plugin **This plugin can be disabled by setting `KIMAGEFORMATS_JP2` to `OFF` @@ -426,6 +428,25 @@ selectively change the conversion (see also [raw_p.h](./src/imageformats/raw_p.h The default setting tries to balance quality and conversion speed. +### The TGA plugin + +TGA plugin supports both version 1 and version 2 of TGA files. When writing, +it is possible to force which version to use by setting the following subtypes: +- `TGAv1`: force TGA v1.0. No metadata. +- `TGAv2` (default): force TGA v2.0 (strict). Adds the TGA Extension Area. +- `TGAv2E`: force TGA v2.0 (enhanced). Same as TGA v2.0 (strict) but with the + addition of the TGA v2.0 Developer Area with info like, for e.g., Exif data, + XMP packet and the ICC profile. + +They are all TGA specs compliant. While for versions 1 and 2 (strict) it is +possible to decode all the information with the TGA specification alone, for +version 2 (enhanced) it is necessary to know how the additional data is +encoded. + +The following defines can be defined in cmake to modify the behavior of the +plugin: +- `TGA_V2E_AS_DEFAULT`: change the default version of the plugin to `TGAv2E`. + ### The XCF plugin XCF support has the following limitations: diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index e871752..465e411 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -189,7 +189,7 @@ kimageformats_write_tests( pic-lossless qoi-lossless rgb-lossless - tga # fixme: the alpha images appear not to be written properly + tga-nodatacheck ) # EPS read tests depend on the vagaries of GhostScript diff --git a/autotests/README.md b/autotests/README.md index 3f68bbb..11df784 100644 --- a/autotests/README.md +++ b/autotests/README.md @@ -88,30 +88,33 @@ are iterated sequentially and the first object that matches the requirements is used for testing (successes are ignored). Supported values ​​for JSON objects: -- `comment`: Type string. A string shown by the test when a condition occurs. -- `description`: Type string. A description of the object. Not used by the +- `comment`: Type `string`. A string shown by the test when a condition occurs. +- `description`: Type `string`. A description of the object. Not used by the test. -- `disableAutoTransform`: Type boolean. By default, tests are run with +- `disableAutoTransform`: Type `boolean`. By default, tests are run with autotransform enabled (i.e. rotation is applied if the plugin supports it). Set to `true` to disable autotransform. -- `filename`: Type string. Name of the template file to use. E.g. +- `filename`: Type `string`. Name of the template file to use. E.g. "testRGB_Qt_6_2.png". -- `fuzziness`: Type integer. Set the fuzziness only if not already set on the +- `fuzziness`: Type `integer`. Set the fuzziness only if not already set on the command line. The value set on the command line wins over the one in the JSON file. -- `maxQtVersion`: Type string. Maximum Qt version this object is compatible +- `maxQtVersion`: Type `string`. Maximum Qt version this object is compatible with (if not set means all). E.g. "6.2.99". -- `metadata`: Type Array. An array of key/value objects (string type) +- `metadata`: Type `array`. An array of key/value objects (string type) containing the image metadata as returned by `QImage::text`. -- `minQtVersion`: Type string. Minimum Qt version this object is compatible +- `minQtVersion`: Type `string`. Minimum Qt version this object is compatible with (if not set means all). E.g. "6.2.0". -- `perceptiveFuzziness` Type boolean. Set the perceptive fuzziness only if not +- `perceptiveFuzziness` Type `boolean`. Set the perceptive fuzziness only if not already set on the command line. The value set on the command line wins over the one in the JSON file. -- `resolution`: Type object. An object with the `dotsPerMeterX` and +- `resolution`: Type `object`. An object with the `dotsPerMeterX` and `dotsPerMeterY` (integer) values ​​of the image. -- `seeAlso`: Type string. More info about the object. Normally used to point +- `seeAlso`: Type `string`. More info about the object. Normally used to point to bug reports. Not used by the test. +- `skipSequential`: Type `boolean`. Skip the test on sequential access device. +Some plugins may have limited functionality on sequential devices (e.g., +not reading metadata). - `unsupportedFormat`: Type `boolean`. When true, the test is skipped. Some examples: @@ -169,11 +172,12 @@ See also [Add a test to CMakeLists.txt](#add-a-test-to-cmakeliststxt). The properties file must be located in `write/basic` and must have the name of the file format (e.g. jxl.json). It is a JSON object composed of the following values: -- `format`: Type string. The format tested. -- `metadata`: Type Array. An array of key/value objects (string type) +- `format`: Type `string`. The format tested. +- `metadata`: Type `array`. An array of key/value objects (string type) containing the image metadata as returned by `QImage::text`. -- `resolution`: Type object. An object with the `dotsPerMeterX` and ` +- `resolution`: Type `object`. An object with the `dotsPerMeterX` and ` dotsPerMeterY` (integer) values ​​of the image. +- `subType`: type `string`. The image writer subtype to set when testing. [This is an example](write/basic/jxl.json) of property file. diff --git a/autotests/read/tga/bottom_left.tga b/autotests/read/tga/bottom_left.tga new file mode 100644 index 0000000000000000000000000000000000000000..049e4d42ff28afd091efa9dabc9ae70118af9595 GIT binary patch literal 230939 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 X#?AU$j5istUnjH8z<7`(t62EEPQ literal 0 HcmV?d00001 diff --git a/autotests/read/tga/bottom_left.tga.json b/autotests/read/tga/bottom_left.tga.json new file mode 100644 index 0000000..cd45ed6 --- /dev/null +++ b/autotests/read/tga/bottom_left.tga.json @@ -0,0 +1,5 @@ +[ + { + "fileName" : "orientation.png" + } +] diff --git a/autotests/read/tga/bottom_right.tga b/autotests/read/tga/bottom_right.tga new file mode 100644 index 0000000000000000000000000000000000000000..1784a8ecf95c3349051caf07904341b68ae9958e GIT binary patch literal 230939 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 literal 0 HcmV?d00001 diff --git a/autotests/read/tga/bottom_right.tga.json b/autotests/read/tga/bottom_right.tga.json new file mode 100644 index 0000000..cd45ed6 --- /dev/null +++ b/autotests/read/tga/bottom_right.tga.json @@ -0,0 +1,5 @@ +[ + { + "fileName" : "orientation.png" + } +] diff --git a/autotests/read/tga/devarea.tga b/autotests/read/tga/devarea.tga new file mode 100644 index 0000000000000000000000000000000000000000..c0fe83289899c1de846d384795ee33a6afdadfdd GIT binary patch literal 81592 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

oPME=w}_XPmJ${Q^8%P#4FRD?*(~_Pj8c@) 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 literal 0 HcmV?d00001 diff --git a/autotests/read/tga/extarea.tga b/autotests/read/tga/extarea.tga new file mode 100644 index 0000000000000000000000000000000000000000..ff3a718690d681f071a2485d7b53a26b3c1af0ba GIT binary patch literal 69192 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 T%k`FPRx52bv$Qc){^kD%ac<4~ literal 0 HcmV?d00001 diff --git a/autotests/read/tga/top_left.tga.json b/autotests/read/tga/top_left.tga.json new file mode 100644 index 0000000..cd45ed6 --- /dev/null +++ b/autotests/read/tga/top_left.tga.json @@ -0,0 +1,5 @@ +[ + { + "fileName" : "orientation.png" + } +] diff --git a/autotests/read/tga/top_right.tga b/autotests/read/tga/top_right.tga new file mode 100644 index 0000000000000000000000000000000000000000..98af8bf7bea506587119a4b7ca8d828bbc48e45d GIT binary patch literal 230939 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 literal 0 HcmV?d00001 diff --git a/autotests/read/tga/top_right.tga.json b/autotests/read/tga/top_right.tga.json new file mode 100644 index 0000000..cd45ed6 --- /dev/null +++ b/autotests/read/tga/top_right.tga.json @@ -0,0 +1,5 @@ +[ + { + "fileName" : "orientation.png" + } +] diff --git a/autotests/readtest.cpp b/autotests/readtest.cpp index 061da8e..639db0c 100644 --- a/autotests/readtest.cpp +++ b/autotests/readtest.cpp @@ -281,6 +281,12 @@ int main(int argc, char **argv) continue; } + if (seq && timg.skipSequentialDeviceTest()) { + QTextStream(stdout) << "SKIP : " << fi.fileName() << ": marked to be skipped on a sequential device (don't worry, it's ok)\n"; + ++skipped; + continue; + } + TemplateImage::TestFlags flags = TemplateImage::None; QString comment; QFileInfo expFileInfo = timg.compareImage(flags, comment); diff --git a/autotests/templateimage.cpp b/autotests/templateimage.cpp index 65b4fff..15ad33c 100644 --- a/autotests/templateimage.cpp +++ b/autotests/templateimage.cpp @@ -76,6 +76,15 @@ bool TemplateImage::isLicense() const return !m_fi.suffix().compare(QStringLiteral("license"), Qt::CaseInsensitive); } +bool TemplateImage::skipSequentialDeviceTest() const +{ + auto obj = searchObject(m_fi); + if (obj.isEmpty()) { + return false; + } + return obj.value("skipSequential").toBool(); +} + QFileInfo TemplateImage::compareImage(TestFlags &flags, QString& comment) const { auto fi = jsonImage(flags, comment); diff --git a/autotests/templateimage.h b/autotests/templateimage.h index 847689e..d2bb504 100644 --- a/autotests/templateimage.h +++ b/autotests/templateimage.h @@ -54,6 +54,12 @@ public: */ bool isLicense() const; + /*! + * \brief skipSequentialDeviceTest + * \return tre it the sequential test should be skipped. + */ + bool skipSequentialDeviceTest() const; + /*! * \brief compareImage * \param flags Flags for modifying test behavior (e.g. image format not supported by current Qt version). diff --git a/autotests/write/basic/tga.json b/autotests/write/basic/tga.json new file mode 100644 index 0000000..86d6497 --- /dev/null +++ b/autotests/write/basic/tga.json @@ -0,0 +1,62 @@ +{ + "format" : "tga", + "subType" : "TGAv2E", + "metadata" : [ + { + "key" : "CreationDate", + "value" : "2025-01-14T13:53:32+01:00" + }, + { + "key" : "Direction", + "value" : "123.7" + }, + { + "key" : "Software" , + "value" : "Adobe Photoshop 26.2 (Windows)" + }, + { + "key" : "Altitude", + "value" : "34" + }, + { + "key" : "Author", + "value" : "KDE Project" + }, + { + "key" : "Copyright", + "value" : "@2025 KDE Project" + }, + { + "key" : "Description", + "value" : "テレビ放送テスト映像。(TV broadcast test image.)" + }, + { + "key" : "Latitude", + "value" : "44.6478" + }, + { + "key" : "LensManufacturer", + "value" : "KDE Glasses" + }, + { + "key" : "LensModel", + "value" : "A1234" + }, + { + "key" : "Longitude", + "value" : "10.9254" + }, + { + "key" : "Manufacturer", + "value" : "KFramework" + }, + { + "key" : "Model", + "value" : "KImageFormats" + } + ], + "resolution" : { + "dotsPerMeterX" : 11811, + "dotsPerMeterY" : 11812 + } +} diff --git a/autotests/write/format/tga/Format_RGB16.tga b/autotests/write/format/tga/Format_RGB16.tga index 9ef437cef19d7742ab6d1ea25eb33a85b69d22eb..2c00745066bc45f21e4d4230456a48796ab9ed4d 100644 GIT binary patch literal 18971 zcmeI4;cwei5Ww9vgKX*t3p!y$#X?oObnPlKp>?UcidifySqW7(N*h?H2qK`2b|Orh z)Jgdd=otMnwEuw#C`btYfPI`m0fyi!c_#VBlZ2ouszm$&V zD#evlB!w9E9tNmXBZ zLnGGXH?r-R_f!V9OY&$=H`~wu#1R_b%lM-=t21Nc>_I!?e=T+`v32~qIW~SbO&+w) z|4njsay_z@{J=huMGxxpTW29zzp_GP-^g;)vfPYrZdx}tW1d^}w*6rBHvlK*%HK1vQX6#t{A&kths{ly=gJW^dB z;JlLgEal&i6TRQ~57sB(G{N)Vtb3Ic}%^#9hiof?k!}nhI*=nWe zH2+8)`TVQ$b6t4NEXS8TDnIe8&ir5bm*=?2ILP>T-IsPt$GEZFIsQz)JjeRF={2() zU)p8*(lM5IIzN1m1)6mhQsd860-C7r{VQ9o6xI0i9waAzs%za;`B}cT{A^d{CwcXA zH}S`L)hYbW*Wb>Fe=R@Xe|84{N=l?pwJ!Pju`~E-{f+CHdMZCjE5(t^!Ip?8Pg9-0ro5uOd7IWT=-YVhRXi;ujpdt&#|-OmL^0^#m~?ofB%E~DCdyY#M} zuAmmw0$Kp)`TDPH)p`DrI+Y@=o;cTUE&o9a|056h1JAe4PxDOmNyX;+3s37R|K|Dc zCw^FKQ~7n1DnQL2j>G2s4dstkKXd3Vg6-PHAEI5$PZ`uYf1nNdUyq-@_b5GRYy3UV z|KFCtJEX^1RC=PupZDyK>_2pWN-uBy4l@`vrJ`NMK`{s)h~y9lo; zKc7dzAHEm9Tf_gw1OCMg{!_rOx5CeMReo4G!F^W#NDRJT*ciW4`~`nY@ptB@I<@lS zX8;ZG+vJZ;{5|2PPhaTzi(b(EC!CuG`0M14n*Rry&VQ%)Q}pfmb<@Z;#@|@}w4a~8 zK}-Bx&(u@-N$R|ndFZz9JSy)|>zCzfkI&cZ7uf^KE7+^*^Ee$!ZlyxmyON4_7MPA<&AR*k>Zl6|i0TK={8p2WU9@UxCL{5<|z{6^;G z4fJ5J+M)7H!-)R<7tHY1)oaTR7r_TL!o~prFN7h>Xel)j|ayw3I{JI&5 zrSp(WZtbf2sf3ZG_00M{!d`i7tNduKoRMR?>%(Wb?wF;1d-x$HaGl3r!^`oV`-NmQ zSI*!XxF7h5Ayxg2Es(9w6q3*_lk#gT>I{(a4d}u~2yGy@d;xhU|t3 f*$FpfkDbI_XHu`8n2Dc`zmhyO8;eh!7}fp*XGhG% literal 27666 zcmeI5F=!jf8poH1iY;8YNTK427_NxniWpLyAWa0XQK{0^9p;Khc*S9^2;!O`Tm+FK zh!jD*BA^ror7-9f0i`i)ihx`M^oj>+u26A>iz{5_{;Sda=gT*vwJfdewPi7A|1;mW z-_HE@n~}6D*-`Y5$Uc6Geu~QXzuJdwc3W$4TW7P%*{re_x3w0xbvCP<%_?hgTWfJ! zXS2%Ltg;rjwHCK^HmjV?Dr<3DYjIm=v&z}5vKF_s7PoaatDMa$YjIm^aa(7z%Gs>4 z7Pqw)w{ro3dO+OaG`pJQ*T#_ieZJvcA{qQR#6scwtlrZ9?<`wL*of65 zGtTILBN;re$izaCSL8I#L38wFgc-z9$RR-Id93Hn_Uks16VEwDCKifZ`i#W^aXN20 z5=btQ&ma5rq~vuhi3Kr(kLK&DD*fO0R0-}_s7BRcRI3LKRTk{9Jn5-kj1N4KFnDD# zyW?0Y&egYc-*vHun{F(~$M3TbP5CUy2QMXjVM2tfry;v7kB&DISP8F@&*1q}*&ox- zLbdb`dxIDI3Xz&zs0RCtM)i;^L)LZ~aLb3OI1PS$xo8Ai5+zy^ra8;~6^p;qJ!qLH|$xI#Y=Jaa}Zjx<~u%!|-aX z5EXfTnUh;PXmpPU649!B-qd;@T3C+!I0_D`#peSuyRTY}!!8l|<6{2!17r)==gFUA zqiM~c8Yp^Ij$|qP=Yl~r$oOB5adnq43P67F-J~M4be~gV@WL&-vu(aRpwcqaE zRz85!{?Ny>KX(7T`#!*ue0Ir$s_)~+xk32@GW%~kwHHhBNoUrZ8k6T%@&Tg$^nQVw zgZ_EfxpC0!9PLXux0O%*W%!zmL6q@Arr;PpL9nv1fb&as4;ne6igG}eSSZjaa}0M+ zf_$V8v>&;Ed{mzm98@t1Tym6d#6ltYq*vZT*MFpsiFRxF%!X_~HxUbk9QzDr@bjsS zaLf2$IOYzK85glokWcS@&-kp>{KAlB3K0th`HcTRUQa&hl51y&#Nw|ZrX`p^%9(L8 zMD{aj%E$-qL>xp3f+frTcYhToz_WU7o{ zM39d$O(qi~=Eae7a1HsSS4XE8Nayisze?}&&&vAc4+d_&RuSZbyJ-&2TFx&FA9EJZ zK|bd4zC*N@`D0cX^5H7V7K-5dL#q+oJwsgk`mFjKT%VPXKO8uy&mciQF1x17lpn`$ zxpqFP&p|%Y2Vb}FM*%+HEY9n?{s0ud78v9s8K!zI*B=ZV>+l^PImGP zKKL#i`KWbUR)h0PIzU$*S4?4h(OTFs3Q5LjnzDt=u?5$kqS5gCgCVPN1^GxHT;U0V zl0IwA=WroDji39f_~*huUqx&2``rJvp^Eas=d4BYN5Mf=#X*i0jfUSJzt0K|s>)}< z`L(uu%x{HE3T3>I1^Jl0_-uAZwXlL+r3mH^twsX3X6pu^T!qBBgchH z9K=H5$5~rGxWqv$6e*u?zk9j9eCB+&_qEq441t&bj5!Vtlp>w*H*`b!Kvmd@^3hg89Q8XX44;*C)GYkJEDccz5z6N`3sO zK6+FiKCC4VYlDZi{twmOgKGCdrSpBI{e7i%f2VnWXaBqHr{8VwmA7}xTlITewR`32 zX1TIi-r3mPjyJc`5|>NyW+{$QroH5pxscEuUhMUYSSS$3pgTQ1H6qBznE3ov^QotN zew^}oLZ9sWB@GJ?@6PV3h}>$ibK z1UKd52k~1toZN+ftYC}kv*I&8POz8qStJg~j7}!Eo6qF)5V)4+)BL4Bct0kh1>-3A zxu*>Sssqids@!n-^Q<{|*8w!8y#6scw1o`0dtos4ojpAeA;G7Z*g+F$Q z1=irh=TrT?jZ#18w2lTw`#Ua|QF*ODet)XZ+9N?dfK2Uq zyZ31XfjDZfYv-f-118PG!PD0>IH(c}g+GcF`IzJxe97$KG^q=^Fqhh!pqB>H)$ZaM!{Ela&-!U!6%hK*O+-ASC zUo)fQ#_ssNM!(Z*4AY@~abv^%ljA3HCQ7p|>(H1TKfQi*{z>q&&w1{!f6}qFTV`}R zeWUGom!~uzsy;T1-&ci?I!45L2u82eo4?< zo1kBkIKg`m=ApB*<_D)7VDxFP=7&D$`<-d=J6^jrI{&LsoreX}<9EFOIrGRkNZn;{B*TeY<^r%#_^MN#pb8?;2aZCem*uu=Ql?n%Fp-0iq5b7k9;;Q z&2M`3XB^V@()oBn=IfTsec8rJx@Bq)ZS@}c%JIxyVa<=VC9`bD)0fU;q;5%O*_Jf& zyrcPPuE)FdKdf)!s`&iuk1)T9t6AWuN~8I4UYG@biWSX|`|z{H&zUG~(frsWb5^$V z$zQCi^B4V+L0(sAe$)=BFWdR>V_nUUe#y}9nCwlyevtaIeLVcVhGdZSb~gOqZp}8o z+njBF6F-^n1MA{|&lXqLLd+0*YpX`6ock9qUzW4$Cp$nc_=cngbNVtm1T+sf<9@1p}{QqOs zen4OOY@uFe&@_jr&)eDO|n(mDs2Yxbs#quZY-<^a&6(-{6~SjKVP0NpRxlvJCH?d z(JBoja2lWchX2Q^$@NF-&?kx}vo*izb-XZtU_p-jST`>I>D{{KKRW)4#83CyG{57S z444J~lefeCCW4C3&z=tR&yN53?7;k7MWrp;|JZZRId|cC`FZ(|fjlceD?hcL+K2Wp z_C5RF*`EX13&dYs59H%Ou9vQtywXBxo+Nl~-#ocLyzRg_)cI-fFN_@jN&Yw9H`fnr1+Mqp z<|O?;d4AYs$dS?9(){7Q(bw`gW^G4ji}vXJjqc|j*wx;J1voC@^Bv~N$}IIUOSlCd z@ZSwRLo3HX|4IGH>pLjL;=hvW`IBz_%IhOgB>v!eTyg&-91rk+x4u{ZZJT4LK>Vu} zKP`W^{=u!iK@1g#pS&N(&)Fn1fj!SzEc;({vPtO-ay~ z{}eywU5(=%kN;;~NW(gP*R4hx5yf<~FV#y7hyNgN+sc?*?t9W*S?v z#=o4O*WIqsR`W|O*+yQ6`42YA{^b_&Lnj}8%zv=)Yh!CbALfUSq?c?_e)7Vu`hH*D z{I71U__S)&|D*Cx)Blfm4f|yI>6@Z#e}4Y&HK<c7n8GROxIBoWCfz^L$LMGV*6%g=+wkf1$>+VsxW{fX{+IUB?;#M`er?AO|26_$N71hp z&~HSHdc5RX#{XPvv@NJVC;cb>K{S}BH8?7`|F1V>jGVM{_CU#c+xqj(GuFG-J6Ts+ zU-MS&Prq;3mo7RVUaZ*V^>4TD{CFX58au9Y(D&AL-gV=%FIH=7pRax5zxS25w!V7N F`X7}OhS2~3 literal 27666 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 literal 27666 zcmeI4A$0Oe5QTG|ibNtG5{bkjk;tldPGuz$i$q3Zkw|20Boc{5B9VPJo$lTJXO=YO z50Dmea=JG=vy1|GVn^Vr>OK0(=w>jl)PC1J&oyC{l z=9ITN&}z2gc}1`lq7_8}Xsn@UQ#Hgw(NyFx4zq>*S0iP8*y>w8 zyWNgKATEv*27x9Pil!n<9CRBqNKV>pNTUPdL9;n`yR=uf_^do9CA#|9C!I6?urrj-6O2tdHlj93y#fXnhnM9JZei z$h>5W*?L7pc3dGAJ4UG?pTlu4`kZH2-$FiN_n-xf;-h?`hidH=CdGC|P-vxmY@8PI zQGI6G><)X;b;f0VfF)bKW~-Oq$_H?=e1o5M?Do1_A7BZS2Zz?j#`!_{12WUqa=f^Z zPYGu^X7c<>K0t&Q26e8x^;vGFA)MdJXR?StlaZ-WaU)Z3gpZw2s-}hWOZ5;rqju$h zLt>#oWw_3l&ydaY4dnxW8@Yvi!f`<>I5@;8_%=bDiG?B@`{#$yN8+PCcM}Um$mbL0 zBk@7n$QzCin6vm9+c*yk! zZIC(9Ey_oEzNYUl<$n6ukCXK9vG2#}Zk%q%X)#LkQMwtW>tVVYrprN^4bsIR znfH@fKbiKE*Ix3{OD5f9+)YN^WY|dtAA3JddTG*4lTK3ZDR%zm`7NP3jKk>qW8G}c zA1`<2^C%y+KA+<=so;}%KE34a27FYXqkQNi58*8w)LgLs{60SNhBV3t48tYpTKRL~ z{7Swxt>}!AGB-q2=Z_@GIX>YOy8)lxP1c|KeE5dq9G{!#PrKHi)9EBI$%i+3)=)(A zht^LqdVL?goQCCo9KIaNeX<`+c7w@wFfIn;d@$bhN9+D*)gLZl)4^ak_ZVA}1! zb^EW~{!6zv>GZ~(?x@opcDjSK(@#6Sa!fFQ z5m7!WSKl?CNy%q;hELz~nUPON`1G#FNA>yK`h$<{^duGv^1<6NZ1B9CPmTOBe6E;3 z9JPpZe8RPtSSZK`LF68H5ueKWRh2(?<`aH-3f}$D zJYVvG1D=6g&gbI!bw56`q>yBoHpral7UdK5tghs_8W+{)J!g%sKj)modeRfI-yIbq zI4hs9`8nM<76v?bMpdu+toRgJ{QoSeAUITU7E}E1fjmTHeQXe0!{Ib8?75;fYFvuX zz9`U2`P7L6GP~{Jck?-Hx4?BVpZV)1U+;;iW*h~-@w8z;b)s{JDmQ%o%;xzb`x`zW zvz!<6x6l7w@yqx~@>KJwxE4$sF4Xn{jZddW_R;95_C~@Yi0!lF&tbb`B3U0|p|H6@ zJ`mfYT!^esQ=?FDaM)C2+h<_eZSu`*9`aFhkXR^eoRAN6k?*ZfQ=_;gAFMgD>@>>< ztI#jtgWr=C98j|3V%ktxAC*5czrqJ-$jP6TKY)XemP{K8J9c8Bus%^fcsv^-`aygI z4z4M&P}s4DSYVBAmd|LGVV}&Gi%l-tHoS~jQ|piIkM#3pv79c~qKSpVwu;uMHT)bO zoCW_iU|sAW5J$DTJ0H~_baKAV-?C3QI3yMdJBq*LgR@}Ica7cA8q6QXXO(Y}@X}%V zNh}ms;)By6vU+mTs{Fy<1BPVo!UrpM`0%YId~lnR`^eq-NInCRJi@&@ALMg*z5bF< zof}znvHIPW#6l5Wqtseg(+6LH2p6TAtu8wkTOnugcDSi?5er3AktGiJfRfC(W+M{_ z1R`Vg!>fewy?N*$J{Qyw3&oX2fmdl)ii{QbN|C{nSSYS{E<{E;VK~SrxzHD%3kivN z1m^q}$_2Sm=j_BnQKwZSJ{TI}$S`pW#*n4Pjua;F1Xws@Yvk-WOPx3&7WiXh4TaQ) cKWU-}t)gk7c>06{h=n4wJ{b}V#gFFmKTI# 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

yn&xq-0^zxie%>GAR54p$jSG#QTe|zUa z${PQgi#_wdCO(Ie8ui9HXsq)`9>M$VHP};W@;_et=lSux+)-A~&-$^sR`Pi{dulQF ze~BKzA9Fb2o1*$SN+W-q-^lYg@HJXoeg5LN#de-k7~L`donrsO9dj?@JJhAk{;~gh z=ZzHh-6t)K_t?9A`HFf?(1UqHaKd-w)5uJgfPi5%}yNqfv|iup|u@O^pcZ}aBOgt?CJz9E9t z)l-lBB(EcrWu=N`QMMQJfb+AczVi=h@2TnUtO1)b6taFccXq=t4;U-vL&luEm={)s zLh^L!3VnD2-aEm&53c9$xg6Djn?X~|kIDS@al|}<4p$FPr>NKA{C6Bb;fQxU@qbC) zbt_Sv2Rt!&VEgv2cFTYl-JguEKd|1%Gi_`MF$hfxp=^4$^(=9t0{KzAnxxcfh9iM4gzk7E0(5!Y3r#;d0 zS80$*=-Y4D5Xl=--jMGFn8l7{jMxxtSds}556m@3FW9m?O0{2zx8 z8P40<6#0Hbh9cjQ^LO=orf+}FWBVEm?V9xn=NEE5ZIG6KTFdtzFsvWf$>lnC=Z*8Z zMV8g{e=I9*MxN|xR`r$%%>OTWvbz^sR^@S)m2)aj_U+?p>@n5${O-5UbKfdJITZ&y z+pPjVE9)-Wr}YG*wh%WQ6*Zdvtsi{gen zID>b5&RyUb4cCl7d8?ZBbz*|moYOFapD!_VlV*@9QCyQ*yhm{Cn$@jM_x4@dKi=t{ MC)&2}*ruWN|Fl$Wz5oCK delta 915 zcmZvaQAkr^6vywKn#(Ljx7g}pb1WOCLrrYi3Y9@3J}g-@%*L(EEEX+mqU7o(RuV?( z(WnS93yB31o){r!Jw)_S;*^{g!|JVN8ca)-3|_1#s9~tVscl{c zH@XVzHJG$FGL&Jl!^cp96Wap}PAuBd!r;IOC&8mZ8`_Iy4aRr2GFY&nv|WQyS4hm! zYnN2CmYo+(DW;G}B=*uDSTJ7h|4+)Uh`3=*3f`}bh?)9^=Bn<0labwPCgwfS)w~r7 zrxUCguWk|3Xo6->RD+Ry(R|H0s5?zbF#DsTkq@E^exh^<!VV{e)Uy3CCNLU~i++tIar->`KvT z6`UA5L;G+GT_LrXl{k4;1vgflQ~T|~sc;R)c(JO(!%&aY7u3h$!~KyGcKkTosX_qj zx@_#U;=67OLkJr#nHa)2*JEVpdE9iFwGS4q@T(nw;MEn #include -#include +#include #include +#include typedef quint32 uint; typedef quint16 ushort; typedef quint8 uchar; +#ifdef QT_DEBUG +Q_LOGGING_CATEGORY(LOG_TGAPLUGIN, "kf.imageformats.plugins.tga", QtDebugMsg) +#else +Q_LOGGING_CATEGORY(LOG_TGAPLUGIN, "kf.imageformats.plugins.tga", QtWarningMsg) +#endif + +#ifndef TGA_V2E_AS_DEFAULT +/* + * Uncomment to change the default version of the plugin to `TGAv2E`. + */ +// #define TGA_V2E_AS_DEFAULT +#endif // TGA_V2E_AS_DEFAULT + namespace // Private. { // Header format of saved files. -uchar targaMagic[12] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - enum TGAType { TGA_TYPE_INDEXED = 1, TGA_TYPE_RGB = 2, @@ -58,6 +72,16 @@ enum TGAType { #define TGA_ORIGIN_LOWER 0x00 #define TGA_ORIGIN_UPPER 0x20 +/* + * Each TAG is a SHORT value in the range of 0 to 65535. Values from 0 - 32767 are available + * for developer use, while values from 32768 - 65535 are reserved for Truevision. + * Truevision will maintain a list of tags assigned to companies. + * In any case, there's no public "list of tag" and Truevision no longer exists. + */ +#define TGA_EXIF_TAGID 0x7001 // Exif data preceded by "eXif" string +#define TGA_XMPP_TAGID 0x7002 // Xmp packet preceded by "xMPP" string +#define TGA_ICCP_TAGID 0x7003 // Icc profile preceded by "iCCP" string + /** Tga Header. */ struct TgaHeader { uchar id_length = 0; @@ -78,6 +102,149 @@ struct TgaHeader { }; // const static int SIZE = 18; }; +/** Tga 2.0 Footer */ +struct TgaFooter { + TgaFooter() + : extensionOffset(0) + , developerOffset(0) + { + std::memcpy(signature, "TRUEVISION-XFILE.\0", 18); + } + bool isValid() const + { + return std::memcmp(signature, "TRUEVISION-XFILE.\0", 18) == 0; + } + + quint32 extensionOffset; // Extension Area Offset + quint32 developerOffset; // Developer Directory Offset + char signature[18]; // TGA Signature +}; + +/** Tga 2.0 extension area */ +struct TgaExtension { + enum AttributeType : quint16 { + NoAlpha = 0, // no Alpha data included (bits 3-0 of TgaHeader::flags should also be set to zero). + IgnoreAlpha = 1, // undefined data in the Alpha field, can be ignored + RetainAlpha = 2, // undefined data in the Alpha field, but should be retained + Alpha = 3, // useful Alpha channel data is present + PremultipliedAlpha = 4 // pre-multiplied Alpha (see description below) + }; + + TgaExtension() + { + std::memset(this, 0, sizeof(TgaExtension)); + size = 495; // TGA 2.0 specs + + // If you do not use Software Version field, set the SHORT to binary + // zero, and the BYTE to a space (' '). + versionLetter = 0x20; + } + + bool isValid() const + { + return size == 495; + } + + void setDateTime(const QDateTime &dt) + { + if (dt.isValid()) { + auto date = dt.date(); + stampMonth = date.month(); + stampDay = date.day(); + stampYear = date.year(); + auto time = dt.time(); + stampHour = time.hour(); + stampMinute = time.minute(); + stampSecond = time.second(); + } + } + QDateTime dateTime() const + { + auto date = QDate(stampYear, stampMonth, stampDay); + auto time = QTime(stampHour, stampMinute, stampSecond); + if (!date.isValid() || !time.isValid()) + return {}; + return QDateTime(date, time); + } + + void setAuthor(const QString &str) + { + auto ba = str.toLatin1(); + std::memcpy(authorName, ba.data(), std::min(sizeof(authorName) - 1, size_t(ba.size()))); + } + QString author() const + { + if (authorName[sizeof(authorName) - 1] != char(0)) + return {}; + return QString::fromLatin1(authorName); + } + + void setComment(const QString &str) + { + auto ba = str.toLatin1(); + std::memcpy(authorComment, ba.data(), std::min(sizeof(authorComment) - 1, size_t(ba.size()))); + } + QString comment() const + { + if (authorComment[sizeof(authorComment) - 1] != char(0)) + return {}; + return QString::fromLatin1(authorComment); + } + + void setSoftware(const QString &str) + { + auto ba = str.toLatin1(); + std::memcpy(softwareId, ba.data(), std::min(sizeof(softwareId) - 1, size_t(ba.size()))); + } + QString software() const + { + if (softwareId[sizeof(softwareId) - 1] != char(0)) + return {}; + return QString::fromLatin1(softwareId); + } + + quint16 size; // Extension Size + char authorName[41]; // Author Name + char authorComment[324]; // Author Comment + quint16 stampMonth; // Date/Time Stamp: Month + quint16 stampDay; // Date/Time Stamp: Day + quint16 stampYear; // Date/Time Stamp: Year + quint16 stampHour; // Date/Time Stamp: Hour + quint16 stampMinute; // Date/Time Stamp: Minute + quint16 stampSecond; // Date/Time Stamp: Second + char jobName[41]; // Job Name/ID + quint16 jobHour; // Job Time: Hours + quint16 jobMinute; // Job Time: Minutes + quint16 jobSecond; // Job Time: Seconds + char softwareId[41]; // Software ID + quint16 versionNumber; // Software Version Number + quint8 versionLetter; // Software Version Letter + quint32 keyColor; // Key Color + quint16 pixelNumerator; // Pixel Aspect Ratio + quint16 pixelDenominator; // Pixel Aspect Ratio + quint16 gammaNumerator; // Gamma Value + quint16 gammaDenominator; // Gamma Value + quint32 colorOffset; // Color Correction Offset + quint32 stampOffset; // Postage Stamp Offset + quint32 scanOffset; // Scan-Line Table Offset + quint8 attributesType; // Attributes Types +}; + +struct TgaDeveloperDirectory { + struct Field { + quint16 tagId; + quint32 offset; + quint32 size; + }; + + bool isEmpty() const + { + return fields.isEmpty(); + } + + QList fields; +}; + static QDataStream &operator>>(QDataStream &s, TgaHeader &head) { s >> head.id_length; @@ -95,6 +262,107 @@ static QDataStream &operator>>(QDataStream &s, TgaHeader &head) return s; } +static QDataStream &operator>>(QDataStream &s, TgaFooter &footer) +{ + s >> footer.extensionOffset; + s >> footer.developerOffset; + s.readRawData(footer.signature, sizeof(footer.signature)); + return s; +} + +static QDataStream &operator<<(QDataStream &s, const TgaFooter &footer) +{ + s << footer.extensionOffset; + s << footer.developerOffset; + s.writeRawData(footer.signature, sizeof(footer.signature)); + return s; +} + +static QDataStream &operator>>(QDataStream &s, TgaDeveloperDirectory &dir) +{ + quint16 n; + s >> n; + for (auto i = n; i > 0; --i) { + TgaDeveloperDirectory::Field f; + s >> f.tagId; + s >> f.offset; + s >> f.size; + dir.fields << f; + } + return s; +} + +static QDataStream &operator<<(QDataStream &s, const TgaDeveloperDirectory &dir) +{ + s << quint16(dir.fields.size()); + for (auto &&f : dir.fields) { + s << f.tagId; + s << f.offset; + s << f.size; + } + return s; +} + +static QDataStream &operator>>(QDataStream &s, TgaExtension &ext) +{ + s >> ext.size; + s.readRawData(ext.authorName, sizeof(ext.authorName)); + s.readRawData(ext.authorComment, sizeof(ext.authorComment)); + s >> ext.stampMonth; + s >> ext.stampDay; + s >> ext.stampYear; + s >> ext.stampHour; + s >> ext.stampMinute; + s >> ext.stampSecond; + s.readRawData(ext.jobName, sizeof(ext.jobName)); + s >> ext.jobHour; + s >> ext.jobMinute; + s >> ext.jobSecond; + s.readRawData(ext.softwareId, sizeof(ext.softwareId)); + s >> ext.versionNumber; + s >> ext.versionLetter; + s >> ext.keyColor; + s >> ext.pixelNumerator; + s >> ext.pixelDenominator; + s >> ext.gammaNumerator; + s >> ext.gammaDenominator; + s >> ext.colorOffset; + s >> ext.stampOffset; + s >> ext.scanOffset; + s >> ext.attributesType; + return s; +} + +static QDataStream &operator<<(QDataStream &s, const TgaExtension &ext) +{ + s << ext.size; + s.writeRawData(ext.authorName, sizeof(ext.authorName)); + s.writeRawData(ext.authorComment, sizeof(ext.authorComment)); + s << ext.stampMonth; + s << ext.stampDay; + s << ext.stampYear; + s << ext.stampHour; + s << ext.stampMinute; + s << ext.stampSecond; + s.writeRawData(ext.jobName, sizeof(ext.jobName)); + s << ext.jobHour; + s << ext.jobMinute; + s << ext.jobSecond; + s.writeRawData(ext.softwareId, sizeof(ext.softwareId)); + s << ext.versionNumber; + s << ext.versionLetter; + s << ext.keyColor; + s << ext.pixelNumerator; + s << ext.pixelDenominator; + s << ext.gammaNumerator; + s << ext.gammaDenominator; + s << ext.colorOffset; + s << ext.stampOffset; + s << ext.scanOffset; + s << ext.attributesType; + return s; +} + static bool IsSupported(const TgaHeader &head) { if (head.image_type != TGA_TYPE_INDEXED && head.image_type != TGA_TYPE_RGB && head.image_type != TGA_TYPE_GREY && head.image_type != TGA_TYPE_RLE_INDEXED @@ -106,8 +374,7 @@ static bool IsSupported(const TgaHeader &head) if (head.pixel_size > 8 || head.colormap_type != 1) { return false; } - // colormap_size == 16 would be ARRRRRGG GGGBBBBB but we don't support that. - if (head.colormap_size != 24 && head.colormap_size != 32) { + if (head.colormap_size != 15 && head.colormap_size != 16 && head.colormap_size != 24 && head.colormap_size != 32) { return false; } } @@ -119,7 +386,7 @@ static bool IsSupported(const TgaHeader &head) if (head.width == 0 || head.height == 0) { return false; } - if (head.pixel_size != 8 && head.pixel_size != 16 && head.pixel_size != 24 && head.pixel_size != 32) { + if (head.pixel_size != 8 && head.pixel_size != 15 && head.pixel_size != 16 && head.pixel_size != 24 && head.pixel_size != 32) { return false; } // If the colormap_type field is set to zero, indicating that no color map exists, then colormap_index and colormap_length should be set to zero. @@ -130,11 +397,17 @@ static bool IsSupported(const TgaHeader &head) return true; } -struct Color555 { - ushort b : 5; - ushort g : 5; - ushort r : 5; -}; +/*! + * \brief imageId + * Create the TGA imageId from the image TITLE metadata + */ +static QByteArray imageId(const QImage &img) +{ + auto ba = img.text(QStringLiteral(META_KEY_TITLE)).trimmed().toLatin1(); + if (ba.size() > 255) + ba = ba.left(255); + return ba; +} struct TgaHeaderInfo { bool rle; @@ -202,6 +475,8 @@ static QImage::Format imageFormat(const TgaHeader &head) format = QImage::Format_Grayscale8; } else if (info.pal) { format = QImage::Format_Indexed8; + } else if (info.rgb && (head.pixel_size == 15 || head.pixel_size == 16)) { + format = QImage::Format_RGB555; } else { format = QImage::Format_RGB32; } @@ -305,23 +580,30 @@ static QByteArray readTgaLine(QIODevice *dev, qint32 pixel_size, qint32 size, bo return data; } +inline QRgb rgb555ToRgb(char c0, char c1) +{ + // c0 = GGGBBBBB + // c1 = IRRRRRGG (I = interrupt control of VDA(D) -> ignore it) + return qRgb(int((c1 >> 2) & 0x1F) * 255 / 31, int(((c1 & 3) << 3) | ((c0 >> 5) & 7)) * 255 / 31, int(c0 & 0x1F) * 255 / 31); +} + static bool LoadTGA(QIODevice *dev, const TgaHeader &tga, QImage &img) { img = imageAlloc(tga.width, tga.height, imageFormat(tga)); if (img.isNull()) { - qWarning() << "LoadTGA: Failed to allocate image, invalid dimensions?" << QSize(tga.width, tga.height); + qCWarning(LOG_TGAPLUGIN) << "LoadTGA: Failed to allocate image, invalid dimensions?" << QSize(tga.width, tga.height); return false; } TgaHeaderInfo info(tga); - const int numAlphaBits = tga.flags & 0xf; - bool hasAlpha = img.hasAlphaChannel(); - qint32 pixel_size = (tga.pixel_size / 8); + const int numAlphaBits = qBound(0, tga.flags & 0xf, 8); + bool hasAlpha = img.hasAlphaChannel() && numAlphaBits > 0; + qint32 pixel_size = (tga.pixel_size == 15 ? 16 : tga.pixel_size) / 8; qint32 line_size = qint32(tga.width) * pixel_size; qint64 size = qint64(tga.height) * line_size; if (size < 1) { - // qDebug() << "This TGA file is broken with size " << size; + // qCDebug(LOG_TGAPLUGIN) << "This TGA file is broken with size " << size; return false; } @@ -334,8 +616,8 @@ static bool LoadTGA(QIODevice *dev, const TgaHeader &tga, QImage &img) colorTable.resizeForOverwrite(tga.colormap_length); #endif - if (tga.colormap_size == 32) { // BGRA. - char data[4]; + if (tga.colormap_size == 32) { + char data[4]; // BGRA for (QRgb &rgb : colorTable) { const auto dataRead = dev->read(data, 4); if (dataRead < 4) { @@ -344,8 +626,8 @@ static bool LoadTGA(QIODevice *dev, const TgaHeader &tga, QImage &img) // BGRA. rgb = qRgba(data[2], data[1], data[0], data[3]); } - } else if (tga.colormap_size == 24) { // BGR. - char data[3]; + } else if (tga.colormap_size == 24) { + char data[3]; // BGR for (QRgb &rgb : colorTable) { const auto dataRead = dev->read(data, 3); if (dataRead < 3) { @@ -354,7 +636,15 @@ static bool LoadTGA(QIODevice *dev, const TgaHeader &tga, QImage &img) // BGR. rgb = qRgb(data[2], data[1], data[0]); } - // TODO tga.colormap_size == 16 ARRRRRGG GGGBBBBB + } else if (tga.colormap_size == 16 || tga.colormap_size == 15) { + char data[2]; + for (QRgb &rgb : colorTable) { + const auto dataRead = dev->read(data, 2); + if (dataRead < 2) { + return false; + } + rgb = rgb555ToRgb(data[0], data[1]); + } } else { return false; } @@ -364,24 +654,28 @@ static bool LoadTGA(QIODevice *dev, const TgaHeader &tga, QImage &img) // Convert image to internal format. bool valid = true; - int y_start; - int y_step; - int y_end; + int y_start = tga.height - 1; + int y_step = -1; + int y_end = -1; if (tga.flags & TGA_ORIGIN_UPPER) { y_start = 0; y_step = 1; y_end = tga.height; - } else { - y_start = tga.height - 1; - y_step = -1; - y_end = -1; + } + int x_start = 0; + int x_step = 1; + int x_end = tga.width; + if (tga.flags & TGA_ORIGIN_RIGHT) { + x_start = tga.width - 1; + x_step = -1; + x_end = -1; } QByteArray cache; for (int y = y_start; y != y_end; y += y_step) { auto tgaLine = readTgaLine(dev, pixel_size, line_size, info.rle, cache); if (tgaLine.size() != qsizetype(line_size)) { - qWarning() << "LoadTGA: Error while decoding a TGA raw line"; + qCWarning(LOG_TGAPLUGIN) << "LoadTGA: Error while decoding a TGA raw line"; valid = false; break; } @@ -389,7 +683,7 @@ static bool LoadTGA(QIODevice *dev, const TgaHeader &tga, QImage &img) if (info.pal && img.depth() == 8) { // Paletted. auto scanline = img.scanLine(y); - for (int x = 0; x < tga.width; x++) { + for (int x = x_start; x != x_end; x += x_step) { uchar idx = *src++; if (Q_UNLIKELY(idx >= tga.colormap_length)) { valid = false; @@ -400,13 +694,13 @@ static bool LoadTGA(QIODevice *dev, const TgaHeader &tga, QImage &img) } else if (info.grey) { if (tga.pixel_size == 16 && img.depth() == 32) { // Greyscale with alpha. auto scanline = reinterpret_cast(img.scanLine(y)); - for (int x = 0; x < tga.width; x++) { + for (int x = x_start; x != x_end; x += x_step) { scanline[x] = qRgba(*src, *src, *src, *(src + 1)); src += 2; } } else if (tga.pixel_size == 8 && img.depth() == 8) { // Greyscale. auto scanline = img.scanLine(y); - for (int x = 0; x < tga.width; x++) { + for (int x = x_start; x != x_end; x += x_step) { scanline[x] = *src; src++; } @@ -415,25 +709,25 @@ static bool LoadTGA(QIODevice *dev, const TgaHeader &tga, QImage &img) break; } } else { - auto scanline = reinterpret_cast(img.scanLine(y)); // True Color. - if (tga.pixel_size == 16 && img.depth() == 16) { - for (int x = 0; x < tga.width; x++) { - Color555 c = *reinterpret_cast(src); - scanline[x] = qRgb((c.r << 3) | (c.r >> 2), (c.g << 3) | (c.g >> 2), (c.b << 3) | (c.b >> 2)); + if ((tga.pixel_size == 15 || tga.pixel_size == 16) && img.depth() == 16) { + auto scanline = reinterpret_cast(img.scanLine(y)); + for (int x = x_start; x != x_end; x += x_step) { + scanline[x] = ((quint16(src[1] & 0x7f) << 8) | quint8(src[0])); src += 2; } } else if (tga.pixel_size == 24 && img.depth() == 32) { - for (int x = 0; x < tga.width; x++) { + auto scanline = reinterpret_cast(img.scanLine(y)); + for (int x = x_start; x != x_end; x += x_step) { scanline[x] = qRgb(src[2], src[1], src[0]); src += 3; } } else if (tga.pixel_size == 32 && img.depth() == 32) { + auto scanline = reinterpret_cast(img.scanLine(y)); auto div = (1 << numAlphaBits) - 1; if (div == 0) hasAlpha = false; - for (int x = 0; x < tga.width; x++) { - // ### TODO: verify with images having really some alpha data + for (int x = x_start; x != x_end; x += x_step) { const int alpha = hasAlpha ? int((src[3]) << (8 - numAlphaBits)) * 255 / div : 255; scanline[x] = qRgba(src[2], src[1], src[0], alpha); src += 4; @@ -445,11 +739,9 @@ static bool LoadTGA(QIODevice *dev, const TgaHeader &tga, QImage &img) } } -#ifdef QT_DEBUG if (!cache.isEmpty() && valid) { - qDebug() << "LoadTGA: Found unused image data"; + qCDebug(LOG_TGAPLUGIN) << "LoadTGA: Found unused image data"; } -#endif return valid; } @@ -459,10 +751,32 @@ static bool LoadTGA(QIODevice *dev, const TgaHeader &tga, QImage &img) class TGAHandlerPrivate { public: - TGAHandlerPrivate() {} + TGAHandlerPrivate() +#ifdef TGA_V2E_AS_DEFAULT + : m_subType(subTypeTGA_V2E()) +#else + : m_subType(subTypeTGA_V2S()) +#endif + { + } ~TGAHandlerPrivate() {} + static QByteArray subTypeTGA_V1() + { + return QByteArrayLiteral("TGAv1"); + } + static QByteArray subTypeTGA_V2S() + { + return QByteArrayLiteral("TGAv2"); + } + static QByteArray subTypeTGA_V2E() + { + return QByteArrayLiteral("TGAv2E"); + } + TgaHeader m_header; + + QByteArray m_subType; }; TGAHandler::TGAHandler() @@ -482,31 +796,43 @@ bool TGAHandler::canRead() const bool TGAHandler::read(QImage *outImage) { - // qDebug() << "Loading TGA file!"; + // qCDebug(LOG_TGAPLUGIN) << "Loading TGA file!"; auto dev = device(); auto&& tga = d->m_header; if (!peekHeader(dev, tga) || !IsSupported(tga)) { - // qDebug() << "This TGA file is not valid."; + // qCDebug(LOG_TGAPLUGIN) << "This TGA file is not valid."; return false; } + QByteArray imageId; if (dev->isSequential()) { - dev->read(TgaHeader::SIZE + tga.id_length); + auto tmp = dev->read(TgaHeader::SIZE); + if (tmp.size() != TgaHeader::SIZE) + return false; } else { - dev->seek(TgaHeader::SIZE + tga.id_length); + if (!dev->seek(TgaHeader::SIZE)) + return false; + } + if (tga.id_length > 0) { + imageId = dev->read(tga.id_length); } // Check image file format. if (dev->atEnd()) { - // qDebug() << "This TGA file is not valid."; + // qCDebug(LOG_TGAPLUGIN) << "This TGA file is not valid."; return false; } QImage img; if (!LoadTGA(dev, tga, img)) { - // qDebug() << "Error loading TGA file."; + // qCDebug(LOG_TGAPLUGIN) << "Error loading TGA file."; return false; + } else if (!imageId.isEmpty()) { + img.setText(QStringLiteral(META_KEY_TITLE), QString::fromLatin1(imageId)); + } + if (!readMetadata(img)) { + qCDebug(LOG_TGAPLUGIN) << "read: error while reading metadata"; } *outImage = img; @@ -515,163 +841,434 @@ bool TGAHandler::read(QImage *outImage) bool TGAHandler::write(const QImage &image) { - if (image.format() == QImage::Format_Indexed8) - return writeIndexed(image); - if (image.format() == QImage::Format_Grayscale8 || image.format() == QImage::Format_Grayscale16) - return writeGrayscale(image); - return writeRGBA(image); + auto ok = false; + if (image.format() == QImage::Format_Indexed8) { + ok = writeIndexed(image); + } else if (image.format() == QImage::Format_Grayscale8 || image.format() == QImage::Format_Grayscale16) { + ok = writeGrayscale(image); + } else if (image.format() == QImage::Format_RGB555 || image.format() == QImage::Format_RGB16 || image.format() == QImage::Format_RGB444) { + ok = writeRGB555(image); + } else { + ok = writeRGBA(image); + } + return (ok && writeMetadata(image)); } bool TGAHandler::writeIndexed(const QImage &image) { - QDataStream s(device()); - s.setByteOrder(QDataStream::LittleEndian); + auto dev = device(); + { // write header and palette + QDataStream s(dev); + s.setByteOrder(QDataStream::LittleEndian); - QImage img(image); - auto ct = img.colorTable(); + auto ct = image.colorTable(); + auto iid = imageId(image); + s << quint8(iid.size()); // 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 << 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(image.width()); // Image Width + s << quint16(image.height()); // Image Height + s << quint8(8); // Pixel Depth + s << quint8(TGA_ORIGIN_UPPER + TGA_ORIGIN_LEFT); // Image Descriptor - s << quint16(img.width()); // Image Width - s << quint16(img.height()); // Image Height - s << quint8(8); // Pixel Depth - s << quint8(TGA_ORIGIN_UPPER + TGA_ORIGIN_LEFT); // Image Descriptor + if (!iid.isEmpty()) + s.writeRawData(iid.data(), iid.size()); - 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); + 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, h = image.height(), w = image.width(); y < h; y++) { + auto ptr = reinterpret_cast(image.constScanLine(y)); + if (dev->write(ptr, w) != w) { + return false; + } + } + return true; } bool TGAHandler::writeGrayscale(const QImage &image) { - QDataStream s(device()); - s.setByteOrder(QDataStream::LittleEndian); + auto dev = device(); + { // write header + QDataStream s(dev); + s.setByteOrder(QDataStream::LittleEndian); - QImage img(image); - if (img.format() != QImage::Format_Grayscale8) { - img = img.convertToFormat(QImage::Format_Grayscale8); - } - if (img.isNull()) { - qCritical() << "TGAHandler::writeGrayscale: image conversion to 8 bits grayscale failed!"; - return false; - } + auto iid = imageId(image); + s << quint8(iid.size()); // ID Length + s << quint8(0); // Color Map Type + s << quint8(TGA_TYPE_GREY); // Image Type + s << quint16(0); // First Entry Index + s << quint16(0); // Color Map Length + s << quint8(0); // Color map Entry Size + s << quint16(0); // X-origin of Image + s << quint16(0); // Y-origin of Image - s << quint8(0); // ID Length - s << quint8(0); // Color Map Type - s << quint8(TGA_TYPE_GREY); // Image Type - s << quint16(0); // First Entry Index - s << quint16(0); // Color Map Length - s << quint8(0); // Color map Entry Size - s << quint16(0); // X-origin of Image - s << quint16(0); // Y-origin of Image + s << quint16(image.width()); // Image Width + s << quint16(image.height()); // Image Height + s << quint8(8); // Pixel Depth + s << quint8(TGA_ORIGIN_UPPER + TGA_ORIGIN_LEFT); // Image Descriptor - s << quint16(img.width()); // Image Width - s << quint16(img.height()); // Image Height - s << quint8(8); // Pixel Depth - s << quint8(TGA_ORIGIN_UPPER + TGA_ORIGIN_LEFT); // Image Descriptor + if (!iid.isEmpty()) + s.writeRawData(iid.data(), iid.size()); - 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; } } + ScanLineConverter scl(QImage::Format_Grayscale8); + for (int y = 0, h = image.height(), w = image.width(); y < h; y++) { + auto ptr = reinterpret_cast(scl.convertedScanLine(image, y)); + if (dev->write(ptr, w) != w) { + return false; + } + } + + return true; +} + +bool TGAHandler::writeRGB555(const QImage &image) +{ + auto dev = device(); + { // write header + QDataStream s(dev); + s.setByteOrder(QDataStream::LittleEndian); + + auto iid = imageId(image); + for (char c : {int(iid.size()), 0, int(TGA_TYPE_RGB), 0, 0, 0, 0, 0, 0, 0, 0, 0}) { + s << c; + } + s << quint16(image.width()); // width + s << quint16(image.height()); // height + s << quint8(16); // depth + s << quint8(TGA_ORIGIN_UPPER + TGA_ORIGIN_LEFT); + + if (!iid.isEmpty()) + s.writeRawData(iid.data(), iid.size()); + + if (s.status() != QDataStream::Ok) { + return false; + } + } + + ScanLineConverter scl(QImage::Format_RGB555); + QByteArray ba(image.width() * 2, char()); + for (int y = 0, h = image.height(); y < h; y++) { + auto ptr = reinterpret_cast(scl.convertedScanLine(image, y)); + for (int x = 0, w = image.width(); x < w; x++) { + auto color = *(ptr + x); + ba[x * 2] = char(color); + ba[x * 2 + 1] = char(color >> 8); + } + if (dev->write(ba.data(), ba.size()) != qint64(ba.size())) { + return false; + } + } + return true; } bool TGAHandler::writeRGBA(const QImage &image) { - QDataStream s(device()); - s.setByteOrder(QDataStream::LittleEndian); - - QImage img(image); - const bool hasAlpha = img.hasAlphaChannel(); + auto format = image.format(); + const bool hasAlpha = image.hasAlphaChannel(); #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0) auto cs = image.colorSpace(); + auto tcs = QColorSpace(); if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) { - img = image.convertedToColorSpace(QColorSpace(QColorSpace::SRgb), QImage::Format_RGB32); - } else if (hasAlpha && img.format() != QImage::Format_ARGB32) { + format = QImage::Format_RGB32; + tcs = QColorSpace(QColorSpace::SRgb); + } else if (hasAlpha && image.format() != QImage::Format_ARGB32) { #else - if (hasAlpha && img.format() != QImage::Format_ARGB32) { + if (hasAlpha && image.format() != QImage::Format_ARGB32) { #endif - img = img.convertToFormat(QImage::Format_ARGB32); - } else if (!hasAlpha && img.format() != QImage::Format_RGB32) { - img = img.convertToFormat(QImage::Format_RGB32); - } - if (img.isNull()) { - qCritical() << "TGAHandler::writeRGBA: image conversion to 32 bits failed!"; - return false; - } - static constexpr quint8 originTopLeft = TGA_ORIGIN_UPPER + TGA_ORIGIN_LEFT; // 0x20 - static constexpr quint8 alphaChannel8Bits = 0x08; - - for (int i = 0; i < 12; i++) { - s << targaMagic[i]; + format = QImage::Format_ARGB32; + } else if (!hasAlpha && image.format() != QImage::Format_RGB32) { + format = QImage::Format_RGB32; } - // write header - s << quint16(img.width()); // width - s << quint16(img.height()); // height - 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) + auto dev = device(); + { // write header + QDataStream s(dev); + s.setByteOrder(QDataStream::LittleEndian); - if (s.status() != QDataStream::Ok) { - return false; - } + const quint8 originTopLeft = TGA_ORIGIN_UPPER + TGA_ORIGIN_LEFT; // 0x20 + const quint8 alphaChannel8Bits = 0x08; - for (int y = 0; y < img.height(); y++) { - auto ptr = reinterpret_cast(img.constScanLine(y)); - for (int x = 0; x < img.width(); x++) { - auto color = *(ptr + x); - s << quint8(qBlue(color)); - s << quint8(qGreen(color)); - s << quint8(qRed(color)); - if (hasAlpha) { - s << quint8(qAlpha(color)); - } + auto iid = imageId(image); + for (char c : {int(iid.size()), 0, int(TGA_TYPE_RGB), 0, 0, 0, 0, 0, 0, 0, 0, 0}) { + s << c; } + s << quint16(image.width()); // width + s << quint16(image.height()); // height + 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) + + if (!iid.isEmpty()) + s.writeRawData(iid.data(), iid.size()); + if (s.status() != QDataStream::Ok) { return false; } } + ScanLineConverter scl(format); + if (tcs.isValid()) { + scl.setTargetColorSpace(tcs); + } + auto mul = hasAlpha ? 4 : 3; + QByteArray ba(image.width() * mul, char()); + for (int y = 0, h = image.height(); y < h; y++) { + auto ptr = reinterpret_cast(scl.convertedScanLine(image, y)); + for (int x = 0, w = image.width(); x < w; x++) { + auto color = *(ptr + x); + auto xmul = x * mul; + ba[xmul] = char(qBlue(color)); + ba[xmul + 1] = char(qGreen(color)); + ba[xmul + 2] = char(qRed(color)); + if (hasAlpha) { + ba[xmul + 3] = char(qAlpha(color)); + } + } + if (dev->write(ba.data(), ba.size()) != qint64(ba.size())) { + return false; + } + } + return true; } +bool TGAHandler::writeMetadata(const QImage &image) +{ + if (d->m_subType == TGAHandlerPrivate::subTypeTGA_V1()) { + return true; // TGA V1 does not have these data + } + + auto dev = device(); + if (dev == nullptr) { + return false; + } + if (dev->isSequential()) { + qCInfo(LOG_TGAPLUGIN) << "writeMetadata: unable to save metadata on a sequential device"; + return true; + } + + QDataStream s(dev); + s.setByteOrder(QDataStream::LittleEndian); + + // TGA 2.0 footer + TgaFooter foot; + + // 32-bit overflow check (rough check) + // I need at least 495 (extension) + 26 (footer) bytes -> 1024 bytes. + // for the development area I roughly estimate 4096 KiB (profile, exif and xmp) they should always be less. + auto reqBytes = qint64(d->m_subType == TGAHandlerPrivate::subTypeTGA_V2E() ? 4096 * 1024 : 1024); + if (dev->pos() > std::numeric_limits::max() - reqBytes) { + qCInfo(LOG_TGAPLUGIN) << "writeMetadata: there is no enough space for metadata"; + return true; + } + + // TGA 2.0 developer area + TgaDeveloperDirectory dir; + if (d->m_subType == TGAHandlerPrivate::subTypeTGA_V2E()) { + auto exif = MicroExif::fromImage(image); + if (!exif.isEmpty()) { + auto ba = QByteArray("eXif").append(exif.toByteArray(s.byteOrder())); + TgaDeveloperDirectory::Field f; + f.tagId = TGA_EXIF_TAGID; + f.offset = dev->pos(); + f.size = ba.size(); + if (s.writeRawData(ba.data(), ba.size()) != ba.size()) { + return false; + } + dir.fields << f; + } + auto icc = image.colorSpace().iccProfile(); + if (!icc.isEmpty()) { + auto ba = QByteArray("iCCP").append(icc); + TgaDeveloperDirectory::Field f; + f.tagId = TGA_ICCP_TAGID; + f.offset = dev->pos(); + f.size = ba.size(); + if (s.writeRawData(ba.data(), ba.size()) != ba.size()) { + return false; + } + dir.fields << f; + } + auto xmp = image.text(QStringLiteral(META_KEY_XMP_ADOBE)).trimmed(); + if (!xmp.isEmpty()) { + auto ba = QByteArray("xMPP").append(xmp.toUtf8()); + TgaDeveloperDirectory::Field f; + f.tagId = TGA_XMPP_TAGID; + f.offset = dev->pos(); + f.size = ba.size(); + if (s.writeRawData(ba.data(), ba.size()) != ba.size()) { + return false; + } + dir.fields << f; + } + } + + // TGA 2.0 extension area + TgaExtension ext; + ext.setDateTime(QDateTime::currentDateTimeUtc()); + if (image.hasAlphaChannel()) { + ext.attributesType = TgaExtension::Alpha; + } + auto keys = image.textKeys(); + for (auto &&key : keys) { + if (!key.compare(QStringLiteral(META_KEY_AUTHOR), Qt::CaseInsensitive)) { + ext.setAuthor(image.text(key)); + continue; + } + if (!key.compare(QStringLiteral(META_KEY_COMMENT), Qt::CaseInsensitive)) { + ext.setComment(image.text(key)); + continue; + } + if (!key.compare(QStringLiteral(META_KEY_DESCRIPTION), Qt::CaseInsensitive)) { + if (ext.comment().isEmpty()) + ext.setComment(image.text(key)); + continue; + } + if (!key.compare(QStringLiteral(META_KEY_SOFTWARE), Qt::CaseInsensitive)) { + ext.setSoftware(image.text(key)); + continue; + } + } + + // write developer area + if (!dir.isEmpty()) { + foot.developerOffset = dev->pos(); + s << dir; + } + + // write extension area (date time is always set) + foot.extensionOffset = dev->pos(); + s << ext; + s << foot; + + return s.status() == QDataStream::Ok; +} + +bool TGAHandler::readMetadata(QImage &image) +{ + auto dev = device(); + if (dev == nullptr) { + return false; + } + if (dev->isSequential()) { + qCInfo(LOG_TGAPLUGIN) << "readMetadata: unable to load metadata on a sequential device"; + return true; + } + + // read TGA footer + if (!dev->seek(dev->size() - 26)) { + return false; + } + + QDataStream s(dev); + s.setByteOrder(QDataStream::LittleEndian); + + TgaFooter foot; + s >> foot; + if (s.status() != QDataStream::Ok) { + return false; + } + if (!foot.isValid()) { + return true; // not a TGA 2.0 -> no metadata are present + } + + if (foot.extensionOffset > 0) { + // read the extension area + if (!dev->seek(foot.extensionOffset)) { + return false; + } + + TgaExtension ext; + s >> ext; + if (s.status() != QDataStream::Ok || !ext.isValid()) { + return false; + } + + auto dt = ext.dateTime(); + if (dt.isValid()) { + image.setText(QStringLiteral(META_KEY_MODIFICATIONDATE), dt.toString(Qt::ISODate)); + } + auto au = ext.author(); + if (!au.isEmpty()) { + image.setText(QStringLiteral(META_KEY_AUTHOR), au); + } + auto cm = ext.comment(); + if (!cm.isEmpty()) { + image.setText(QStringLiteral(META_KEY_COMMENT), cm); + } + auto sw = ext.software(); + if (!sw.isEmpty()) { + image.setText(QStringLiteral(META_KEY_SOFTWARE), sw); + } + } + + if (foot.developerOffset > 0) { + // read developer area + if (!dev->seek(foot.developerOffset)) { + return false; + } + + TgaDeveloperDirectory dir; + s >> dir; + if (s.status() != QDataStream::Ok) { + return false; + } + + for (auto &&f : dir.fields) { + if (!dev->seek(f.offset)) { + return false; + } + if (f.tagId == TGA_EXIF_TAGID) { + auto ba = dev->read(f.size); + if (ba.startsWith(QByteArray("eXif"))) { + auto exif = MicroExif::fromByteArray(ba.mid(4)); + exif.updateImageMetadata(image, true); + exif.updateImageResolution(image); + } + continue; + } + if (f.tagId == TGA_ICCP_TAGID) { + auto ba = dev->read(f.size); + if (ba.startsWith(QByteArray("iCCP"))) { + image.setColorSpace(QColorSpace::fromIccProfile(ba.mid(4))); + } + continue; + } + if (f.tagId == TGA_XMPP_TAGID) { + auto ba = dev->read(f.size); + if (ba.startsWith(QByteArray("xMPP"))) { + image.setText(QStringLiteral(META_KEY_XMP_ADOBE), QString::fromUtf8(ba.mid(4))); + } + continue; + } + } + } + + return s.status() == QDataStream::Ok; +} + bool TGAHandler::supportsOption(ImageOption option) const { if (option == QImageIOHandler::Size) { @@ -680,48 +1277,74 @@ bool TGAHandler::supportsOption(ImageOption option) const if (option == QImageIOHandler::ImageFormat) { return true; } + if (option == QImageIOHandler::SubType) { + return true; + } + if (option == QImageIOHandler::SupportedSubTypes) { + return true; + } return false; } +void TGAHandler::setOption(ImageOption option, const QVariant &value) +{ + if (option == QImageIOHandler::SubType) { + auto subType = value.toByteArray(); + auto list = TGAHandler::option(QImageIOHandler::SupportedSubTypes).value>(); + if (list.contains(subType)) { + d->m_subType = subType; + } else { + d->m_subType = TGAHandlerPrivate::subTypeTGA_V2S(); + } + } +} + QVariant TGAHandler::option(ImageOption option) const { - QVariant v; + if (!supportsOption(option)) { + return {}; + } + + if (option == QImageIOHandler::SupportedSubTypes) { + return QVariant::fromValue(QList() + << TGAHandlerPrivate::subTypeTGA_V1() << TGAHandlerPrivate::subTypeTGA_V2S() << TGAHandlerPrivate::subTypeTGA_V2E()); + } + + if (option == QImageIOHandler::SubType) { + return QVariant::fromValue(d->m_subType); + } + + auto &&header = d->m_header; + if (!IsSupported(header)) { + if (auto dev = device()) + if (!peekHeader(dev, header) && IsSupported(header)) + return {}; + if (!IsSupported(header)) { + return {}; + } + } if (option == QImageIOHandler::Size) { - auto&& header = d->m_header; - if (IsSupported(header)) { - v = QVariant::fromValue(QSize(header.width, header.height)); - } else if (auto dev = device()) { - if (peekHeader(dev, header) && IsSupported(header)) { - v = QVariant::fromValue(QSize(header.width, header.height)); - } - } + return QVariant::fromValue(QSize(header.width, header.height)); } if (option == QImageIOHandler::ImageFormat) { - auto&& header = d->m_header; - if (IsSupported(header)) { - v = QVariant::fromValue(imageFormat(header)); - } else if (auto dev = device()) { - if (peekHeader(dev, header) && IsSupported(header)) { - v = QVariant::fromValue(imageFormat(header)); - } - } + return QVariant::fromValue(imageFormat(header)); } - return v; + return {}; } bool TGAHandler::canRead(QIODevice *device) { if (!device) { - qWarning("TGAHandler::canRead() called with no device"); + qCWarning(LOG_TGAPLUGIN) << "TGAHandler::canRead() called with no device"; return false; } TgaHeader tga; if (!peekHeader(device, tga)) { - qWarning("TGAHandler::canRead() error while reading the header"); + qCWarning(LOG_TGAPLUGIN) << "TGAHandler::canRead() error while reading the header"; return false; } diff --git a/src/imageformats/tga_p.h b/src/imageformats/tga_p.h index aaafbf0..ca083fb 100644 --- a/src/imageformats/tga_p.h +++ b/src/imageformats/tga_p.h @@ -22,17 +22,20 @@ public: bool write(const QImage &image) override; bool supportsOption(QImageIOHandler::ImageOption option) const override; + void setOption(ImageOption option, const QVariant &value) override; QVariant option(QImageIOHandler::ImageOption option) const override; static bool canRead(QIODevice *device); private: bool writeIndexed(const QImage &image); - bool writeGrayscale(const QImage &image); - + bool writeRGB555(const QImage &image); bool writeRGBA(const QImage &image); + bool writeMetadata(const QImage &image); + bool readMetadata(QImage &image); + const QScopedPointer d; };