~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to ksplash/ksplashx/qjpegio.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** This file is based on sources of the Qt GUI Toolkit, used under the terms
 
4
** of the GNU General Public License version 2 (see the original copyright
 
5
** notice below).
 
6
** All further contributions to this file are (and are required to be)
 
7
** licensed under the terms of the GNU General Public License as published by
 
8
** the Free Software Foundation; either version 2 of the License, or
 
9
** (at your option) any later version.
 
10
**
 
11
** The original Qt license header follows:
 
12
** 
 
13
**
 
14
** Implementation of JPEG QImage IOHandler
 
15
**
 
16
** Created : 990521
 
17
**
 
18
** Copyright (C) 1992-2008 Trolltech ASA.  All rights reserved.
 
19
**
 
20
** This file is part of the kernel module of the Qt GUI Toolkit.
 
21
**
 
22
** This file may be used under the terms of the GNU General
 
23
** Public License versions 2.0 or 3.0 as published by the Free
 
24
** Software Foundation and appearing in the files LICENSE.GPL2
 
25
** and LICENSE.GPL3 included in the packaging of this file.
 
26
** Alternatively you may (at your option) use any later version
 
27
** of the GNU General Public License if such license has been
 
28
** publicly approved by Trolltech ASA (or its successors, if any)
 
29
** and the KDE Free Qt Foundation.
 
30
**
 
31
** Please review the following information to ensure GNU General
 
32
** Public Licensing requirements will be met:
 
33
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
 
34
** If you are unsure which license is appropriate for your use, please
 
35
** review the following information:
 
36
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
 
37
** or contact the sales department at sales@trolltech.com.
 
38
**
 
39
** This file may be used under the terms of the Q Public License as
 
40
** defined by Trolltech ASA and appearing in the file LICENSE.QPL
 
41
** included in the packaging of this file.  Licensees holding valid Qt
 
42
** Commercial licenses may use this file in accordance with the Qt
 
43
** Commercial License Agreement provided with the Software.
 
44
**
 
45
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
 
46
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
 
47
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
 
48
** herein.
 
49
**
 
50
**********************************************************************/
 
51
 
 
52
#ifndef QT_CLEAN_NAMESPACE
 
53
#define QT_CLEAN_NAMESPACE
 
54
#endif
 
55
 
 
56
#include "qimage.h"
 
57
#include "qcolor.h"
 
58
 
 
59
#ifndef QT_NO_IMAGEIO_JPEG
 
60
 
 
61
#include <stdio.h>      // jpeglib needs this to be pre-included
 
62
#include <setjmp.h>
 
63
 
 
64
 
 
65
// including jpeglib.h seems to be a little messy
 
66
extern "C" {
 
67
#define XMD_H           // shut JPEGlib up
 
68
#if defined(Q_OS_UNIXWARE)
 
69
#  define HAVE_BOOLEAN  // libjpeg under Unixware seems to need this
 
70
#endif
 
71
#include <jpeglib.h>
 
72
#ifdef const
 
73
#  undef const          // remove crazy C hackery in jconfig.h
 
74
#endif
 
75
}
 
76
 
 
77
 
 
78
struct my_error_mgr : public jpeg_error_mgr {
 
79
    jmp_buf setjmp_buffer;
 
80
};
 
81
 
 
82
#if defined(Q_C_CALLBACKS)
 
83
extern "C" {
 
84
#endif
 
85
 
 
86
static
 
87
void my_error_exit (j_common_ptr cinfo)
 
88
{
 
89
    my_error_mgr* myerr = (my_error_mgr*) cinfo->err;
 
90
    char buffer[JMSG_LENGTH_MAX];
 
91
    (*cinfo->err->format_message)(cinfo, buffer);
 
92
    qWarning(buffer);
 
93
    longjmp(myerr->setjmp_buffer, 1);
 
94
}
 
95
 
 
96
#if defined(Q_C_CALLBACKS)
 
97
}
 
98
#endif
 
99
 
 
100
 
 
101
static const int max_buf = 4096;
 
102
 
 
103
struct my_jpeg_source_mgr : public jpeg_source_mgr {
 
104
    // Nothing dynamic - cannot rely on destruction over longjump
 
105
    FILE* f;
 
106
    JOCTET buffer[max_buf];
 
107
 
 
108
public:
 
109
    my_jpeg_source_mgr(FILE* f);
 
110
};
 
111
 
 
112
#if defined(Q_C_CALLBACKS)
 
