File indexing completed on 2024-05-12 04:19:58

0001 /*
0002 Gwenview: an image viewer
0003 Copyright 2007 Aurélien Gâteau <agateau@kde.org>
0004 
0005 This program is free software; you can redistribute it and/or
0006 modify it under the terms of the GNU General Public License
0007 as published by the Free Software Foundation; either version 2
0008 of the License, or (at your option) any later version.
0009 
0010 This program is distributed in the hope that it will be useful,
0011 but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 GNU General Public License for more details.
0014 
0015 You should have received a copy of the GNU General Public License
0016 along with this program; if not, write to the Free Software
0017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0018 
0019 */
0020 #include "jpegcontenttest.h"
0021 #include <iostream>
0022 
0023 // Qt
0024 #include <QDebug>
0025 #include <QDir>
0026 #include <QFile>
0027 #include <QImage>
0028 #include <QString>
0029 #include <QTest>
0030 
0031 // KF
0032 
0033 // Local
0034 #include "../lib/jpegcontent.h"
0035 #include "../lib/orientation.h"
0036 #include "testutils.h"
0037 
0038 using namespace std;
0039 
0040 const char *ORIENT6_FILE = "orient6.jpg";
0041 const char *ORIENT1_VFLIP_FILE = "orient1_vflip.jpg";
0042 const char *CUT_FILE = "cut.jpg";
0043 const char *TMP_FILE = "tmp.jpg";
0044 const char *THUMBNAIL_FILE = "test_thumbnail.jpg";
0045 
0046 const int ORIENT6_WIDTH = 128; // This size is the size *after* orientation
0047 const int ORIENT6_HEIGHT = 256; // has been applied
0048 const QString ORIENT6_COMMENT = "a comment";
0049 
0050 QTEST_MAIN(JpegContentTest)
0051 
0052 void JpegContentTest::initTestCase()
0053 {
0054     bool result;
0055     QFile in(pathForTestFile(ORIENT6_FILE));
0056     result = in.open(QIODevice::ReadOnly);
0057     QVERIFY(result);
0058 
0059     QFileInfo info(in);
0060     int size = info.size() / 2;
0061 
0062     char *data = new char[size];
0063     int readSize = in.read(data, size);
0064     QCOMPARE(size, readSize);
0065 
0066     QFile out(CUT_FILE);
0067     result = out.open(QIODevice::WriteOnly);
0068     QVERIFY(result);
0069 
0070     int wroteSize = out.write(data, size);
0071     QCOMPARE(size, wroteSize);
0072     delete[] data;
0073 }
0074 
0075 void JpegContentTest::cleanupTestCase()
0076 {
0077     QDir::current().remove(CUT_FILE);
0078 }
0079 
0080 using MetaInfoMap = QMap<QString, QString>;
0081 
0082 #if 0
0083 MetaInfoMap getMetaInfo(const QString& path)
0084 {
0085     KFileMetaInfo fmi(path);
0086     QStringList list = fmi.supportedKeys();
0087     QStringList::ConstIterator it = list.constBegin();
0088     MetaInfoMap map;
0089 
0090     for (; it != list.constEnd(); ++it) {
0091         KFileMetaInfoItem item = fmi.item(*it);
0092         map[*it] = item.value().toString();
0093     }
0094 
0095     return map;
0096 }
0097 
0098 void compareMetaInfo(const QString& path1, const QString& path2, const QStringList& ignoredKeys)
0099 {
0100     MetaInfoMap mim1 = getMetaInfo(path1);
0101     MetaInfoMap mim2 = getMetaInfo(path2);
0102 
0103     QCOMPARE(mim1.keys(), mim2.keys());
0104     QList<QString> keys = mim1.keys();
0105     QList<QString>::ConstIterator it = keys.constBegin();
0106     for (; it != keys.constEnd(); ++it) {
0107         QString key = *it;
0108         if (ignoredKeys.contains(key)) continue;
0109 
0110         QString msg =
0111             QStringLiteral("Meta info differs for key '%1': v1=%2 v2=%3")
0112             .arg(key)
0113             .arg(mim1[key])
0114             .arg(mim2[key]);
0115 
0116         QVERIFY2(mim1[key] == mim2[key], msg.toUtf8());
0117     }
0118 }
0119 #endif
0120 
0121 void JpegContentTest::testResetOrientation()
0122 {
0123     Gwenview::JpegContent content;
0124     bool result;
0125 
0126     // Test resetOrientation without transform
0127     result = content.load(pathForTestFile(ORIENT6_FILE));
0128     QVERIFY(result);
0129 
0130     content.resetOrientation();
0131 
0132     result = content.save(TMP_FILE);
0133     QVERIFY(result);
0134 
0135     result = content.load(TMP_FILE);
0136     QVERIFY(result);
0137     QCOMPARE(content.orientation(), Gwenview::NORMAL);
0138 
0139     // Test resetOrientation with transform
0140     result = content.load(pathForTestFile(ORIENT6_FILE));
0141     QVERIFY(result);
0142 
0143     content.resetOrientation();
0144     content.transform(Gwenview::ROT_90);
0145 
0146     result = content.save(TMP_FILE);
0147     QVERIFY(result);
0148 
0149     result = content.load(TMP_FILE);
0150     QVERIFY(result);
0151     QCOMPARE(content.orientation(), Gwenview::NORMAL);
0152 }
0153 
0154 /**
0155  * This function tests JpegContent::transform() by applying a ROT_90
0156  * transformation, saving, reloading and applying a ROT_270 to undo the ROT_90.
0157  * Saving and reloading are necessary because lossless transformation only
0158  * happens in JpegContent::save()
0159  */
0160 void JpegContentTest::testTransform()
0161 {
0162     bool result;
0163     QImage finalImage, expectedImage;
0164 
0165     Gwenview::JpegContent content;
0166     result = content.load(pathForTestFile(ORIENT6_FILE));
0167     QVERIFY(result);
0168 
0169     content.transform(Gwenview::ROT_90);
0170     result = content.save(TMP_FILE);
0171     QVERIFY(result);
0172 
0173     result = content.load(TMP_FILE);
0174     QVERIFY(result);
0175     content.transform(Gwenview::ROT_270);
0176     result = content.save(TMP_FILE);
0177     QVERIFY(result);
0178 
0179     result = finalImage.load(TMP_FILE);
0180     QVERIFY(result);
0181 
0182     result = expectedImage.load(pathForTestFile(ORIENT6_FILE));
0183     QVERIFY(result);
0184 
0185     QCOMPARE(finalImage, expectedImage);
0186 }
0187 
0188 void JpegContentTest::testSetComment()
0189 {
0190     QString comment = "test comment";
0191     Gwenview::JpegContent content;
0192     bool result;
0193     result = content.load(pathForTestFile(ORIENT6_FILE));
0194     QVERIFY(result);
0195 
0196     content.setComment(comment);
0197     QCOMPARE(content.comment(), comment);
0198     result = content.save(TMP_FILE);
0199     QVERIFY(result);
0200 
0201     result = content.load(TMP_FILE);
0202     QVERIFY(result);
0203     QCOMPARE(content.comment(), comment);
0204 }
0205 
0206 void JpegContentTest::testReadInfo()
0207 {
0208     Gwenview::JpegContent content;
0209     bool result = content.load(pathForTestFile(ORIENT6_FILE));
0210     QVERIFY(result);
0211     QCOMPARE(int(content.orientation()), 6);
0212     QCOMPARE(content.comment(), ORIENT6_COMMENT);
0213     QCOMPARE(content.size(), QSize(ORIENT6_WIDTH, ORIENT6_HEIGHT));
0214 }
0215 
0216 void JpegContentTest::testThumbnail()
0217 {
0218     Gwenview::JpegContent content;
0219     bool result = content.load(pathForTestFile(ORIENT6_FILE));
0220     QVERIFY(result);
0221     QImage thumbnail = content.thumbnail();
0222     result = thumbnail.save(THUMBNAIL_FILE, "JPEG");
0223     QVERIFY(result);
0224 }
0225 
0226 void JpegContentTest::testMultipleRotations()
0227 {
0228     // Test that rotating a file a lot of times does not cause findJxform() to fail
0229     Gwenview::JpegContent content;
0230     bool result = content.load(pathForTestFile(ORIENT6_FILE));
0231     QVERIFY(result);
0232     result = content.load(pathForTestFile(ORIENT6_FILE));
0233     QVERIFY(result);
0234 
0235     // 12*4 + 1 is the same as 1, since rotating four times brings you back
0236     for (int loop = 0; loop < 12 * 4 + 1; ++loop) {
0237         content.transform(Gwenview::ROT_90);
0238     }
0239     result = content.save(TMP_FILE);
0240     QVERIFY(result);
0241 
0242     result = content.load(TMP_FILE);
0243     QVERIFY(result);
0244 
0245     QCOMPARE(content.size(), QSize(ORIENT6_HEIGHT, ORIENT6_WIDTH));
0246 
0247     // Check the other meta info are still here
0248     //    QStringList ignoredKeys;
0249     //    ignoredKeys << "Orientation" << "Comment";
0250     //    compareMetaInfo(pathForTestFile(ORIENT6_FILE), pathForTestFile(ORIENT1_VFLIP_FILE), ignoredKeys);
0251 }
0252 
0253 void JpegContentTest::testLoadTruncated()
0254 {
0255     // Test that loading and manipulating a truncated file does not crash
0256     Gwenview::JpegContent content;
0257     bool result = content.load(CUT_FILE);
0258     QVERIFY(result);
0259     QCOMPARE(int(content.orientation()), 6);
0260     QCOMPARE(content.comment(), ORIENT6_COMMENT);
0261     content.transform(Gwenview::VFLIP);
0262     qWarning() << "# Next function should output errors about incomplete image";
0263     content.save(TMP_FILE);
0264     qWarning() << "#";
0265 }
0266 
0267 void JpegContentTest::testRawData()
0268 {
0269     Gwenview::JpegContent content;
0270     bool result = content.load(pathForTestFile(ORIENT6_FILE));
0271     QVERIFY(result);
0272 
0273     QByteArray fileData;
0274     QFile file(pathForTestFile(ORIENT6_FILE));
0275     result = file.open(QIODevice::ReadOnly);
0276     QVERIFY(result);
0277     fileData = file.readAll();
0278 
0279     QCOMPARE(content.rawData(), fileData);
0280 }
0281 
0282 void JpegContentTest::testSetImage()
0283 {
0284     Gwenview::JpegContent content;
0285     bool result = content.load(pathForTestFile(ORIENT6_FILE));
0286     QVERIFY(result);
0287 
0288     QImage image = QImage(400, 300, QImage::Format_RGB32);
0289     image.fill(Qt::red);
0290 
0291     content.setImage(image);
0292 
0293     result = content.save(TMP_FILE);
0294     QVERIFY(result);
0295 
0296     result = content.load(TMP_FILE);
0297     QVERIFY(result);
0298 
0299     QCOMPARE(content.size(), image.size());
0300 
0301     //    QStringList ignoredKeys;
0302     //    ignoredKeys << "Orientation";
0303     //    compareMetaInfo(pathForTestFile(ORIENT6_FILE), pathForTestFile(TMP_FILE), ignoredKeys);
0304 }
0305 
0306 #include "moc_jpegcontenttest.cpp"