001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.imaging.formats.tiff.photometricinterpreters; 018 019import java.io.IOException; 020 021import org.apache.commons.imaging.ImagingException; 022import org.apache.commons.imaging.common.ImageBuilder; 023 024public class PhotometricInterpreterYCbCr extends AbstractPhotometricInterpreter { 025 026 /** 027 * 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 028 * 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 029 * imageHeight. These variables are either set manually in the case of a null constructor, or they are automatically calculated from the image parameter 030 * constructor. 031 * 032 * @param y The Y component set. 033 * @param cb The Cb component set. 034 * @param cr The Cr component set. 035 * @return R The R component. 036 */ 037 public static int convertYCbCrtoRGB(final int y, final int cb, final int cr) { 038 final double r1 = 1.164 * (y - 16.0) + 1.596 * (cr - 128.0); 039 final double g1 = 1.164 * (y - 16.0) - 0.813 * (cr - 128.0) - 0.392 * (cb - 128.0); 040 final double b1 = 1.164 * (y - 16.0) + 2.017 * (cb - 128.0); 041 042 final int r = limit((int) r1, 0, 255); 043 final int g = limit((int) g1, 0, 255); 044 final int b = limit((int) b1, 0, 255); 045 046 final int alpha = 0xff; 047 return alpha << 24 | r << 16 | g << 8 | b << 0; 048 } 049 050 public static int limit(final int value, final int min, final int max) { 051 return Math.min(max, Math.max(min, value)); 052 } 053 054 public PhotometricInterpreterYCbCr(final int samplesPerPixel, final int[] bitsPerSample, final int predictor, final int width, final int height) { 055 super(samplesPerPixel, bitsPerSample, predictor, width, height); 056 } 057 058 @Override 059 public void interpretPixel(final ImageBuilder imageBuilder, final int[] samples, final int x, final int y) throws ImagingException, IOException { 060 final int Y = samples[0]; 061 final int cb = samples[1]; 062 final int cr = samples[2]; 063 final double r = Y + 1.402 * (cr - 128.0); 064 final double g = Y - 0.34414 * (cb - 128.0) - 0.71414 * (cr - 128.0); 065 final double b = Y + 1.772 * (cb - 128.0); 066 067 final int red = limit((int) r, 0, 255); 068 final int green = limit((int) g, 0, 255); 069 final int blue = limit((int) b, 0, 255); 070 071 final int alpha = 0xff; 072 final int rgb = alpha << 24 | red << 16 | green << 8 | blue << 0; 073 imageBuilder.setRgb(x, y, rgb); 074 075 } 076}