~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/poppler/cpp/poppler-image.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010, Pino Toscano <pino@kde.org>
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2, or (at your option)
 
7
 * any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 */
 
18
 
 
19
#include "poppler-image.h"
 
20
 
 
21
#include "poppler-image-private.h"
 
22
 
 
23
#include <config.h>
 
24
#include "ImgWriter.h"
 
25
#if defined(ENABLE_LIBPNG)
 
26
#include "PNGWriter.h"
 
27
#endif
 
28
#if defined(ENABLE_LIBJPEG)
 
29
#include "JpegWriter.h"
 
30
#endif
 
31
 
 
32
#include <cstdlib>
 
33
#include <cstring>
 
34
#include <algorithm>
 
35
#include <memory>
 
36
#include <vector>
 
37
 
 
38
namespace {
 
39
 
 
40
struct FileCloser {
 
41
    inline FileCloser(FILE *ff)
 
42
        : f(ff) {}
 
43
    inline ~FileCloser()
 
44
    { (void)close(); }
 
45
    inline bool close()
 
46
    { if (f) { const int c = fclose(f); f = 0; return c == 0; } return true; }
 
47
 
 
48
    FILE *f;
 
49
};
 
50
 
 
51
int calc_bytes_per_row(int width, poppler::image::format_enum format)
 
52
{
 
53
    switch (format) {
 
54
    case poppler::image::format_invalid:
 
55
        return 0;
 
56
    case poppler::image::format_mono:
 
57
        return (width + 7) >> 3;
 
58
    case poppler::image::format_rgb24:
 
59
        return width * 3;
 
60
    case poppler::image::format_argb32:
 
61
        return width * 4;
 
62
    }
 
63
    return 0;
 
64
}
 
65
 
 
66
}
 
67
 
 
68
using namespace poppler;
 
69
 
 
70
image_private::image_private(int iwidth, int iheight, image::format_enum iformat)
 
71
    : ref(1)
 
72
    , data(0)
 
73
    , width(iwidth)
 
74
    , height(iheight)
 
75
    , bytes_per_row(0)
 
76
    , bytes_num(0)
 
77
    , format(iformat)
 
78
    , own_data(true)
 
79
{
 
80
}
 
81
 
 
82
image_private::~image_private()
 
83
{
 
84
    if (own_data) {
 
85
        std::free(data);
 
86
    }
 
87
}
 
88
 
 
89
image_private *image_private::create_data(int width, int height, image::format_enum format)
 
90
{
 
91
    if (width <= 0 || height <= 0) {
 
92
        return 0;
 
93
    }
 
94
 
 
95
    int bpr = calc_bytes_per_row(width, format);
 
96
    if (bpr <= 0) {
 
97
        return 0;
 
98
    }
 
99
 
 
100
    std::auto_ptr<image_private> d(new image_private(width, height, format));
 
101
    d->bytes_num = bpr * height;
 
102
    d->data = reinterpret_cast<char *>(std::malloc(d->bytes_num));
 
103
    if (!d->data) {
 
104
        return 0;
 
105
    }
 
106
    d->own_data = true;
 
107
    d->bytes_per_row = bpr;
 
108
 
 
109
    return d.release();
 
110
}
 
111
 
 
112
image_private *image_private::create_data(char *data, int width, int height, image::format_enum format)
 
113
{
 
114
    if (width <= 0 || height <= 0 || !data) {
 
115
        return 0;
 
116
    }
 
117
 
 
118
    int bpr = calc_bytes_per_row(width, format);
 
119
    if (bpr <= 0) {
 
120
        return 0;
 
121
    }
 
122
 
 
123
    std::auto_ptr<image_private> d(new image_private(width, height, format));
 
124
    d->bytes_num = bpr * height;
 
125
    d->data = data;
 
126
    d->own_data = false;
 
127
    d->bytes_per_row = bpr;
 
128
 
 
129
    return d.release();
 
130
}
 
131
 
 
132
/**
 
133
 \class poppler::image poppler-image.h "poppler/cpp/poppler-image.h"
 
134
 
 
135
 A simple representation of image, with direct access to the data.
 
136
 
 
137
 This class uses implicit sharing for the internal data, so it can be used as
 
138
 value class. This also means any non-const operation will make sure that the
 
139
 data used by current instance is not shared with other instances (ie
 
140
 \em detaching), copying the shared data.
 
141
 
 
142
 \since 0.16
 
143
 */
 
144
 
 
145
/**
 
146
 \enum poppler::image::format_enum
 
147
 
 
148
 The possible formats for an image.
 
149
*/
 
