~ubuntu-branches/ubuntu/saucy/digikam/saucy

« back to all changes in this revision

Viewing changes to libs/threadimageio/thumbnailcreator.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-12-21 23:19:11 UTC
  • mfrom: (1.2.33 upstream) (3.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20101221231911-z9jip7s5aht1jqn9
Tags: 2:1.7.0-1ubuntu1
* Merge from Debian Experimental. Remaining Ubuntu changes:
  - Export .pot name and copy to plugins in debian/rules
  - Version build-depends on kipi-plugins-dev to ensure build is against the
    same version on all archs
* Drop debian/patches/kubuntu_01_linker.diff, incoporated upstream
* Remove patches directory and unused patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
82
82
}
83
83
 
84
84
ThumbnailCreator::ThumbnailCreator(StorageMethod method)
85
 
                : d(new ThumbnailCreatorPriv)
 
85
    : d(new ThumbnailCreatorPriv)
86
86
{
87
87
    d->thumbnailStorage = method;
88
88
    initialize();
89
89
}
90
90
 
91
91
ThumbnailCreator::ThumbnailCreator(int thumbnailSize, StorageMethod method)
92
 
                : d(new ThumbnailCreatorPriv)
 
92
    : d(new ThumbnailCreatorPriv)
93
93
{
94
94
    setThumbnailSize(thumbnailSize);
95
95
    d->thumbnailStorage = method;
104
104
void ThumbnailCreator::initialize()
105
105
{
106
106
    if (d->thumbnailStorage == FreeDesktopStandard)
 
107
    {
107
108
        initThumbnailDirs();
 
109
    }
108
110
}
109
111
 
110
112
void ThumbnailCreator::setThumbnailSize(int thumbnailSize)
111
113
{
112
114
    d->thumbnailSize = thumbnailSize;
 
115
 
113
116
    // on-disk thumbnail sizes according to spec
114
117
    if (d->onlyLargeThumbnails)
 
118
    {
115
119
        d->cachedSize = 256;
 
120
    }
116
121
    else
 
122
    {
117
123
        d->cachedSize = (thumbnailSize <= 128) ? 128 : 256;
 
124
    }
118
125
}
119
126
 
120
127
void ThumbnailCreator::setExifRotate(bool rotate)
132
139
    d->removeAlphaChannel = removeAlpha;
133
140
}
134
141
 
135
 
void ThumbnailCreator::setLoadingProperties(DImgLoaderObserver *observer, const DRawDecoding& settings)
 
142
void ThumbnailCreator::setLoadingProperties(DImgLoaderObserver* observer, const DRawDecoding& settings)
136
143
{
137
144
    d->observer    = observer;
138
145
    d->rawSettings = settings;
139
146
}
140
147
 
141
 
void ThumbnailCreator::setThumbnailInfoProvider(ThumbnailInfoProvider *provider)
 
148
void ThumbnailCreator::setThumbnailInfoProvider(ThumbnailInfoProvider* provider)
142
149
{
143
150
    d->infoProvider = provider;
144
151
}
168
175
    }
169
176
 
170
177
    if (d->thumbnailStorage == ThumbnailDatabase)
171
 
        d->dbIdForReplacement = -1; // just to prevent bugs
 
178
    {
 
179
        d->dbIdForReplacement = -1;    // just to prevent bugs
 
180
    }
172
181
 
173
182
    // get info about path
174
183
    ThumbnailInfo info;
 
184
 
175
185
    if (d->infoProvider)
 
186
    {
176
187
        info = d->infoProvider->thumbnailInfo(path);
 
188
    }
177
189
    else
 
190
    {
178
191
        info = fileThumbnailInfo(path);
 
192
    }
179
193
 
180
194
    // load pregenerated thumbnail
181
195
    ThumbnailImage image;
 
196
 
182
197
    switch (d->thumbnailStorage)
