~ubuntu-branches/ubuntu/feisty/digikam/feisty

« back to all changes in this revision

Viewing changes to kioslave/digikamthumbnail.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Achim Bohnet
  • Date: 2005-03-10 02:39:02 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 hoary)
  • Revision ID: james.westby@ubuntu.com-20050310023902-023nymfst5mg696c
Tags: 0.7.2-2
* debian/TODO: clean
* digikam manpage: better --detect-camera description

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <qcstring.h>
2
 
#include <qstring.h>
3
 
#include <qimage.h>
4
 
#include <qdatastream.h>
5
 
 
6
 
#include <kdebug.h>
7
 
#include <kurl.h>
8
 
#include <kinstance.h>
9
 
#include <kio/global.h>
10
 
#include <kimageio.h>
11
 
 
12
 
#define XMD_H
13
 
 
14
 
extern "C" {
15
 
#include <stdlib.h>
16
 
#include <unistd.h>
17
 
#include <jpeglib.h>
18
 
#include <stdio.h>
19
 
#include <sys/stat.h>
20
 
#include <setjmp.h>
21
 
#include <sys/types.h>
22
 
#include <sys/ipc.h>
23
 
#include <sys/shm.h>
24
 
}
25
 
 
26
 
 
27
 
#include "digikamthumbnail.h"
28
 
 
29
 
using namespace KIO;
30
 
 
31
 
 
32
 
kio_digikamthumbnailProtocol::kio_digikamthumbnailProtocol(const QCString &pool_socket,
33
 
                                                           const QCString &app_socket)
34
 
    : SlaveBase("kio_digikamthumbnail", pool_socket, app_socket)
35
 
{
36
 
}
37
 
 
38
 
 
39
 
kio_digikamthumbnailProtocol::~kio_digikamthumbnailProtocol()
40
 
{
41
 
}
42
 
 
43
 
 
44
 
void kio_digikamthumbnailProtocol::get(const KURL& url )
45
 
{
46
 
    size_ = metaData("size").toInt();
47
 
    if (size_ <= 0) {
48
 
        error(KIO::ERR_INTERNAL, "No or invalid size specified");
49
 
        kdWarning() << "No or invalid size specified" << endl;
50
 
        return;
51
 
    }
52
 
 
53
 
    QImage img;
54
 
    // try jpeg loading
55
 
    if (!loadJPEG(img, url.path()))
56
 
        img.load(url.path());
57
 
    
58
 
    if (img.isNull()) {
59
 
        error(KIO::ERR_INTERNAL, "Cannot create thumbnail for " + url.path());
60
 
        kdWarning() << "Cannot create thumbnail for " << url.path() << endl;
61
 
        return;
62
 
    }
63
 
 
64
 
    if (QMAX(img.width(),img.height()) != size_)
65
 
        img = img.smoothScale(size_,size_,QImage::ScaleMin);
66
 
 
67
 
    if (img.depth() != 32)
68
 
        img = img.convertDepth(32);
69
 
    
70
 
    QByteArray imgData;
71
 
    QDataStream stream( imgData, IO_WriteOnly );
72
 
 
73
 
    QString shmid = metaData("shmid");
74
 
    if (shmid.isEmpty()) {
75
 
        stream << img;
76
 
    }
77
 
    else
78
 
    {
79
 
        void *shmaddr = shmat(shmid.toInt(), 0, 0);
80
 
        if (shmaddr == (void *)-1)
81
 
        {
82
 
            error(KIO::ERR_INTERNAL,
83
 
                  "Failed to attach to shared memory segment "
84
 
                  + shmid);
85
 
            kdWarning() << "Failed to attach to shared memory segment "
86
 
                        << shmid << endl;
87
 
            return;
88
 
        }
89
 
        if (img.width() * img.height() > size_ * size_)
90
 
        {
91
 
            error(KIO::ERR_INTERNAL,
92
 
                  "Image is too big for the shared memory segment");
93
 
            kdWarning() << "Image is too big for the shared memory segment"
94
 
                        << endl;
95
 
            shmdt((char*)shmaddr);
96
 
            return;
97
 
        }
98
 
        stream << img.width() << img.height() << img.depth();
99
 
        memcpy(shmaddr, img.bits(), img.numBytes());
100
 
        shmdt((char*)shmaddr);
101
 
    }
102
 
    
103
 
    data(imgData);
104
 
    finished();
105
 
}
106
 
 
107
 
struct myjpeg_error_mgr : public jpeg_error_mgr 
108
 
{
109
 
    jmp_buf setjmp_buffer;
110
 
};
111
 
 
112
 
extern "C"
113
 
