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