1 /* Copyright (C) 2005-2011 Fabio Riccardi */
2 
3 package com.lightcrafts.jai.opimage;
4 
5 import com.lightcrafts.mediax.jai.PointOpImage;
6 import com.lightcrafts.mediax.jai.ImageLayout;
7 import com.lightcrafts.mediax.jai.RasterAccessor;
8 import com.lightcrafts.mediax.jai.RasterFormatTag;
9 
10 import java.awt.image.*;
11 import java.awt.color.ColorSpace;
12 import java.awt.*;
13 import java.util.Map;
14 
15 /**
16  * Created by IntelliJ IDEA.
17  * User: fabio
18  * Date: Mar 13, 2007
19  * Time: 2:36:29 PM
20  * To change this template use File | Settings | File Templates.
21  */
22 public class RedMaskOpImage extends PointOpImage {
23     private final double tolerance;
24 
createLayout(RenderedImage source)25     private static ImageLayout createLayout(RenderedImage source) {
26         ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
27                                                 false, false,
28                                                 Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
29 
30         ImageLayout layout = new ImageLayout(source);
31         layout.setColorModel(cm);
32         layout.setSampleModel(cm.createCompatibleSampleModel(source.getWidth(), source.getHeight()));
33         return layout;
34     }
35 
RedMaskOpImage(RenderedImage source, double tolerance, Map config)36     public RedMaskOpImage(RenderedImage source, double tolerance, Map config) {
37         super(source, createLayout(source), config, true);
38         this.tolerance = tolerance;
39     }
40 
41     @Override
computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect)42     protected void computeRect(Raster[] sources,
43                                WritableRaster dest,
44                                Rectangle destRect) {
45         // Retrieve format tags.
46         RasterFormatTag[] formatTags = getFormatTags();
47 
48         Raster source = sources[0];
49         Rectangle srcRect = mapDestRect(destRect, 0);
50 
51         RasterAccessor src = new RasterAccessor(source, srcRect, 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_BYTE:
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         byte dstData[] = dst.getByteDataArray(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 srcLOffset = srcBandOffsets[0];
79         int srcAOffset = srcBandOffsets[1];
80         int srcBOffset = srcBandOffsets[2];
81 
82         int dstOffset = dstBandOffsets[0];
83 
84 //        double ra = 68; double radev = 15.3 * tolerance;
85 //        double rb = 39; double rbdev = 14.5 * tolerance;
86 //
87 //        int raMin = (int) ((ra - radev) * 256);
88 //        int raMax = (int) ((ra + radev) * 256);
89 //        int rbMin = (int) ((rb - rbdev) * 256);
90 //        int rbMax = (int) ((rb + rbdev) * 256);
91 //
92 //        double sa = 19; double sadev = 5.1 * 3.5;
93 //        double sb = 17; double sbdev = 2.66 * 3.5;
94 //
95 //        int saMin = (int) ((sa - sadev) * 256);
96 //        int saMax = (int) ((sa + sadev) * 256);
97 //        int sbMin = (int) ((sb - sbdev) * 256);
98 //        int sbMax = (int) ((sb + sbdev) * 256);
99 
100         // Sclera Red
101         int raMin = (int) ((71.5 - 48.5 * tolerance) * 256);
102         int raMax = (int) ((71.5 + 48.5 * tolerance) * 256);
103         int rbMin = (int) ((8 - 35 * tolerance) * 256);
104         int rbMax = (int) ((8 + 35 * tolerance) * 256);
105 
106         // Really Red
107         int rraMin = (int) ((62 - 6.8 * 2) * 256);
108         int rraMax = (int) ((62 + 6.8 * 2) * 256);
109         int rrbMin = (int) ((35 - 6.5 * 2) * 256);
110         int rrbMax = (int) ((35 + 6.5 * 2) * 256);
111 
112         // Kinda Orange
113         int oaMin = (31 - 15 * 2) * 256;
114         int oaMax = (31 + 15 * 2) * 256;
115         int obMin = (56 -  5 * 2) * 256;
116         int obMax = (56 +  5 * 2) * 256;
117 
118         // Magenta
119         // int maMin = ( 30 - 12 * 2) * 256;
120         // int maMax = ( 30 + 12 * 2) * 256;
121         // int mbMin = (-12 - 13 * 2) * 256;
122         // int mbMax = (-12 + 13 * 2) * 256;
123 
124         // Skin
125         int sLMin = (int) (43.3593 * 0xffff / 100);
126         int sLMax = (int) (99.6093 * 0xffff / 100);
127         int saMin = (int) (1.5 * 256);
128         int saMax = (int) (43.125 * 256);
129         int sbMin = (int) (-4.6875 * 256);
130         int sbMax = (int) (34.6875 * 256);
131 
132         for (int row = 0; row < height; row++) {
133             for (int col = 0; col < width; col++) {
134                 int L = 0xffff & srcData[3 * col + row * srcLineStride + srcLOffset];
135                 int a = 0xffff & srcData[srcPixelStride * col + row * srcLineStride + srcAOffset] - 128 * 256;
136                 int b = 0xffff & srcData[srcPixelStride * col + row * srcLineStride + srcBOffset] - 128 * 256;
137 
138                 if (((a > raMin && a < raMax && b > rbMin && b < rbMax)
139                     || (a > oaMin && a < oaMax && b > obMin && b < obMax)
140                     || (a > rraMin && a < rraMax && b > rrbMin && b < rrbMax))
141                     // || (a > maMin && a < maMax && b > mbMin && b < mbMax))
142                      && !(L > sLMin && L < sLMax && a > saMin && a < saMax && b > sbMin && b < sbMax))
143                     dstData[dstPixelStride * col + row * dstLineStride + dstOffset] = (byte) 0xff;
144                 else
145                     dstData[dstPixelStride * col + row * dstLineStride + dstOffset] = (byte) 0;
146             }
147         }
148     }
149 }
150