Statistics
| Branch: | Tag: | Revision:

root / Imaging / JpegLib / imjccolor.pas @ 0:95bd93c28625

History | View | Annotate | Download (17.6 kB)

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