1 /* Copyright (C) 2005-2011 Fabio Riccardi */
2 
3 package com.lightcrafts.jai.opimage;
4 
5 import com.lightcrafts.mediax.jai.ImageLayout;
6 import com.lightcrafts.mediax.jai.PointOpImage;
7 import com.lightcrafts.mediax.jai.RasterFormatTag;
8 import com.lightcrafts.mediax.jai.RasterAccessor;
9 import java.awt.image.RenderedImage;
10 import java.awt.image.Raster;
11 import java.awt.image.WritableRaster;
12 import java.awt.image.DataBuffer;
13 import java.awt.*;
14 import java.util.Map;
15 
16 public class RawAdjustmentsOpImage extends PointOpImage {
17     private float exposureCompensation;
18     private float[][] cameraRGB;
19 
RawAdjustmentsOpImage(RenderedImage source, Map config, ImageLayout layout, float exposureCompensation, float colorTemperature, float[][] cameraRGB)20     public RawAdjustmentsOpImage(RenderedImage source,
21                                 Map config,
22                                 ImageLayout layout,
23                                 float exposureCompensation,
24                                 float colorTemperature,
25                                 float[][] cameraRGB) {
26         super(source, layout, config, true);
27 
28         this.exposureCompensation = exposureCompensation;
29         this.cameraRGB = cameraRGB;
30 
31         permitInPlaceOperation();
32     }
33 
computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect)34     protected void computeRect(Raster[] sources,
35                                WritableRaster dest,
36                                Rectangle destRect) {
37         // Retrieve format tags.
38         RasterFormatTag[] formatTags = getFormatTags();
39 
40         Raster source = sources[0];
41         Rectangle srcRect = mapDestRect(destRect, 0);
42 
43         RasterAccessor srcAccessor =
44                 new RasterAccessor(source, srcRect, formatTags[0],
45                                    getSourceImage(0).getColorModel());
46         RasterAccessor dstAccessor =
47                 new RasterAccessor(dest, destRect, formatTags[1],
48                                    this.getColorModel());
49 
50         switch (dstAccessor.getDataType()) {
51         case DataBuffer.TYPE_USHORT:
52             ushortLoop(srcAccessor, dstAccessor);
53             break;
54         default:
55         }
56 
57         // If the RasterAccessor object set up a temporary buffer for the
58         // op to write to, tell the RasterAccessor to write that data
59         // to the raster no that we're done with it.
60         if (dstAccessor.isDataCopy()) {
61             dstAccessor.clampDataArrays();
62             dstAccessor.copyDataToRaster();
63         }
64     }
65 
ushortLoop(RasterAccessor src, RasterAccessor dst)66     protected void ushortLoop(RasterAccessor src, RasterAccessor dst) {
67         int width = src.getWidth();
68         int height = src.getHeight();
69 
70         short dstDataArrays[][] = dst.getShortDataArrays();
71         int dstBandOffsets[] = dst.getBandOffsets();
72         int dstLineStride = dst.getScanlineStride();
73 
74         short srcDataArrays[][] = src.getShortDataArrays();
75         int srcBandOffsets[] = src.getBandOffsets();
76         int srcLineStride = src.getScanlineStride();
77 
78         short dstData[] = dstDataArrays[0];
79         short srcData[] = srcDataArrays[0];
80 
81         int srcROffset = srcBandOffsets[0];
82         int srcGOffset = srcBandOffsets[1];
83         int srcBOffset = srcBandOffsets[2];
84 
85         int dstROffset = dstBandOffsets[0];
86         int dstGOffset = dstBandOffsets[1];
87         int dstBOffset = dstBandOffsets[2];
88 
89         float t00 = cameraRGB[0][0], t01 = cameraRGB[0][1], t02 = cameraRGB[0][2],
90               t10 = cameraRGB[1][0], t11 = cameraRGB[1][1], t12 = cameraRGB[1][2],
91               t20 = cameraRGB[2][0], t21 = cameraRGB[2][1], t22 = cameraRGB[2][2];
92 
93         for (int row = 0; row < height; row++) {
94             for (int col = 0; col < width; col++) {
95                 int r = 0xffff & srcData[3 * col + row * srcLineStride + srcROffset];
96                 int g = 0xffff & srcData[3 * col + row * srcLineStride + srcGOffset];
97                 int b = 0xffff & srcData[3 * col + row * srcLineStride + srcBOffset];
98 
99                 float r1 = t00 * r + t01 * g + t02 * b;
100                 float g1 = t10 * r + t11 * g + t12 * b;
101                 float b1 = t20 * r + t21 * g + t22 * b;
102 
103                 // Highlight recovery code
104 
105                 float c = exposureCompensation;
106 
107                 if (c < 1 && (g1 > 0xffff || r1 > 0xffff || b1 > 0xffff)) {
108                     float rs = Math.min(r1, 0xffff);
109                     float gs = Math.min(g1, 0xffff);
110                     float bs = Math.min(b1, 0xffff);
111 
112                     float c1s = gs - rs;
113                     float c2s = gs - bs;
114 
115                     r1 = c * (g1 - c1s);
116                     b1 = c * (g1 - c2s);
117                 } else {
118                     r1 *= c;
119                     b1 *= c;
120                 }
121                 g1 *= c;
122 
123                 dstData[3 * col + row * dstLineStride + dstROffset] = (short) (r1 < 0 ? 0 : r1 > 0xffff ? 0xffff : (int) r1);
124                 dstData[3 * col + row * dstLineStride + dstGOffset] = (short) (g1 < 0 ? 0 : g1 > 0xffff ? 0xffff : (int) g1);
125                 dstData[3 * col + row * dstLineStride + dstBOffset] = (short) (b1 < 0 ? 0 : b1 > 0xffff ? 0xffff : (int) b1);
126             }
127         }
128     }
129 }
130