1 /* Copyright (C) 2005-2011 Fabio Riccardi */ 2 3 package com.lightcrafts.jai.opimage; 4 5 6 import com.lightcrafts.mediax.jai.PointOpImage; 7 import com.lightcrafts.mediax.jai.ImageLayout; 8 import com.lightcrafts.mediax.jai.RasterAccessor; 9 import com.lightcrafts.mediax.jai.RasterFormatTag; 10 import com.lightcrafts.jai.JAIContext; 11 import com.lightcrafts.utils.HSB; 12 13 import java.awt.image.DataBuffer; 14 import java.awt.image.RenderedImage; 15 import java.awt.image.Raster; 16 import java.awt.image.WritableRaster; 17 import java.awt.*; 18 import java.awt.color.ICC_ProfileRGB; 19 import java.util.Map; 20 21 import Jama.Matrix; 22 23 /** 24 * Copyright (C) Light Crafts, Inc. 25 * User: fabio 26 * Date: Mar 20, 2007 27 * Time: 4:32:46 PM 28 */ 29 public class HueRotateOpImage extends PointOpImage { 30 private float angle; 31 private float toSRGB[][]; 32 private float toLinearRGB[][]; 33 HueRotateOpImage(RenderedImage source, float angle, Map config)34 public HueRotateOpImage(RenderedImage source, float angle, Map config) { 35 super(source, new ImageLayout(source), config, true); 36 permitInPlaceOperation(); 37 this.angle = angle; 38 39 ICC_ProfileRGB sRGB = (ICC_ProfileRGB) JAIContext.sRGBColorProfile; 40 toSRGB = new Matrix(sRGB.getMatrix()).inverse().times(new Matrix(((ICC_ProfileRGB) JAIContext.linearProfile).getMatrix())).getArrayFloat(); 41 toLinearRGB = new Matrix(sRGB.getMatrix()).inverse().times(new Matrix(((ICC_ProfileRGB) JAIContext.linearProfile).getMatrix())).inverse().getArrayFloat(); 42 } 43 44 @Override computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect)45 protected void computeRect(Raster[] sources, 46 WritableRaster dest, 47 Rectangle destRect) { 48 // Retrieve format tags. 49 RasterFormatTag[] formatTags = getFormatTags(); 50 51 RasterAccessor src = new RasterAccessor(sources[0], destRect, formatTags[0], 52 getSourceImage(0).getColorModel()); 53 RasterAccessor dst = new RasterAccessor(dest, destRect, formatTags[1], getColorModel()); 54 55 switch (dst.getDataType()) { 56 case DataBuffer.TYPE_USHORT: 57 ushortLoop(src, dst); 58 break; 59 default: 60 throw new UnsupportedOperationException("Unsupported data type: " + dst.getDataType()); 61 } 62 } 63 ushortLoop(RasterAccessor src, RasterAccessor dst)64 protected void ushortLoop(RasterAccessor src, RasterAccessor dst) { 65 int width = src.getWidth(); 66 int height = src.getHeight(); 67 68 short dstData[] = dst.getShortDataArray(0); 69 int dstBandOffsets[] = dst.getBandOffsets(); 70 int dstLineStride = dst.getScanlineStride(); 71 int dstPixelStride = dst.getPixelStride(); 72 73 short srcData[] = src.getShortDataArray(0); 74 int srcBandOffsets[] = src.getBandOffsets(); 75 int srcLineStride = src.getScanlineStride(); 76 int srcPixelStride = src.getPixelStride(); 77 78 int srcROffset = srcBandOffsets[0]; 79 int srcGOffset = srcBandOffsets[1]; 80 int srcBOffset = srcBandOffsets[2]; 81 82 int dstROffset = dstBandOffsets[0]; 83 int dstGOffset = dstBandOffsets[1]; 84 int dstBOffset = dstBandOffsets[2]; 85 86 float rgb[] = new float[3]; 87 float hsi[] = new float[3]; 88 89 for (int row = 0; row < height; row++) { 90 for (int col = 0; col < width; col++) { 91 int srcPixOffset = srcPixelStride * col + row * srcLineStride; 92 int r = (0xffff & srcData[srcPixOffset + srcROffset]); 93 int g = (0xffff & srcData[srcPixOffset + srcGOffset]); 94 int b = (0xffff & srcData[srcPixOffset + srcBOffset]); 95 96 rgb[0] = (toSRGB[0][0] * r + toSRGB[0][1] * g + toSRGB[0][2] * b) / (float) 0xffff; 97 rgb[1] = (toSRGB[1][0] * r + toSRGB[1][1] * g + toSRGB[1][2] * b) / (float) 0xffff; 98 rgb[2] = (toSRGB[2][0] * r + toSRGB[2][1] * g + toSRGB[2][2] * b) / (float) 0xffff; 99 100 HSB.fromRGB(rgb, hsi); 101 102 hsi[0] += angle; 103 104 if (hsi[0] < 0) 105 hsi[0] += 1; 106 else if (hsi[0] >= 1) 107 hsi[0] -= 1; 108 109 HSB.toRGB(hsi, rgb); 110 111 r = (int) (0xffff *(toLinearRGB[0][0] * rgb[0] + toLinearRGB[0][1] * rgb[1] + toLinearRGB[0][2] * rgb[2])); 112 g = (int) (0xffff *(toLinearRGB[1][0] * rgb[0] + toLinearRGB[1][1] * rgb[1] + toLinearRGB[1][2] * rgb[2])); 113 b = (int) (0xffff *(toLinearRGB[2][0] * rgb[0] + toLinearRGB[2][1] * rgb[1] + toLinearRGB[2][2] * rgb[2])); 114 115 int dstPixOffset = dstPixelStride * col + row * dstLineStride; 116 dstData[dstPixOffset + dstROffset] = (short) (r < 0 ? 0 : r > 0xffff ? 0xffff : r); 117 dstData[dstPixOffset + dstGOffset] = (short) (g < 0 ? 0 : g > 0xffff ? 0xffff : g); 118 dstData[dstPixOffset + dstBOffset] = (short) (b < 0 ? 0 : b > 0xffff ? 0xffff : b); 119 } 120 } 121 } 122 } 123