150
 
 
151
 
 
152
/**
 
153
 Construct an invalid image.
 
154
 */
 
155
image::image()
 
156
    : d(0)
 
157
{
 
158
}
 
159
 
 
160
/**
 
161
 Construct a new image.
 
162
 
 
163
 It allocates the storage needed for the image data; if the allocation fails,
 
164
 the image is an invalid one.
 
165
 
 
166
 \param iwidth the width for the image
 
167
 \param iheight the height for the image
 
168
 \param iformat the format for the bits of the image
 
169
 */
 
170
image::image(int iwidth, int iheight, image::format_enum iformat)
 
171
    : d(image_private::create_data(iwidth, iheight, iformat))
 
172
{
 
173
}
 
174
 
 
175
/**
 
176
 Construct a new image.
 
177
 
 
178
 It uses the provide data buffer for the image, so you \b must ensure it
 
179
 remains valid for the whole lifetime of the image.
 
180
 
 
181
 \param idata the buffer to use for the image
 
182
 \param iwidth the width for the image
 
183
 \param iheight the height for the image
 
184
 \param iformat the format for the bits of the image
 
185
 */
 
186
image::image(char *idata, int iwidth, int iheight, image::format_enum iformat)
 
187
    : d(image_private::create_data(idata, iwidth, iheight, iformat))
 
188
{
 
189
}
 
190
 
 
191
/**
 
192
 Copy constructor.
 
193
 */
 
194
image::image(const image &pt)
 
195
    : d(pt.d)
 
196
{
 
197
    if (d) {
 
198
        ++d->ref;
 
199
    }
 
200
}
 
201
 
 
202
/**
 
203
 Destructor.
 
204
 */
 
205
image::~image()
 
206
{
 
207
    if (d && !--d->ref) {
 
208
        delete d;
 
209
    }
 
210
}
 
211
 
 
212
/**
 
213
 Image validity check.
 
214
 
 
215
 \returns whether the image is valid.
 
216
 */
 
217
bool image::is_valid() const
 
218
{
 
219
    return d && d->format != format_invalid;
 
220
}
 
221
 
 
222
/**
 
223
 \returns the format of the image
 
224
 */
 
225
image::format_enum image::format() const
 
226
{
 
227
    return d ? d->format : format_invalid;
 
228
}
 
229
 
 
230
/**
 
231
 \returns whether the width of the image
 
232
 */
 
233
int image::width() const
 
234
{
 
235
    return d ? d->width : 0;
 
236
}
 
237
 
 
238
/**
 
239
 \returns whether the height of the image
 
240
 */
 
241
int image::height() const
 
242
{
 
243
    return d ? d->height : 0;
 
244
}
 
245
 
 
246
/**
 
247
 \returns the number of bytes in each row of the image
 
248
 */
 
249
int image::bytes_per_row() const
 
250
{
 
251
    return d ? d->bytes_per_row : 0;
 
252
}
 
253
 
 
254
/**
 
255
 Access to the image bits.
 
256
 
 
257
 This function will detach and copy the shared data.
 
258
 
 
259
 \returns the pointer to the first pixel
 
260
 */
 
261
char *image::data()
 
262
{
 
263
    if (!d) {
 
264
        return 0;
 
265
    }
 
266
 
 
267
    detach();
 
268
    return d->data;
 
269
}
 
270
 
 
271
/**
 
272
 Access to the image bits.
 
273
 
 
274
 This function provides const access to the data.
 
275
 
 
276
 \returns the pointer to the first pixel
 
277
 */
 
278
const char *image::const_data() const
 
279
{
 
280
    return d ? d->data : 0;
 
281
}
 
282
 
 
283
/**
 
284
 Copy of a slice of the image.
 
285
 
 
286
 \param r the sub-area of this image to copy; if empty, the whole image is
 
287
          copied
 
288
 
 
289
 \returns a new image representing the specified part of the current image
 
290
 */
 
291
image image::copy(const rect &r) const
 
292
{
 
293
    if (r.is_empty()) {
 
294
        image img(*this);
 
295
        img.detach();
 
296
        return img;
 
297
    }
 
298
 
 
299
    // ### FIXME
 
300
    return *this;
 
301
}
 
302
 
 
303
/**
 
304
 Saves the current image to file.
 
305
 
 
306
 Using this function it is possible to save the image to the specified
 
307
 \p file_name, in the specified \p out_format and with a resolution of the
 
308
 specified \p dpi.
 
309
 
 
310
 Image formats commonly supported are:
 
311
 \li PNG: \c png
 
312
 \li JPEG: \c jpeg, \c jpg
 
313
 
 
314
 If an image format is not supported (check the result of
 
315
 supported_image_formats()), the saving fails.
 
316
 
 
317
 \returns whether the saving succeeded
 
318
 */
 