{
114
 
  static void myjpeg_error_exit(j_common_ptr cinfo)
115
 
  {
116
 
    myjpeg_error_mgr* myerr = 
117
 
      (myjpeg_error_mgr*) cinfo->err;
118
 
 
119
 
    char buffer[JMSG_LENGTH_MAX];
120
 
    (*cinfo->err->format_message)(cinfo, buffer);
121
 
    kdWarning() << buffer << endl;
122
 
    longjmp(myerr->setjmp_buffer, 1);
123
 
  }
124
 
}
125
 
 
126
 
bool kio_digikamthumbnailProtocol::loadJPEG(QImage& image,
127
 
                                            const QString& path)
128
 
{
129
 
    QString format=QImageIO::imageFormat(path);
130
 
    if (format !="JPEG") return false;
131
 
    
132
 
    FILE* inputFile=fopen(path.latin1(), "rb");
133
 
    if(!inputFile)
134
 
        return false;
135
 
 
136
 
    struct jpeg_decompress_struct    cinfo;
137
 
    struct myjpeg_error_mgr jerr;
138
 
 
139
 
    // JPEG error handling - thanks to Marcus Meissner
140
 
    cinfo.err             = jpeg_std_error(&jerr);
141
 
    cinfo.err->error_exit = myjpeg_error_exit;
142
 
 
143
 
    if (setjmp(jerr.setjmp_buffer)) {
144
 
      jpeg_destroy_decompress(&cinfo);
145
 
      fclose(inputFile);
146
 
      return false;
147
 
    }
148
 
 
149
 
    jpeg_create_decompress(&cinfo);
150
 
    jpeg_stdio_src(&cinfo, inputFile);
151
 
    jpeg_read_header(&cinfo, TRUE);
152
 
 
153
 
    int imgSize = QMAX(cinfo.image_width, cinfo.image_height);
154
 
 
155
 
    int scale=1;
156
 
    while(size_*scale*2<=imgSize) {
157
 
        scale*=2;
158
 
    }
159
 
    if(scale>8) scale=8;
160
 
 
161
 
    cinfo.scale_num=1;
162
 
    cinfo.scale_denom=scale;
163
 
 
164
 
    // Create QImage
165
 
    jpeg_start_decompress(&cinfo);
166
 
 
167
 
    QImage img;
168
 
    
169
 
    switch(cinfo.output_components) {
170
 
    case 3:
171
 
    case 4:
172
 
        img.create( cinfo.output_width, cinfo.output_height, 32 );
173
 
        break;
174
 
    case 1: // B&W image
175
 
        img.create( cinfo.output_width, cinfo.output_height,
176
 
                      8, 256 );
177
 
        for (int i=0; i<256; i++)
178
 
            img.setColor(i, qRgb(i,i,i));
179
 
        break;
180
 
    default:
181
 
        return false;
182
 
    }
183
 
 
184
 
    uchar** lines = img.jumpTable();
185
 
    while (cinfo.output_scanline < cinfo.output_height)
186
 
        jpeg_read_scanlines(&cinfo, lines + cinfo.output_scanline,
187
 
                            cinfo.output_height);
188
 
    jpeg_finish_decompress(&cinfo);
189
 
 
190
 
    // Expand 24->32 bpp
191
 
    if ( cinfo.output_components == 3 ) {
192
 
        for (uint j=0; j<cinfo.output_height; j++) {
193
 
            uchar *in = img.scanLine(j) + cinfo.output_width*3;
194
 
            QRgb *out = (QRgb*)( img.scanLine(j) );
195
 
 
196
 
            for (uint i=cinfo.output_width; i--; ) {
197
 
                in-=3;
198
 
                out[i] = qRgb(in[0], in[1], in[2]);
199
 
            }
200
 
        }
201
 
    }
202
 
 
203
 
    int newMax = QMAX(cinfo.output_width, cinfo.output_height);
204
 
    int newx = size_*cinfo.output_width / newMax;
205
 
    int newy = size_*cinfo.output_height / newMax;
206
 
 
207
 
    jpeg_destroy_decompress(&cinfo);
208
 
    fclose(inputFile);
209
 
 
210
 
    image = img.smoothScale(newx,newy);
211
 
    
212
 
    return true;
213
 
}
214
 
 
215
 
 
216
 
 
217
 
extern "C"
218
 
{
219
 
    int kdemain(int argc, char **argv)
220
 
    {
221
 
        KInstance instance( "kio_digikamthumbnail" );
222
 
        
223
 
        kdDebug() << "*** Starting kio_digikamthumbnail " << endl;
224
 
        
225
 
        if (argc != 4) {
226
 
            kdDebug() << "Usage: kio_digikamthumbnail  protocol domain-socket1 domain-socket2" << endl;
227
 
            exit(-1);
228
 
        }
229
 
 
230
 
        KImageIO::registerFormats();
231
 
        
232
 
        kio_digikamthumbnailProtocol slave(argv[2], argv[3]);
233
 
        slave.dispatchLoop();
234
 
        
235
 
        kdDebug() << "*** kio_digikamthumbnail Done" << endl;
236
 
        return 0;
237
 
    }
238
 
}