Visual Servoing Platform version 3.5.0
vpImageIoLibjpeg.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2022 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it 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 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See http://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * Libjpeg backend for JPEG image I/O operations.
33 *
34 *****************************************************************************/
35
41#include "vpImageIoBackend.h"
42#include <visp3/core/vpImageConvert.h>
43
44#if defined(VISP_HAVE_JPEG)
45#include <jerror.h>
46#include <jpeglib.h>
47#endif
48
49
50//--------------------------------------------------------------------------
51// JPEG
52//--------------------------------------------------------------------------
53
54#if defined(VISP_HAVE_JPEG)
55
64void writeJPEGLibjpeg(const vpImage<unsigned char> &I, const std::string &filename, int quality)
65{
66 struct jpeg_compress_struct cinfo;
67 struct jpeg_error_mgr jerr;
68 FILE *file;
69
70 cinfo.err = jpeg_std_error(&jerr);
71 jpeg_create_compress(&cinfo);
72
73 // Test the filename
74 if (filename.empty()) {
75 throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file: filename empty"));
76 }
77
78 file = fopen(filename.c_str(), "wb");
79
80 if (file == NULL) {
81 throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file \"%s\"", filename.c_str()));
82 }
83
84 unsigned int width = I.getWidth();
85 unsigned int height = I.getHeight();
86
87 jpeg_stdio_dest(&cinfo, file);
88
89 cinfo.image_width = width;
90 cinfo.image_height = height;
91 cinfo.input_components = 1;
92 cinfo.in_color_space = JCS_GRAYSCALE;
93 jpeg_set_defaults(&cinfo);
94 jpeg_set_quality(&cinfo, quality, TRUE);
95
96 jpeg_start_compress(&cinfo, TRUE);
97
98 unsigned char *line;
99 line = new unsigned char[width];
100 unsigned char *input = (unsigned char *)I.bitmap;
101 while (cinfo.next_scanline < cinfo.image_height) {
102 for (unsigned int i = 0; i < width; i++) {
103 line[i] = *(input);
104 input++;
105 }
106 jpeg_write_scanlines(&cinfo, &line, 1);
107 }
108
109 jpeg_finish_compress(&cinfo);
110 jpeg_destroy_compress(&cinfo);
111 delete[] line;
112 fclose(file);
113}
114
123void writeJPEGLibjpeg(const vpImage<vpRGBa> &I, const std::string &filename, int quality)
124{
125 struct jpeg_compress_struct cinfo;
126 struct jpeg_error_mgr jerr;
127 FILE *file;
128
129 cinfo.err = jpeg_std_error(&jerr);
130 jpeg_create_compress(&cinfo);
131
132 // Test the filename
133 if (filename.empty()) {
134 throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file: filename empty"));
135 }
136
137 file = fopen(filename.c_str(), "wb");
138
139 if (file == NULL) {
140 throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file \"%s\"", filename.c_str()));
141 }
142
143 unsigned int width = I.getWidth();
144 unsigned int height = I.getHeight();
145
146 jpeg_stdio_dest(&cinfo, file);
147
148 cinfo.image_width = width;
149 cinfo.image_height = height;
150 cinfo.input_components = 3;
151 cinfo.in_color_space = JCS_RGB;
152 jpeg_set_defaults(&cinfo);
153 jpeg_set_quality(&cinfo, quality, TRUE);
154
155 jpeg_start_compress(&cinfo, TRUE);
156
157 unsigned char *line;
158 line = new unsigned char[3 * width];
159 unsigned char *input = (unsigned char *)I.bitmap;
160 while (cinfo.next_scanline < cinfo.image_height) {
161 for (unsigned int i = 0; i < width; i++) {
162 line[i * 3] = *(input);
163 input++;
164 line[i * 3 + 1] = *(input);
165 input++;
166 line[i * 3 + 2] = *(input);
167 input++;
168 input++;
169 }
170 jpeg_write_scanlines(&cinfo, &line, 1);
171 }
172
173 jpeg_finish_compress(&cinfo);
174 jpeg_destroy_compress(&cinfo);
175 delete[] line;
176 fclose(file);
177}
178
194void readJPEGLibjpeg(vpImage<unsigned char> &I, const std::string &filename)
195{
196 struct jpeg_decompress_struct cinfo;
197 struct jpeg_error_mgr jerr;
198 FILE *file;
199
200 cinfo.err = jpeg_std_error(&jerr);
201 jpeg_create_decompress(&cinfo);
202
203 // Test the filename
204 if (filename.empty()) {
205 throw(vpImageException(vpImageException::ioError, "Cannot read JPEG image: filename empty"));
206 }
207
208 file = fopen(filename.c_str(), "rb");
209
210 if (file == NULL) {
211 throw(vpImageException(vpImageException::ioError, "Cannot read JPEG file \"%s\"", filename.c_str()));
212 }
213
214 jpeg_stdio_src(&cinfo, file);
215 jpeg_read_header(&cinfo, TRUE);
216
217 unsigned int width = cinfo.image_width;
218 unsigned int height = cinfo.image_height;
219
220 if ((width != I.getWidth()) || (height != I.getHeight()))
221 I.resize(height, width);
222
223 jpeg_start_decompress(&cinfo);
224
225 unsigned int rowbytes = cinfo.output_width * (unsigned int)(cinfo.output_components);
226 JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, rowbytes, 1);
227
228 if (cinfo.out_color_space == JCS_RGB) {
229 vpImage<vpRGBa> Ic(height, width);
230 unsigned char *output = (unsigned char *)Ic.bitmap;
231 while (cinfo.output_scanline < cinfo.output_height) {
232 jpeg_read_scanlines(&cinfo, buffer, 1);
233 for (unsigned int i = 0; i < width; i++) {
234 *(output++) = buffer[0][i * 3];
235 *(output++) = buffer[0][i * 3 + 1];
236 *(output++) = buffer[0][i * 3 + 2];
237 *(output++) = vpRGBa::alpha_default;
238 }
239 }
241 }
242
243 else if (cinfo.out_color_space == JCS_GRAYSCALE) {
244 while (cinfo.output_scanline < cinfo.output_height) {
245 unsigned int row = cinfo.output_scanline;
246 jpeg_read_scanlines(&cinfo, buffer, 1);
247 memcpy(I[row], buffer[0], rowbytes);
248 }
249 }
250
251 jpeg_finish_decompress(&cinfo);
252 jpeg_destroy_decompress(&cinfo);
253 fclose(file);
254}
255
274void readJPEGLibjpeg(vpImage<vpRGBa> &I, const std::string &filename)
275{
276 struct jpeg_decompress_struct cinfo;
277 struct jpeg_error_mgr jerr;
278 FILE *file;
279
280 cinfo.err = jpeg_std_error(&jerr);
281 jpeg_create_decompress(&cinfo);
282
283 // Test the filename
284 if (filename.empty()) {
285 throw(vpImageException(vpImageException::ioError, "Cannot read JPEG image: filename empty"));
286 }
287
288 file = fopen(filename.c_str(), "rb");
289
290 if (file == NULL) {
291 throw(vpImageException(vpImageException::ioError, "Cannot read JPEG file \"%s\"", filename.c_str()));
292 }
293
294 jpeg_stdio_src(&cinfo, file);
295
296 jpeg_read_header(&cinfo, TRUE);
297
298 unsigned int width = cinfo.image_width;
299 unsigned int height = cinfo.image_height;
300
301 if ((width != I.getWidth()) || (height != I.getHeight()))
302 I.resize(height, width);
303
304 jpeg_start_decompress(&cinfo);
305
306 unsigned int rowbytes = cinfo.output_width * (unsigned int)(cinfo.output_components);
307 JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, rowbytes, 1);
308
309 if (cinfo.out_color_space == JCS_RGB) {
310 unsigned char *output = (unsigned char *)I.bitmap;
311 while (cinfo.output_scanline < cinfo.output_height) {
312 jpeg_read_scanlines(&cinfo, buffer, 1);
313 for (unsigned int i = 0; i < width; i++) {
314 *(output++) = buffer[0][i * 3];
315 *(output++) = buffer[0][i * 3 + 1];
316 *(output++) = buffer[0][i * 3 + 2];
317 *(output++) = vpRGBa::alpha_default;
318 }
319 }
320 }
321
322 else if (cinfo.out_color_space == JCS_GRAYSCALE) {
323 vpImage<unsigned char> Ig(height, width);
324
325 while (cinfo.output_scanline < cinfo.output_height) {
326 unsigned int row = cinfo.output_scanline;
327 jpeg_read_scanlines(&cinfo, buffer, 1);
328 memcpy(Ig[row], buffer[0], rowbytes);
329 }
330
332 }
333
334 jpeg_finish_decompress(&cinfo);
335 jpeg_destroy_decompress(&cinfo);
336 fclose(file);
337}
338#endif
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Error that can be emited by the vpImage class and its derivates.
unsigned int getWidth() const
Definition: vpImage.h:246
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:800
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
unsigned int getHeight() const
Definition: vpImage.h:188
@ alpha_default
Definition: vpRGBa.h:69