Main MRPT website > C++ reference for MRPT 1.9.9
jccolor.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #define JPEG_INTERNALS
11 #include "jinclude.h"
12 #include "mrpt_jpeglib.h"
13 
14 /* Private subobject */
15 
16 typedef struct
17 {
18  struct jpeg_color_converter pub; /* public fields */
19 
20  /* Private state for RGB->YCC conversion */
21  INT32* rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
23 
25 
26 /**************** RGB -> YCbCr conversion: most common case **************/
27 
28 /*
29  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
30  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
31  * The conversion equations to be implemented are therefore
32  * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
33  * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
34  * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
35  * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
36  * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
37  * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and
38  * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
39  * were not represented exactly. Now we sacrifice exact representation of
40  * maximum red and maximum blue in order to get exact grayscales.
41  *
42  * To avoid floating-point arithmetic, we represent the fractional constants
43  * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
44  * the products by 2^16, with appropriate rounding, to get the correct answer.
45  *
46  * For even more speed, we avoid doing any multiplications in the inner loop
47  * by precalculating the constants times R,G,B for all possible values.
48  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
49  * for 12-bit samples it is still acceptable. It's not very reasonable for
50  * 16-bit samples, but if you want lossless storage you shouldn't be changing
51  * colorspace anyway.
52  * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
53  * in the tables to save adding them separately in the inner loop.
54  */
55 
56 #define SCALEBITS 16 /* speediest right-shift on some machines */
57 #define CBCR_OFFSET ((INT32)CENTERJSAMPLE << SCALEBITS)
58 #define ONE_HALF ((INT32)1 << (SCALEBITS - 1))
59 #define FIX(x) ((INT32)((x) * (1L << SCALEBITS) + 0.5))
60 
61 /* We allocate one big table and divide it up into eight parts, instead of
62  * doing eight alloc_small requests. This lets us use a single table base
63  * address, which can be held in a in the inner loops on many
64  * machines (more than can hold all eight addresses, anyway).
65  */
66 
67 #define R_Y_OFF 0 /* offset to R => Y section */
68 #define G_Y_OFF (1 * (MAXJSAMPLE + 1)) /* offset to G => Y section */
69 #define B_Y_OFF (2 * (MAXJSAMPLE + 1)) /* etc. */
70 #define R_CB_OFF (3 * (MAXJSAMPLE + 1))
71 #define G_CB_OFF (4 * (MAXJSAMPLE + 1))
72 #define B_CB_OFF (5 * (MAXJSAMPLE + 1))
73 #define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */
74 #define G_CR_OFF (6 * (MAXJSAMPLE + 1))
75 #define B_CR_OFF (7 * (MAXJSAMPLE + 1))
76 #define TABLE_SIZE (8 * (MAXJSAMPLE + 1))
77 
78 /*
79  * Initialize for RGB->YCC colorspace conversion.
80  */
81 
82 METHODDEF(void)
84 {
85  my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
86  INT32* rgb_ycc_tab;
87  INT32 i;
88 
89  /* Allocate and fill in the conversion tables. */
90  cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32*)(*cinfo->mem->alloc_small)(
92 
93  for (i = 0; i <= MAXJSAMPLE; i++)
94  {
95  rgb_ycc_tab[i + R_Y_OFF] = FIX(0.29900) * i;
96  rgb_ycc_tab[i + G_Y_OFF] = FIX(0.58700) * i;
97  rgb_ycc_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
98  rgb_ycc_tab[i + R_CB_OFF] = (-FIX(0.16874)) * i;
99  rgb_ycc_tab[i + G_CB_OFF] = (-FIX(0.33126)) * i;
100  /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
101  * This ensures that the maximum output will round to MAXJSAMPLE
102  * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
103  */
104  rgb_ycc_tab[i + B_CB_OFF] =
105  FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF - 1;
106  /* B=>Cb and R=>Cr tables are the same
107  rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET +
108  ONE_HALF-1;
109  */
110  rgb_ycc_tab[i + G_CR_OFF] = (-FIX(0.41869)) * i;
111  rgb_ycc_tab[i + B_CR_OFF] = (-FIX(0.08131)) * i;
112  }
113 }
114 
115 /*
116  * Convert some rows of samples to the JPEG colorspace.
117  *
118  * Note that we change from the application's interleaved-pixel format
119  * to our internal noninterleaved, one-plane-per-component format.
120  * The input buffer is therefore three times as wide as the output buffer.
121  *
122  * A starting row offset is provided only for the output buffer. The caller
123  * can easily adjust the passed input_buf value to accommodate any row
124  * offset required on that side.
125  */
126 
127 METHODDEF(void)
130  JDIMENSION output_row, int num_rows)
131 {
132  my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
133  int r, g, b;
134  INT32* ctab = cconvert->rgb_ycc_tab;
135  JSAMPROW inptr;
136  JSAMPROW outptr0, outptr1, outptr2;
137  JDIMENSION col;
138  JDIMENSION num_cols = cinfo->image_width;
139 
140  while (--num_rows >= 0)
141  {
142  inptr = *input_buf++;
143  outptr0 = output_buf[0][output_row];
144  outptr1 = output_buf[1][output_row];
145  outptr2 = output_buf[2][output_row];
146  output_row++;
147  for (col = 0; col < num_cols; col++)
148  {
149  r = GETJSAMPLE(inptr[RGB_RED]);
150  g = GETJSAMPLE(inptr[RGB_GREEN]);
151  b = GETJSAMPLE(inptr[RGB_BLUE]);
152  inptr += RGB_PIXELSIZE;
153  /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
154  * must be too; we do not need an explicit range-limiting operation.
155  * Hence the value being shifted is never negative, and we don't
156  * need the general RIGHT_SHIFT macro.
157  */
158  /* Y */
159  outptr0[col] = (JSAMPLE)(
160  (ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + ctab[b + B_Y_OFF]) >>
161  SCALEBITS);
162  /* Cb */
163  outptr1[col] = (JSAMPLE)(
164  (ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] +
165  ctab[b + B_CB_OFF]) >>
166  SCALEBITS);
167  /* Cr */
168  outptr2[col] = (JSAMPLE)(
169  (ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] +
170  ctab[b + B_CR_OFF]) >>
171  SCALEBITS);
172  }
173  }
174 }
175 
176 /**************** Cases other than RGB -> YCbCr **************/
177 
178 /*
179  * Convert some rows of samples to the JPEG colorspace.
180  * This version handles RGB->grayscale conversion, which is the same
181  * as the RGB->Y portion of RGB->YCbCr.
182  * We assume rgb_ycc_start has been called (we only use the Y tables).
183  */
184 
185 METHODDEF(void)
188  JDIMENSION output_row, int num_rows)
189 {
190  my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
191  int r, g, b;
192  INT32* ctab = cconvert->rgb_ycc_tab;
193  JSAMPROW inptr;
195  JDIMENSION col;
196  JDIMENSION num_cols = cinfo->image_width;
197 
198  while (--num_rows >= 0)
199  {
200  inptr = *input_buf++;
201  outptr = output_buf[0][output_row];
202  output_row++;
203  for (col = 0; col < num_cols; col++)
204  {
205  r = GETJSAMPLE(inptr[RGB_RED]);
206  g = GETJSAMPLE(inptr[RGB_GREEN]);
207  b = GETJSAMPLE(inptr[RGB_BLUE]);
208  inptr += RGB_PIXELSIZE;
209  /* Y */
210  outptr[col] = (JSAMPLE)(
211  (ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + ctab[b + B_Y_OFF]) >>
212  SCALEBITS);
213  }
214  }
215 }
216 
217 /*
218  * Convert some rows of samples to the JPEG colorspace.
219  * This version handles Adobe-style CMYK->YCCK conversion,
220  * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
221  * conversion as above, while passing K (black) unchanged.
222  * We assume rgb_ycc_start has been called.
223  */
224 
225 METHODDEF(void)
228  JDIMENSION output_row, int num_rows)
229 {
230  my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
231  int r, g, b;
232  INT32* ctab = cconvert->rgb_ycc_tab;
233  JSAMPROW inptr;
234  JSAMPROW outptr0, outptr1, outptr2, outptr3;
235  JDIMENSION col;
236  JDIMENSION num_cols = cinfo->image_width;
237 
238  while (--num_rows >= 0)
239  {
240  inptr = *input_buf++;
241  outptr0 = output_buf[0][output_row];
242  outptr1 = output_buf[1][output_row];
243  outptr2 = output_buf[2][output_row];
244  outptr3 = output_buf[3][output_row];
245  output_row++;
246  for (col = 0; col < num_cols; col++)
247  {
248  r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
249  g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
250  b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
251  /* K passes through as-is */
252  outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */
253  inptr += 4;
254  /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
255  * must be too; we do not need an explicit range-limiting operation.
256  * Hence the value being shifted is never negative, and we don't
257  * need the general RIGHT_SHIFT macro.
258  */
259  /* Y */
260  outptr0[col] = (JSAMPLE)(
261  (ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + ctab[b + B_Y_OFF]) >>
262  SCALEBITS);
263  /* Cb */
264  outptr1[col] = (JSAMPLE)(
265  (ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] +
266  ctab[b + B_CB_OFF]) >>
267  SCALEBITS);
268  /* Cr */
269  outptr2[col] = (JSAMPLE)(
270  (ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] +
271  ctab[b + B_CR_OFF]) >>
272  SCALEBITS);
273  }
274  }
275 }
276 
277 /*
278  * Convert some rows of samples to the JPEG colorspace.
279  * This version handles grayscale output with no conversion.
280  * The source can be either plain grayscale or YCbCr (since Y == gray).
281  */
282 
283 METHODDEF(void)
286  JDIMENSION output_row, int num_rows)
287 {
288  JSAMPROW inptr;
290  JDIMENSION col;
291  JDIMENSION num_cols = cinfo->image_width;
292  int instride = cinfo->input_components;
293 
294  while (--num_rows >= 0)
295  {
296  inptr = *input_buf++;
297  outptr = output_buf[0][output_row];
298  output_row++;
299  for (col = 0; col < num_cols; col++)
300  {
301  outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */
302  inptr += instride;
303  }
304  }
305 }
306 
307 /*
308  * Convert some rows of samples to the JPEG colorspace.
309  * This version handles multi-component colorspaces without conversion.
310  * We assume input_components == num_components.
311  */
312 
313 METHODDEF(void)
316  JDIMENSION output_row, int num_rows)
317 {
318  JSAMPROW inptr;
320  JDIMENSION col;
321  int ci;
322  int nc = cinfo->num_components;
323  JDIMENSION num_cols = cinfo->image_width;
324 
325  while (--num_rows >= 0)
326  {
327  /* It seems fastest to make a separate pass for each component. */
328  for (ci = 0; ci < nc; ci++)
329  {
330  inptr = *input_buf;
331  outptr = output_buf[ci][output_row];
332  for (col = 0; col < num_cols; col++)
333  {
334  outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
335  inptr += nc;
336  }
337  }
338  input_buf++;
339  output_row++;
340  }
341 }
342 
343 /*
344  * Empty method for start_pass.
345  */
346 
347 METHODDEF(void)
348 null_method(j_compress_ptr) { /* no work needed */}
349 /*
350  * Module initialization routine for input colorspace conversion.
351  */
352 
353 GLOBAL(void)
355 {
356  my_cconvert_ptr cconvert;
357 
358  cconvert = (my_cconvert_ptr)(*cinfo->mem->alloc_small)(
360  cinfo->cconvert = (struct jpeg_color_converter*)cconvert;
361  /* set start_pass to null method until we find out differently */
362  cconvert->pub.start_pass = null_method;
363 
364  /* Make sure input_components agrees with in_color_space */
365  switch (cinfo->in_color_space)
366  {
367  case JCS_GRAYSCALE:
368  if (cinfo->input_components != 1)
369  ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
370  break;
371 
372  case JCS_RGB:
373 #if RGB_PIXELSIZE != 3
374  if (cinfo->input_components != RGB_PIXELSIZE)
375  ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
376  break;
377 #endif /* else share code with YCbCr */
378 
379  case JCS_YCbCr:
380  if (cinfo->input_components != 3)
381  ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
382  break;
383 
384  case JCS_CMYK:
385  case JCS_YCCK:
386  if (cinfo->input_components != 4)
387  ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
388  break;
389 
390  default: /* JCS_UNKNOWN can be anything */
391  if (cinfo->input_components < 1)
392  ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
393  break;
394  }
395 
396  /* Check num_components, set conversion method based on requested space */
397  switch (cinfo->jpeg_color_space)
398  {
399  case JCS_GRAYSCALE:
400  if (cinfo->num_components != 1)
401  ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
402  if (cinfo->in_color_space == JCS_GRAYSCALE)
403  cconvert->pub.color_convert = grayscale_convert;
404  else if (cinfo->in_color_space == JCS_RGB)
405  {
406  cconvert->pub.start_pass = rgb_ycc_start;
407  cconvert->pub.color_convert = rgb_gray_convert;
408  }
409  else if (cinfo->in_color_space == JCS_YCbCr)
410  cconvert->pub.color_convert = grayscale_convert;
411  else
412  ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
413  break;
414 
415  case JCS_RGB:
416  if (cinfo->num_components != 3)
417  ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
418  if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
419  cconvert->pub.color_convert = null_convert;
420  else
421  ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
422  break;
423 
424  case JCS_YCbCr:
425  if (cinfo->num_components != 3)
426  ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
427  if (cinfo->in_color_space == JCS_RGB)
428  {
429  cconvert->pub.start_pass = rgb_ycc_start;
430  cconvert->pub.color_convert = rgb_ycc_convert;
431  }
432  else if (cinfo->in_color_space == JCS_YCbCr)
433  cconvert->pub.color_convert = null_convert;
434  else
435  ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
436  break;
437 
438  case JCS_CMYK:
439  if (cinfo->num_components != 4)
440  ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
441  if (cinfo->in_color_space == JCS_CMYK)
442  cconvert->pub.color_convert = null_convert;
443  else
444  ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
445  break;
446 
447  case JCS_YCCK:
448  if (cinfo->num_components != 4)
449  ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
450  if (cinfo->in_color_space == JCS_CMYK)
451  {
452  cconvert->pub.start_pass = rgb_ycc_start;
453  cconvert->pub.color_convert = cmyk_ycck_convert;
454  }
455  else if (cinfo->in_color_space == JCS_YCCK)
456  cconvert->pub.color_convert = null_convert;
457  else
458  ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
459  break;
460 
461  default: /* allow null conversion of JCS_UNKNOWN */
462  if (cinfo->jpeg_color_space != cinfo->in_color_space ||
463  cinfo->num_components != cinfo->input_components)
464  ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
465  cconvert->pub.color_convert = null_convert;
466  break;
467  }
468 }
char JSAMPLE
Definition: jmorecfg.h:58
null_method(j_compress_ptr)
Definition: jccolor.cpp:348
#define SCALEBITS
Definition: jccolor.cpp:56
INT32 * rgb_ycc_tab
Definition: jccolor.cpp:21
rgb_ycc_start(j_compress_ptr cinfo)
Definition: jccolor.cpp:83
struct jpeg_common_struct * j_common_ptr
Definition: mrpt_jpeglib.h:258
#define GETJSAMPLE(value)
Definition: jmorecfg.h:62
#define ERREXIT(cinfo, code)
Definition: jerror.h:451
#define SIZEOF(object)
Definition: jinclude.h:74
#define MAXJSAMPLE
Definition: jmorecfg.h:67
null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
Definition: jccolor.cpp:314
#define R_Y_OFF
Definition: jccolor.cpp:67
JSAMPLE FAR * JSAMPROW
Definition: mrpt_jpeglib.h:60
long INT32
Definition: jmorecfg.h:151
#define G_CB_OFF
Definition: jccolor.cpp:71
JCOEFPTR inptr
Definition: jidctflt.cpp:42
JSAMPROW outptr
Definition: jidctflt.cpp:45
grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
Definition: jccolor.cpp:284
jpeg_component_info JCOEFPTR JSAMPARRAY output_buf
Definition: jidctflt.cpp:36
rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
Definition: jccolor.cpp:128
#define JPOOL_IMAGE
Definition: mrpt_jpeglib.h:750
JSAMPROW * JSAMPARRAY
Definition: mrpt_jpeglib.h:61
GLubyte g
Definition: glext.h:6279
#define G_Y_OFF
Definition: jccolor.cpp:68
GLubyte GLubyte b
Definition: glext.h:6279
#define B_CR_OFF
Definition: jccolor.cpp:75
#define FIX(x)
Definition: jccolor.cpp:59
struct jpeg_color_converter pub
Definition: jccolor.cpp:18
rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
Definition: jccolor.cpp:186
JSAMPARRAY * JSAMPIMAGE
Definition: mrpt_jpeglib.h:62
#define ONE_HALF
Definition: jccolor.cpp:58
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
#define GLOBAL(type)
Definition: jmorecfg.h:177
cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
Definition: jccolor.cpp:226
#define METHODDEF(type)
Definition: jmorecfg.h:173
jinit_color_converter(j_compress_ptr cinfo)
Definition: jccolor.cpp:354
#define R_CB_OFF
Definition: jccolor.cpp:70
#define B_Y_OFF
Definition: jccolor.cpp:69
unsigned int JDIMENSION
Definition: jmorecfg.h:161
my_color_converter * my_cconvert_ptr
Definition: jccolor.cpp:24
#define G_CR_OFF
Definition: jccolor.cpp:74
#define CBCR_OFFSET
Definition: jccolor.cpp:57
#define R_CR_OFF
Definition: jccolor.cpp:73
#define B_CB_OFF
Definition: jccolor.cpp:72
#define TABLE_SIZE
Definition: jccolor.cpp:76



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019