183
198
    {
184
199
        case ThumbnailDatabase:
193
208
    if (image.isNull())
194
209
    {
195
210
        image = createThumbnail(info);
 
211
 
196
212
        if (!image.isNull())
197
213
        {
198
214
            switch (d->thumbnailStorage)
201
217
                    storeInDatabase(info, image);
202
218
                    break;
203
219
                case FreeDesktopStandard:
 
220
 
204
221
                    // image is stored rotated
205
222
                    if (d->exifRotate)
 
223
                    {
206
224
                        image.qimage = exifRotate(image.qimage, image.exifOrientation);
 
225
                    }
 
226
 
207
227
                    storeFreedesktop(info, image);
208
228
                    break;
209
229
            }
225
245
    {
226
246
        // image is stored, or created, unrotated, and is now rotated for display
227
247
        if (d->exifRotate)
 
248
        {
228
249
            image.qimage = exifRotate(image.qimage, image.exifOrientation);
 
250
        }
229
251
    }
230
252
 
231
253
    return image.qimage;
234
256
void ThumbnailCreator::store(const QString& path, const QImage& i)
235
257
{
236
258
    QImage qimage(i);
 
259
 
237
260
    if (qimage.isNull())
 
261
    {
238
262
        return;
 
263
    }
 
264
 
239
265
    if (qimage.width() > d->cachedSize || qimage.height() > d->cachedSize)
240
266
    {
241
267
        qimage = qimage.scaled(d->cachedSize, d->cachedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
243
269
 
244
270
    // get info about path
245
271
    ThumbnailInfo info;
 
272
 
246
273
    if (d->infoProvider)
 
274
    {
247
275
        info = d->infoProvider->thumbnailInfo(path);
 
276
    }
248
277
    else
 
278
    {
249
279
        info = fileThumbnailInfo(path);
 
280
    }
250
281
 
251
282
    ThumbnailImage image;
252
283
    image.qimage = qimage;
 
284
 
253
285
    switch (d->thumbnailStorage)
254
286
    {
255
287
        case ThumbnailDatabase:
271
303
        case ThumbnailDatabase:
272
304
        {
273
305
            ThumbnailInfo info;
 
306
 
274
307
            if (d->infoProvider)
 
308
            {
275
309
                info = d->infoProvider->thumbnailInfo(filePath);
 
310
            }
276
311
            else
 
312
            {
277
313
                info = fileThumbnailInfo(filePath);
 
314
            }
 
315
 
278
316
            deleteFromDatabase(info);
279
317
            break;
280
318
        }
288
326
ThumbnailImage ThumbnailCreator::createThumbnail(const ThumbnailInfo& info)
289
327
{
290
328
    QString path = info.filePath;
 
329
 
291
330
    if (!info.isAccessible)
292
331
    {
293
332
        d->error = i18n("File does not exist");
318
357
        if (ext == QString("JPEG") || ext == QString("JPG") || ext == QString("JPE"))
319
358
        {
320
359
            if (colorManage)
 
360
            {
321
361
                qimage = loadWithDImg(path, &profile);
 
362
            }
322
363
            else
323
 
            // use jpegutils
 
364
                // use jpegutils
 
365
            {
324
366
                loadJPEGScaled(qimage, path, d->cachedSize);
 
367
            }
 
368
 
325
369
            failedAtJPEGScaled = qimage.isNull();
326
370
        }
327
371
        else if (ext == QString("PNG")  ||
328
 
            ext == QString("TIFF") ||
329
 
            ext == QString("TIF"))
 
372
                 ext == QString("TIFF") ||
 
373
                 ext == QString("TIF"))
330
374
        {
331
375
            qimage       = loadWithDImg(path, &profile);
332
376
            failedAtDImg = qimage.isNull();
383
427
    }
384
428
 
385
429
    int maxSize = qMax(qimage.width(), qimage.height());
 
430
 
386
431
    if (maxSize != d->cachedSize)
387
432
    {
388
433
        /*
393
438
        */
394
439
        qimage        = qimage.scaled(d->cachedSize, d->cachedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
395
440
    }
 
441
 
396
442
    if (colorManage && !profile.isNull())
397
443
    {
398
444
        IccManager::transformToSRGB(qimage, profile);
416
462
QImage ThumbnailCreator::loadImagePreview(const DMetadata& metadata)
417
463
{
418
464
    QImage image;
 
465
 
419
466
    if (metadata.getImagePreview(image))
420
467
    {
421
468
        kDebug() << "Use Exif/IPTC preview extraction. Size of image: "
422
 
                      << image.width() << "x" << image.height();
 
469
                 << image.width() << "x" << image.height();
423
470
    }
424
471
 
425
472
    return image;
444
491
                p.drawImage(0, 0, qimage);
445
492
                return newImage;
446
493
            }
 
494
 
447
495
            break;
448
496
        }
449
497
        default: // indexed and monochrome formats
451
499
            return qimage.convertToFormat(QImage::Format_RGB32);
452
500
        }
453
501
    }
 
502
 
454
503
    return qimage;
455
504
}
456
505
 
459
508
    // Keep in sync with main version in loadsavethread.cpp
460
509
 
461
510
    if (DImg::fileFormat(filePath) == DImg::RAW && !fromEmbeddedPreview )
 
511
    {
462
512
        return DMetadata::ORIENTATION_NORMAL;
 
513
    }
463
514
 
464
515
    return metadata.getImageOrientation();
465
516
}
468
519
{
469
520
    if (orientation == DMetadata::ORIENTATION_NORMAL ||
470
521
        orientation == DMetadata::ORIENTATION_UNSPECIFIED)
 
522
    {
471
523
        return thumb;
 
524
    }
472
525
 
473
526
    QMatrix matrix;
474
527
 
544
597
        QBuffer buffer(&dbInfo.data);
545
598
        buffer.open(QIODevice::WriteOnly);
546
599
        image.qimage.save(&buffer, "JPEG", 90);  // Here we will use JPEG quality = 90 to reduce artifacts.
 
600
 
547
601
        if (dbInfo.data.isNull())
548
602
        {
549
603
            kWarning() << "Cannot save JPEG thumb in DB";
555
609
        QBuffer buffer(&dbInfo.data);
556
610
        buffer.open(QIODevice::WriteOnly);
557
611
        image.qimage.save(&buffer, "JP2");
 
612
 
558
613
        if (dbInfo.data.isNull())
559
614
        {
560
615
            kWarning() << "Cannot save JPEG2000 thumb in DB";
566
621
        QBuffer buffer(&dbInfo.data);
567
622
        buffer.open(QIODevice::WriteOnly);
568
623
        image.qimage.save(&buffer, "PNG", 0);
 
624
 
569
625
        if (dbInfo.data.isNull())
570
626
        {
571
627
            kWarning() << "Cannot save JPEG2000 thumb in DB";
576
632
    ThumbnailDatabaseAccess access;
577
633
 
578
634
    DatabaseCoreBackend::QueryState lastQueryState = DatabaseCoreBackend::ConnectionError;
579
 
    while(lastQueryState == DatabaseCoreBackend::ConnectionError)
 
635
 
 
636
    while (lastQueryState == DatabaseCoreBackend::ConnectionError)
580
637
    {
581
638
        lastQueryState = access.backend()->beginTransaction();
 
639
 
582
640
        if (DatabaseCoreBackend::NoErrors != lastQueryState)
583
641
        {
584
642
            continue;
589
647
        {
590
648
            QVariant id;
591
649
            lastQueryState = access.db()->insertThumbnail(dbInfo, &id);
 
650
 
592
651
            if (DatabaseCoreBackend::NoErrors != lastQueryState)
593
652
            {
594
653
                continue;
601
660
        else
602
661
        {
603
662
            lastQueryState = access.db()->replaceThumbnail(dbInfo);
 
663
 
604
664
            if (DatabaseCoreBackend::NoErrors != lastQueryState)
605
665
            {
606
666
                continue;
611
671
        if (!info.uniqueHash.isNull())
612
672
        {
613
673
            lastQueryState = access.db()->insertUniqueHash(info.uniqueHash, info.fileSize, dbInfo.id);
 
674
 
614
675
            if (DatabaseCoreBackend::NoErrors != lastQueryState)
615
676
            {
616
677
                continue;
617
678
            }
618
679
        }
 
680
 
619
681
        if (!info.filePath.isNull())
620
682
        {
621
683
            lastQueryState = access.db()->insertFilePath(info.filePath, dbInfo.id);
 
684
 
622
685
            if (DatabaseCoreBackend::NoErrors != lastQueryState)
623
686
            {
624
687
                continue;
644
707
    {
645
708
        dbInfo = access.db()->findByHash(info.uniqueHash, info.fileSize);
646
709
    }
 
710
 
647
711
    if (dbInfo.data.isNull() && !info.filePath.isNull())
648
712
    {
649
713
        dbInfo = access.db()->findByFilePath(info.filePath);
653
717
    d->dbIdForReplacement = dbInfo.id;
654
718
 
655
719
    ThumbnailImage image;
 
720
 
656
721
    if (dbInfo.data.isNull())
 
722
    {
657
723
        return ThumbnailImage();
 
724
    }
658
725
 
659
726
    // check modification date
660
727
    if (dbInfo.modificationDate < info.modificationDate)
 
728
    {
661
729
        return ThumbnailImage();
 
730
    }
662
731
 
663
732
    // Read QImage from data blob
664
733
    if (dbInfo.type == DatabaseThumbnail::PGF)
674
743
        QBuffer buffer(&dbInfo.data);
675
744
        buffer.open(QIODevice::ReadOnly);
676
745
        image.qimage.load(&buffer, "JPEG");
 
746
 
677
747
        if (dbInfo.data.isNull())
678
748
        {
679
749
            kWarning() << "Cannot load JPEG thumb from DB";
685
755
        QBuffer buffer(&dbInfo.data);
686
756
        buffer.open(QIODevice::ReadOnly);
687
757
        image.qimage.load(&buffer, "JP2");
 
758
 
688
759
        if (dbInfo.data.isNull())
689
760
        {
690
761
            kWarning() << "Cannot load JPEG2000 thumb from DB";
696
767
        QBuffer buffer(&dbInfo.data);
697
768
        buffer.open(QIODevice::ReadOnly);
698
769
        image.qimage.load(&buffer, "PNG");
 
770
 
699
771
        if (dbInfo.data.isNull())
700
772
        {
701
773
            kWarning() << "Cannot load PNG thumb from DB";
712
784
{
713
785
    ThumbnailDatabaseAccess access;
714
786
    DatabaseCoreBackend::QueryState lastQueryState=DatabaseCoreBackend::ConnectionError;
715
 
    while(DatabaseCoreBackend::ConnectionError==lastQueryState)
 
787
 
 
788
    while (DatabaseCoreBackend::ConnectionError==lastQueryState)
716
789
    {
717
790
        lastQueryState = access.backend()->beginTransaction();
 
791
 
718
792
        if (DatabaseCoreBackend::NoErrors!=lastQueryState)
719
793
        {
720
794
            continue;
721
795
        }
 
796
 
722
797
        if (!info.uniqueHash.isNull())
723
798
        {
724
799
            lastQueryState=access.db()->removeByUniqueHash(info.uniqueHash, info.fileSize);
 
800
 
725
801
            if (DatabaseCoreBackend::NoErrors!=lastQueryState)
726
802
            {
727
803
                continue;
728
804
            }
729
805
        }
 
806
 
730
807
        if (!info.filePath.isNull())
731
808
        {
732
809
            lastQueryState=access.db()->removeByFilePath(info.filePath);
 
810
 
733
811
            if (DatabaseCoreBackend::NoErrors!=lastQueryState)
734
812
            {
735
813
                continue;
736
814
            }
737
815
        }
 
816
 
738
817
        lastQueryState = access.backend()->commitTransaction();
 
818
 
739
819
        if (DatabaseCoreBackend::NoErrors!=lastQueryState)
740
820
        {
741
821
            continue;
746
826
// --------------- Freedesktop.org standard implementation -----------------------
747
827
 
748
828
 
749
 
ThumbnailInfo ThumbnailCreator::fileThumbnailInfo(const QString &path)
 
829
ThumbnailInfo ThumbnailCreator::fileThumbnailInfo(const QString& path)
750
830
{
751
831
    ThumbnailInfo info;
752
832
    info.filePath          = path;
753
833
    QFileInfo fileInfo(path);
754
834
    info.isAccessible     = fileInfo.exists();
 
835
 
755
836
    if (!info.isAccessible)
 
837
    {
756
838
        return info;
 
839
    }
 
840
 
757
841
    info.modificationDate = fileInfo.lastModified();
758
842
    return info;
759
843
}
779
863
            return info;
780
864
        }
781
865
    }
 
866
 
782
867
    return ThumbnailImage();
783
868
}
784
869
 
792
877
 
793
878
    // required by spec
794
879
    if (qimage.format() != QImage::Format_ARGB32)
 
880
    {
795
881
        qimage = qimage.convertToFormat(QImage::Format_ARGB32);
 
882
    }
796
883
 
797
884
    qimage.setText(QString("Thumb::URI").toLatin1(),   0, uri);
798
885
    qimage.setText(QString("Thumb::MTime").toLatin1(), 0, QString::number(info.modificationDate.toTime_t()));
802
889
    temp.setPrefix(thumbPath + "-digikam-");
803
890
    temp.setSuffix(".png");
804
891
    temp.setAutoRemove(false);
 
892
 
805
893
    if (temp.open())
806
894
    {
807
895
        QString tempFileName   = temp.fileName();
 
896
 
808
897
        if (qimage.save(tempFileName, "PNG", 0))
809
898
        {
810
899
            int ret = 0;
812
901
 
813
902
            temp.close();
814
903
 
815
 
            #if KDE_IS_VERSION(4,2,85)
 
904
#if KDE_IS_VERSION(4,2,85)
816
905
            // KDE 4.3.0
817
906
            ret = KDE::rename(QFile::encodeName(tempFileName),
818
907
                              QFile::encodeName(thumbPath));
819
 
            #else
 
908
#else
820
909
            // KDE 4.2.x or 4.1.x
821
910
            ret = KDE_rename(QFile::encodeName(tempFileName),
822
911
                             QFile::encodeName(thumbPath));
823
 
            #endif
 
912
#endif
824
913
 
825
914
            if (ret != 0)
826
915
            {