View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.imaging.formats.tiff.photometricinterpreters;
18  
19  import java.io.IOException;
20  
21  import org.apache.commons.imaging.ImagingException;
22  import org.apache.commons.imaging.common.ImageBuilder;
23  
24  public class PhotometricInterpreterYCbCr extends PhotometricInterpreter {
25  
26      /**
27       * This method converts a YUV (aka YCbCr) colorspace to a RGB colorspace. This is handy when trying to reconstruct an image in Java from YCbCr transmitted
28       * data. This routine expects the data to fall in the standard PC 0..255 range per pixel, with the array dimensions corresponding to the imageWidth and
29       * imageHeight. These variables are either set manually in the case of a null constructor, or they are automatically calculated from the image parameter
30       * constructor.
31       *
32       * @param y  The Y component set.
33       * @param cb The Cb component set.
34       * @param cr The Cr component set.
35       * @return R The R component.
36       */
37      public static int convertYCbCrtoRGB(final int y, final int cb, final int cr) {
38          final double r1 = 1.164 * (y - 16.0) + 1.596 * (cr - 128.0);
39          final double g1 = 1.164 * (y - 16.0) - 0.813 * (cr - 128.0) - 0.392 * (cb - 128.0);
40          final double b1 = 1.164 * (y - 16.0) + 2.017 * (cb - 128.0);
41  
42          final int r = limit((int) r1, 0, 255);
43          final int g = limit((int) g1, 0, 255);
44          final int b = limit((int) b1, 0, 255);
45  
46          final int alpha = 0xff;
47          return alpha << 24 | r << 16 | g << 8 | b << 0;
48      }
49  
50      public static int limit(final int value, final int min, final int max) {
51          return Math.min(max, Math.max(min, value));
52      }
53  
54      public PhotometricInterpreterYCbCr(final int samplesPerPixel, final int[] bitsPerSample, final int predictor, final int width, final int height) {
55          super(samplesPerPixel, bitsPerSample, predictor, width, height);
56      }
57  
58      @Override
59      public void interpretPixel(final ImageBuilder imageBuilder, final int[] samples, final int x, final int y) throws ImagingException, IOException {
60          final int Y = samples[0];
61          final int cb = samples[1];
62          final int cr = samples[2];
63          final double r = Y + 1.402 * (cr - 128.0);
64          final double g = Y - 0.34414 * (cb - 128.0) - 0.71414 * (cr - 128.0);
65          final double b = Y + 1.772 * (cb - 128.0);
66  
67          final int red = limit((int) r, 0, 255);
68          final int green = limit((int) g, 0, 255);
69          final int blue = limit((int) b, 0, 255);
70  
71          final int alpha = 0xff;
72          final int rgb = alpha << 24 | red << 16 | green << 8 | blue << 0;
73          imageBuilder.setRgb(x, y, rgb);
74  
75      }
76  }