319
bool image::save(const std::string &file_name, const std::string &out_format, int dpi) const
 
320
{
 
321
    if (!is_valid() || file_name.empty() || out_format.empty()) {
 
322
        return false;
 
323
    }
 
324
 
 
325
    std::string fmt = out_format;
 
326
    std::transform(fmt.begin(), fmt.end(), fmt.begin(), tolower);
 
327
 
 
328
    std::auto_ptr<ImgWriter> w;
 
329
    const int actual_dpi = dpi == -1 ? 75 : dpi;
 
330
    if (false) {
 
331
    }
 
332
#if defined(ENABLE_LIBPNG)
 
333
    else if (fmt == "png") {
 
334
        w.reset(new PNGWriter());
 
335
    }
 
336
#endif
 
337
#if defined(ENABLE_LIBJPEG)
 
338
    else if (fmt == "jpeg" || fmt == "jpg") {
 
339
        w.reset(new JpegWriter());
 
340
    }
 
341
#endif
 
342
    if (!w.get()) {
 
343
        return false;
 
344
    }
 
345
    FILE *f = fopen(file_name.c_str(), "w");
 
346
    if (!f) {
 
347
        return false;
 
348
    }
 
349
    const FileCloser fc(f);
 
350
    if (!w->init(f, d->width, d->height, actual_dpi, actual_dpi)) {
 
351
        return false;
 
352
    }
 
353
    switch (d->format) {
 
354
    case format_invalid:
 
355
        return false;
 
356
    case format_mono:
 
357
        return false;
 
358
    case format_rgb24: {
 
359
        char *hptr = d->data;
 
360
        for (int y = 0; y < d->height; ++y) {
 
361
            if (!w->writeRow(reinterpret_cast<unsigned char **>(&hptr))) {
 
362
                return false;
 
363
            }
 
364
            hptr += d->bytes_per_row;
 
365
        }
 
366
        break;
 
367
    }
 
368
    case format_argb32: {
 
369
        std::vector<unsigned char> row(3 * d->width);
 
370
        char *hptr = d->data;
 
371
        for (int y = 0; y < d->height; ++y) {
 
372
            unsigned char *rowptr = &row[0];
 
373
            for (int x = 0; x < d->width; ++x, rowptr += 3) {
 
374
                const unsigned int pixel = *reinterpret_cast<unsigned int *>(hptr + x * 4);
 
375
                rowptr[0] = (pixel >> 16) & 0xff;
 
376
                rowptr[1] = (pixel >> 8) & 0xff;
 
377
                rowptr[2] = pixel & 0xff;
 
378
            }
 
379
            rowptr = &row[0];
 
380
            if (!w->writeRow(&rowptr)) {
 
381
                return false;
 
382
            }
 
383
            hptr += d->bytes_per_row;
 
384
        }
 
385
        break;
 
386
    }
 
387
    }
 
388
 
 
389
    if (!w->close()) {
 
390
        return false;
 
391
    }
 
392
 
 
393
    return true;
 
394
}
 
395
 
 
396
/**
 
397
 \returns a list of the supported image formats
 
398
 */
 
399
std::vector<std::string> image::supported_image_formats()
 
400
{
 
401
    std::vector<std::string> formats;
 
402
#if defined(ENABLE_LIBPNG)
 
403
    formats.push_back("png");
 
404
#endif
 
405
#if defined(ENABLE_LIBJPEG)
 
406
    formats.push_back("jpeg");
 
407
    formats.push_back("jpg");
 
408
#endif
 
409
    return formats;
 
410
}
 
411
 
 
412
/**
 
413
 Assignment operator.
 
414
 */
 
415
image& image::operator=(const image &pt)
 
416
{
 
417
    if (pt.d) {
 
418
        ++pt.d->ref;
 
419
    }
 
420
    image_private *old_d = d;
 
421
    d = pt.d;
 
422
    if (old_d && !--old_d->ref) {
 
423
        delete old_d;
 
424
    }
 
425
    return *this;
 
426
}
 
427
 
 
428
void image::detach()
 
429
{
 
430
    if (d->ref == 1) {
 
431
        return;
 
432
    }
 
433
 
 
434
    image_private *old_d = d;
 
435
    d = image_private::create_data(old_d->width, old_d->height, old_d->format);
 
436
    if (d) {
 
437
        std::memcpy(d->data, old_d->data, old_d->bytes_num);
 
438
        --old_d->ref;
 
439
    } else {
 
440
        d = old_d;
 
441
    }
 
442
}