1 //========================================================================
5 // This file is licensed under the GPLv2 or later
7 // Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
8 // Copyright (C) 2010, 2012 Adrian Johnson <ajohnson@redneon.com>
9 // Copyright (C) 2010 Harry Roberts <harry.roberts@midnight-labs.org>
10 // Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@alfa.de>
11 // Copyright (C) 2013 Peter Breitenlohner <peb@mppmu.mpg.de>
13 //========================================================================
15 #include "JpegWriter.h"
23 #include "poppler/Error.h"
25 struct JpegWriterPrivate
{
28 JpegWriter::Format format
;
29 struct jpeg_compress_struct cinfo
;
30 struct jpeg_error_mgr jerr
;
33 void outputMessage(j_common_ptr cinfo
)
35 char buffer
[JMSG_LENGTH_MAX
];
38 (*cinfo
->err
->format_message
) (cinfo
, buffer
);
40 // Send it to poppler's error handler
41 error(errInternal
, -1, "{0:s}", buffer
);
44 JpegWriter::JpegWriter(int q
, bool p
, Format formatA
)
46 priv
= new JpegWriterPrivate
;
47 priv
->progressive
= p
;
49 priv
->format
= formatA
;
52 JpegWriter::JpegWriter(Format formatA
)
54 priv
= new JpegWriterPrivate
;
55 priv
->progressive
= false;
57 priv
->format
= formatA
;
60 JpegWriter::~JpegWriter()
63 jpeg_destroy_compress(&priv
->cinfo
);
67 bool JpegWriter::init(FILE *f
, int width
, int height
, int hDPI
, int vDPI
)
69 // Setup error handler
70 priv
->cinfo
.err
= jpeg_std_error(&priv
->jerr
);
71 priv
->jerr
.output_message
= &outputMessage
;
74 jpeg_create_compress(&priv
->cinfo
);
76 // First set colorspace and call jpeg_set_defaults() since
77 // jpeg_set_defaults() sets default values for all fields in
78 // cinfo based on the colorspace.
79 switch (priv
->format
) {
81 priv
->cinfo
.in_color_space
= JCS_RGB
;
84 priv
->cinfo
.in_color_space
= JCS_GRAYSCALE
;
87 priv
->cinfo
.in_color_space
= JCS_CMYK
;
92 jpeg_set_defaults(&priv
->cinfo
);
94 // Set destination file
95 jpeg_stdio_dest(&priv
->cinfo
, f
);
97 // Set libjpeg configuration
98 priv
->cinfo
.image_width
= width
;
99 priv
->cinfo
.image_height
= height
;
100 priv
->cinfo
.density_unit
= 1; // dots per inch
101 priv
->cinfo
.X_density
= hDPI
;
102 priv
->cinfo
.Y_density
= vDPI
;
103 switch (priv
->format
) {
105 priv
->cinfo
.input_components
= 1;
108 priv
->cinfo
.input_components
= 3;
111 priv
->cinfo
.input_components
= 4;
112 jpeg_set_colorspace(&priv
->cinfo
, JCS_YCCK
);
113 priv
->cinfo
.write_JFIF_header
= TRUE
;
120 if (priv
->quality
>= 0 && priv
->quality
<= 100) {
121 jpeg_set_quality(&priv
->cinfo
, priv
->quality
, TRUE
);
124 // Use progressive mode
125 if (priv
->progressive
) {
126 jpeg_simple_progression(&priv
->cinfo
);
129 // Get ready for data
130 jpeg_start_compress(&priv
->cinfo
, TRUE
);
135 bool JpegWriter::writePointers(unsigned char **rowPointers
, int rowCount
)
137 if (priv
->format
== CMYK
) {
138 for (int y
= 0; y
< rowCount
; y
++) {
139 unsigned char *row
= rowPointers
[y
];
140 for (unsigned int x
= 0; x
< priv
->cinfo
.image_width
; x
++) {
141 for (int n
= 0; n
< 4; n
++) {
148 // Write all rows to the file
149 jpeg_write_scanlines(&priv
->cinfo
, rowPointers
, rowCount
);
154 bool JpegWriter::writeRow(unsigned char **rowPointer
)
156 if (priv
->format
== CMYK
) {
157 unsigned char *row
= rowPointer
[0];
158 for (unsigned int x
= 0; x
< priv
->cinfo
.image_width
; x
++) {
159 for (int n
= 0; n
< 4; n
++) {
165 // Write the row to the file
166 jpeg_write_scanlines(&priv
->cinfo
, rowPointer
, 1);
171 bool JpegWriter::close()
173 jpeg_finish_compress(&priv
->cinfo
);
178 bool JpegWriter::supportCMYK()
180 return priv
->format
== CMYK
;