001/* ***** BEGIN LICENSE BLOCK ***** 002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 003 * 004 * The contents of this file are subject to the Mozilla Public License Version 005 * 1.1 (the "License"); you may not use this file except in compliance with 006 * the License. You may obtain a copy of the License at 007 * http://www.mozilla.org/MPL/ 008 * 009 * Software distributed under the License is distributed on an "AS IS" basis, 010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 011 * for the specific language governing rights and limitations under the 012 * License. 013 * 014 * The Original Code is part of dcm4che, an implementation of DICOM(TM) in 015 * Java(TM), hosted at https://github.com/gunterze/dcm4che. 016 * 017 * The Initial Developer of the Original Code is 018 * Agfa Healthcare. 019 * Portions created by the Initial Developer are Copyright (C) 2013 020 * the Initial Developer. All Rights Reserved. 021 * 022 * Contributor(s): 023 * See @authors listed below 024 * 025 * Alternatively, the contents of this file may be used under the terms of 026 * either the GNU General Public License Version 2 or later (the "GPL"), or 027 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 028 * in which case the provisions of the GPL or the LGPL are applicable instead 029 * of those above. If you wish to allow use of your version of this file only 030 * under the terms of either the GPL or the LGPL, and not to allow others to 031 * use your version of this file under the terms of the MPL, indicate your 032 * decision by deleting the provisions above and replace them with the notice 033 * and other provisions required by the GPL or the LGPL. If you do not delete 034 * the provisions above, a recipient may use your version of this file under 035 * the terms of any one of the MPL, the GPL or the LGPL. 036 * 037 * ***** END LICENSE BLOCK ***** */ 038 039package org.dcm4che3.image; 040 041/** 042 * @author Gunter Zeilinger <gunterze@gmail.com> 043 * 044 */ 045public enum YBR { 046 FULL { 047 @Override 048 public float[] toRGB(float[] ybr) { 049 return convert(ybr, FROM_YBR_FULL); 050 } 051 052 @Override 053 public float[] fromRGB(float[] rgb) { 054 return convert(rgb, TO_YBR_FULL); 055 } 056 }, 057 PARTIAL { 058 @Override 059 public float[] toRGB(float[] ybr) { 060 return convert(ybr, FROM_YBR_PARTIAL); 061 } 062 063 @Override 064 public float[] fromRGB(float[] rgb) { 065 return convert(rgb, TO_YBR_PARTIAL); 066 } 067 }; 068 069 private static double[] TO_YBR_FULL = { 070 0.2990, 0.5870, 0.1140, 0.0, 071 -0.1687, -0.3313, 0.5, 0.5, 072 0.5, -0.4187, -0.0813, 0.5 073 }; 074 075 private static double[] TO_YBR_PARTIAL = { 076 0.2568, 0.5041, 0.0979, 0.0625, 077 -0.1482, -0.2910, 0.4392, 0.5, 078 0.4392, -0.3678, -0.0714, 0.5 079 }; 080 081 private static final double[] FROM_YBR_FULL = { 082 1.0, -3.681999032610751E-5, 1.4019875769352639, -0.7009753784724688, 083 1.0, -0.34411328131331737, -0.7141038211151132, 0.5291085512142153, 084 1.0, 1.7719781167370596, -1.345834129159976E-4, -0.8859217666620718, 085 }; 086 087 private static final double[] FROM_YBR_PARTIAL = { 088 1.1644154634373545, -9.503599204778129E-5, 1.5960018776303868, -0.8707293872840042, 089 1.1644154634373545, -0.39172456367367336, -0.8130133682767554, 0.5295929995103797, 090 1.1644154634373545, 2.017290682233469, -1.3527300480981362E-4, -1.0813536710791642, 091 }; 092 093 public abstract float[] toRGB(float[] ybr); 094 095 public abstract float[] fromRGB(float[] rgb); 096 097 private static float[] convert(float[] in, double[] a) { 098 return new float[] { 099 (float) Math.max(0.0, Math.min(1.0, 100 a[0] * in[0] 101 + a[1] * in[1] 102 + a[2] * in[2] 103 + a[3])), 104 (float) Math.max(0.0, Math.min(1.0, 105 a[4] * in[0] 106 + a[5] * in[1] 107 + a[6] * in[2] 108 + a[7])), 109 (float) Math.max(0.0, Math.min(1.0, 110 a[8] * in[0] 111 + a[9] * in[1] 112 + a[10] * in[2] 113 + a[11]))}; 114 } 115 116// public static void main(String[] args) { 117// out("FROM_YBR_FULL", invert(TO_YBR_FULL)); 118// out("FROM_YBR_PARTIAL", invert(TO_YBR_PARTIAL)); 119// } 120// 121// private static void out(String label, double[] a) { 122// StringBuffer sb = new StringBuffer(); 123// sb.append("\n private static final double[] "); 124// sb.append(label); 125// sb.append(" = {"); 126// for (int i = 0; i < a.length; i++) { 127// if (i % 4 == 0) 128// sb.append("\n "); 129// sb.append(a[i]); 130// sb.append(", "); 131// } 132// sb.append("\n };"); 133// System.out.println(sb.toString()); 134// } 135// 136// private static double[] invert(double[] a) { 137// double[] b = new double[12]; 138// double det = a[0]*a[5]*a[10] + a[1]*a[6]*a[8] + a[2]*a[4]*a[9] 139// - a[2]*a[5]*a[8] - a[1]*a[4]*a[10] - a[0]*a[6]*a[9]; 140// b[0] = (a[5]*a[10] - a[6]*a[9]) / det; 141// b[1] = (a[2]*a[9] - a[1]*a[10]) / det; 142// b[2] = (a[1]*a[6] - a[2]*a[5]) / det; 143// b[3] = (a[2]*a[5]*a[11] + a[1]*a[7]*a[10] + a[3]*a[6]*a[9] 144// - a[3]*a[5]*a[10] - a[1]*a[6]*a[11] - a[2]*a[7]*a[9]) / det; 145// b[4] = (a[6]*a[8] - a[4]*a[10]) / det; 146// b[5] = (a[0]*a[10] - a[2]*a[8]) / det; 147// b[6] = (a[2]*a[4] - a[0]*a[6]) / det; 148// b[7] = (a[2]*a[7]*a[8] + a[3]*a[4]*a[10] + a[0]*a[6]*a[11] 149// - a[0]*a[7]*a[10] - a[3]*a[6]*a[8] - a[2]*a[4]*a[11]) / det; 150// b[8] = (a[4]*a[9] - a[5]*a[8]) / det; 151// b[9] = (a[1]*a[8] - a[0]*a[9]) / det; 152// b[10] = (a[0]*a[5] - a[1]*a[4]) / det; 153// b[11] = (a[3]*a[5]*a[8] + a[1]*a[4]*a[11] + a[0]*a[7]*a[9] 154// - a[0]*a[5]*a[11] - a[1]*a[7]*a[8] - a[3]*a[4]*a[9]) / det; 155// return b; 156// } 157 158}