113
extern "C" {
 
114
#endif
 
115
 
 
116
static
 
117
void qt_init_source(j_decompress_ptr)
 
118
{
 
119
}
 
120
 
 
121
static
 
122
boolean qt_fill_input_buffer(j_decompress_ptr cinfo)
 
123
{
 
124
    int num_read;
 
125
    my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src;
 
126
    src->next_input_byte = src->buffer;
 
127
    num_read = fread( (char*)src->buffer, 1, max_buf, src->f );
 
128
 
 
129
    if ( num_read <= 0 ) {
 
130
        // Insert a fake EOI marker - as per jpeglib recommendation
 
131
        src->buffer[0] = (JOCTET) 0xFF;
 
132
        src->buffer[1] = (JOCTET) JPEG_EOI;
 
133
        src->bytes_in_buffer = 2;
 
134
    } else {
 
135
        src->bytes_in_buffer = num_read;
 
136
    }
 
137
#if defined(Q_OS_UNIXWARE)
 
138
    return B_TRUE;
 
139
#else
 
140
    return TRUE;
 
141
#endif
 
142
}
 
143
 
 
144
static
 
145
void qt_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
 
146
{
 
147
    my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src;
 
148
 
 
149
    // `dumb' implementation from jpeglib
 
150
 
 
151
    /* Just a dumb implementation for now.  Could use fseek() except
 
152
     * it doesn't work on pipes.  Not clear that being smart is worth
 
153
     * any trouble anyway --- large skips are infrequent.
 
154
     */
 
155
    if (num_bytes > 0) {
 
156
        while (num_bytes > (long) src->bytes_in_buffer) {
 
157
            num_bytes -= (long) src->bytes_in_buffer;
 
158
            (void) qt_fill_input_buffer(cinfo);
 
159
            /* note we assume that qt_fill_input_buffer will never return FALSE,
 
160
            * so suspension need not be handled.
 
161
            */
 
162
        }
 
163
        src->next_input_byte += (size_t) num_bytes;
 
164
        src->bytes_in_buffer -= (size_t) num_bytes;
 
165
    }
 
166
}
 
167
 
 
168
static
 
169
void qt_term_source(j_decompress_ptr)
 
170
{
 
171
}
 
172
 
 
173
#if defined(Q_C_CALLBACKS)
 
174
}
 
175
#endif
 
176
 
 
177
 
 
178
inline my_jpeg_source_mgr::my_jpeg_source_mgr(FILE* fptr)
 
179
{
 
180
    jpeg_source_mgr::init_source = qt_init_source;
 
181
    jpeg_source_mgr::fill_input_buffer = qt_fill_input_buffer;
 
182
    jpeg_source_mgr::skip_input_data = qt_skip_input_data;
 
183
    jpeg_source_mgr::resync_to_restart = jpeg_resync_to_restart;
 
184
    jpeg_source_mgr::term_source = qt_term_source;
 
185
    f = fptr;
 
186
    bytes_in_buffer = 0;
 
187
    next_input_byte = buffer;
 
188
}
 
189
 
 
190
 
 
191
QImage splash_read_jpeg_image(FILE* f)
 
192
{
 
193
    QImage image;
 
194
 
 
195
    struct jpeg_decompress_struct cinfo;
 
196
 
 
197
    struct my_jpeg_source_mgr *iod_src = new my_jpeg_source_mgr(f);
 
198
    struct my_error_mgr jerr;
 
199
 
 
200
    jpeg_create_decompress(&cinfo);
 
201
 
 
202
    cinfo.src = iod_src;
 
203
 
 
204
    cinfo.err = jpeg_std_error(&jerr);
 
205
    jerr.error_exit = my_error_exit;
 
206
 
 
207
    if (!setjmp(jerr.setjmp_buffer)) {
 
208
#if defined(Q_OS_UNIXWARE)
 
209
        (void) jpeg_read_header(&cinfo, B_TRUE);
 
210
#else
 
211
        (void) jpeg_read_header(&cinfo, TRUE);
 
212
#endif
 
213
 
 
214
        (void) jpeg_start_decompress(&cinfo);
 
215
 
 
216
       {
 
217
            bool created = FALSE;
 
218
            if ( cinfo.output_components == 3 || cinfo.output_components == 4) {
 
219
                created = image.create( cinfo.output_width, cinfo.output_height, 32 );
 
220
            } else if ( cinfo.output_components == 1 ) {
 
221
                created = image.create( cinfo.output_width, cinfo.output_height, 8, 256 );
 
222
                for (int i=0; i<256; i++)
 
223
                    image.setColor(i, qRgb(i,i,i));
 
224
            } else {
 
225
                // Unsupported format
 
226
            }
 
227
            if (!created)
 
228
                image = QImage();
 
229
 
 
230
            if (!image.isNull()) {
 
231
                uchar** lines = image.jumpTable();
 
232
                while (cinfo.output_scanline < cinfo.output_height)
 
233
                    (void) jpeg_read_scanlines(&cinfo,
 
234
                                               lines + cinfo.output_scanline,
 
235
                                               cinfo.output_height);
 
236
                (void) jpeg_finish_decompress(&cinfo);
 
237
 
 
238
                if ( cinfo.output_components == 3 ) {
 
239
                    // Expand 24->32 bpp.
 
240
                    for (uint j=0; j<cinfo.output_height; j++) {
 
241
                        uchar *in = image.scanLine(j) + cinfo.output_width * 3;
 
242
                        QRgb *out = (QRgb*)image.scanLine(j);
 
243
 
 
244
                        for (uint i=cinfo.output_width; i--; ) {
 
245
                            in-=3;
 
246
                            out[i] = qRgb(in[0], in[1], in[2]);
 
247
                        }
 
248
                    }
 
249
                }
 
250
            }
 
251
        }
 
252
 
 
253
        if (!image.isNull()) {
 
254
            if ( cinfo.density_unit == 1 ) {
 
255
                image.setDotsPerMeterX( int(100. * cinfo.X_density / 2.54) );
 
256
                image.setDotsPerMeterY( int(100. * cinfo.Y_density / 2.54) );
 
257
            } else if ( cinfo.density_unit == 2 ) {
 
258
                image.setDotsPerMeterX( int(100. * cinfo.X_density) );
 
259
                image.setDotsPerMeterY( int(100. * cinfo.Y_density) );
 
260
            }
 
261
        }
 
262
 
 
263
    }
 
264
 
 
265
    jpeg_destroy_decompress(&cinfo);
 
266
    delete iod_src;
 
267
    return image;
 
268
}
 
269
 
 
270
#endif