Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
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 
64 void 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 
123 void 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 
194 void 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 
274 void 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)
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
Error that can be emited by the vpImage class and its derivates.
unsigned int getHeight() const
Definition: vpImage.h:188
unsigned int getWidth() const
Definition: vpImage.h:246