Visual Servoing Platform  version 3.6.1 under development (2025-03-14)
vpImageIoLibjpeg.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 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 
53 BEGIN_VISP_NAMESPACE
62 void writeJPEGLibjpeg(const vpImage<unsigned char> &I, const std::string &filename, int quality)
63 {
64  struct jpeg_compress_struct cinfo;
65  struct jpeg_error_mgr jerr;
66  FILE *file;
67 
68  cinfo.err = jpeg_std_error(&jerr);
69  jpeg_create_compress(&cinfo);
70 
71  // Test the filename
72  if (filename.empty()) {
73  throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file: filename empty"));
74  }
75 
76  file = fopen(filename.c_str(), "wb");
77 
78  if (file == nullptr) {
79  throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file \"%s\"", filename.c_str()));
80  }
81 
82  unsigned int width = I.getWidth();
83  unsigned int height = I.getHeight();
84 
85  jpeg_stdio_dest(&cinfo, file);
86 
87  cinfo.image_width = width;
88  cinfo.image_height = height;
89  cinfo.input_components = 1;
90  cinfo.in_color_space = JCS_GRAYSCALE;
91  jpeg_set_defaults(&cinfo);
92  jpeg_set_quality(&cinfo, quality, TRUE);
93 
94  jpeg_start_compress(&cinfo, TRUE);
95 
96  unsigned char *line;
97  line = new unsigned char[width];
98  unsigned char *input = (unsigned char *)I.bitmap;
99  while (cinfo.next_scanline < cinfo.image_height) {
100  for (unsigned int i = 0; i < width; ++i) {
101  line[i] = *(input);
102  input++;
103  }
104  jpeg_write_scanlines(&cinfo, &line, 1);
105  }
106 
107  jpeg_finish_compress(&cinfo);
108  jpeg_destroy_compress(&cinfo);
109  delete[] line;
110  fclose(file);
111 }
112 
121 void writeJPEGLibjpeg(const vpImage<vpRGBa> &I, const std::string &filename, int quality)
122 {
123  struct jpeg_compress_struct cinfo;
124  struct jpeg_error_mgr jerr;
125  FILE *file;
126 
127  cinfo.err = jpeg_std_error(&jerr);
128  jpeg_create_compress(&cinfo);
129 
130  // Test the filename
131  if (filename.empty()) {
132  throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file: filename empty"));
133  }
134 
135  file = fopen(filename.c_str(), "wb");
136 
137  if (file == nullptr) {
138  throw(vpImageException(vpImageException::ioError, "Cannot create JPEG file \"%s\"", filename.c_str()));
139  }
140 
141  unsigned int width = I.getWidth();
142  unsigned int height = I.getHeight();
143 
144  jpeg_stdio_dest(&cinfo, file);
145 
146  cinfo.image_width = width;
147  cinfo.image_height = height;
148  cinfo.input_components = 3;
149  cinfo.in_color_space = JCS_RGB;
150  jpeg_set_defaults(&cinfo);
151  jpeg_set_quality(&cinfo, quality, TRUE);
152 
153  jpeg_start_compress(&cinfo, TRUE);
154 
155  unsigned char *line;
156  line = new unsigned char[3 * width];
157  unsigned char *input = (unsigned char *)I.bitmap;
158  while (cinfo.next_scanline < cinfo.image_height) {
159  for (unsigned int i = 0; i < width; ++i) {
160  line[i * 3] = *(input);
161  input++;
162  line[i * 3 + 1] = *(input);
163  input++;
164  line[i * 3 + 2] = *(input);
165  input++;
166  input++;
167  }
168  jpeg_write_scanlines(&cinfo, &line, 1);
169  }
170 
171  jpeg_finish_compress(&cinfo);
172  jpeg_destroy_compress(&cinfo);
173  delete[] line;
174  fclose(file);
175 }
176 
192 void readJPEGLibjpeg(vpImage<unsigned char> &I, const std::string &filename)
193 {
194  struct jpeg_decompress_struct cinfo;
195  struct jpeg_error_mgr jerr;
196  FILE *file;
197 
198  cinfo.err = jpeg_std_error(&jerr);
199  jpeg_create_decompress(&cinfo);
200 
201  // Test the filename
202  if (filename.empty()) {
203  throw(vpImageException(vpImageException::ioError, "Cannot read JPEG image: filename empty"));
204  }
205 
206  file = fopen(filename.c_str(), "rb");
207 
208  if (file == nullptr) {
209  throw(vpImageException(vpImageException::ioError, "Cannot read JPEG file \"%s\"", filename.c_str()));
210  }
211 
212  jpeg_stdio_src(&cinfo, file);
213  jpeg_read_header(&cinfo, TRUE);
214 
215  unsigned int width = cinfo.image_width;
216  unsigned int height = cinfo.image_height;
217 
218  if ((width != I.getWidth()) || (height != I.getHeight()))
219  I.resize(height, width);
220 
221  jpeg_start_decompress(&cinfo);
222 
223  unsigned int rowbytes = cinfo.output_width * (unsigned int)(cinfo.output_components);
224  JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, rowbytes, 1);
225 
226  if (cinfo.out_color_space == JCS_RGB) {
227  vpImage<vpRGBa> Ic(height, width);
228  unsigned char *output = (unsigned char *)Ic.bitmap;
229  while (cinfo.output_scanline < cinfo.output_height) {
230  jpeg_read_scanlines(&cinfo, buffer, 1);
231  for (unsigned int i = 0; i < width; ++i) {
232  *(output++) = buffer[0][i * 3];
233  *(output++) = buffer[0][i * 3 + 1];
234  *(output++) = buffer[0][i * 3 + 2];
235  *(output++) = vpRGBa::alpha_default;
236  }
237  }
239  }
240 
241  else if (cinfo.out_color_space == JCS_GRAYSCALE) {
242  while (cinfo.output_scanline < cinfo.output_height) {
243  unsigned int row = cinfo.output_scanline;
244  jpeg_read_scanlines(&cinfo, buffer, 1);
245  memcpy(I[row], buffer[0], rowbytes);
246  }
247  }
248 
249  jpeg_finish_decompress(&cinfo);
250  jpeg_destroy_decompress(&cinfo);
251  fclose(file);
252 }
253 
272 void readJPEGLibjpeg(vpImage<vpRGBa> &I, const std::string &filename)
273 {
274  struct jpeg_decompress_struct cinfo;
275  struct jpeg_error_mgr jerr;
276  FILE *file;
277 
278  cinfo.err = jpeg_std_error(&jerr);
279  jpeg_create_decompress(&cinfo);
280 
281  // Test the filename
282  if (filename.empty()) {
283  throw(vpImageException(vpImageException::ioError, "Cannot read JPEG image: filename empty"));
284  }
285 
286  file = fopen(filename.c_str(), "rb");
287 
288  if (file == nullptr) {
289  throw(vpImageException(vpImageException::ioError, "Cannot read JPEG file \"%s\"", filename.c_str()));
290  }
291 
292  jpeg_stdio_src(&cinfo, file);
293 
294  jpeg_read_header(&cinfo, TRUE);
295 
296  unsigned int width = cinfo.image_width;
297  unsigned int height = cinfo.image_height;
298 
299  if ((width != I.getWidth()) || (height != I.getHeight()))
300  I.resize(height, width);
301 
302  jpeg_start_decompress(&cinfo);
303 
304  unsigned int rowbytes = cinfo.output_width * (unsigned int)(cinfo.output_components);
305  JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, rowbytes, 1);
306 
307  if (cinfo.out_color_space == JCS_RGB) {
308  unsigned char *output = (unsigned char *)I.bitmap;
309  while (cinfo.output_scanline < cinfo.output_height) {
310  jpeg_read_scanlines(&cinfo, buffer, 1);
311  for (unsigned int i = 0; i < width; ++i) {
312  *(output++) = buffer[0][i * 3];
313  *(output++) = buffer[0][i * 3 + 1];
314  *(output++) = buffer[0][i * 3 + 2];
315  *(output++) = vpRGBa::alpha_default;
316  }
317  }
318  }
319 
320  else if (cinfo.out_color_space == JCS_GRAYSCALE) {
321  vpImage<unsigned char> Ig(height, width);
322 
323  while (cinfo.output_scanline < cinfo.output_height) {
324  unsigned int row = cinfo.output_scanline;
325  jpeg_read_scanlines(&cinfo, buffer, 1);
326  memcpy(Ig[row], buffer[0], rowbytes);
327  }
328 
330  }
331 
332  jpeg_finish_decompress(&cinfo);
333  jpeg_destroy_decompress(&cinfo);
334  fclose(file);
335 }
336 
337 END_VISP_NAMESPACE
338 
339 #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:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:544
Type * bitmap
points toward the bitmap
Definition: vpImage.h:135
unsigned int getHeight() const
Definition: vpImage.h:181
@ alpha_default
Definition: vpRGBa.h:72