1 | /* |
2 | Copyright 2006 Jerry Huxtable |
3 | |
4 | Licensed under the Apache License, Version 2.0 (the "License"); |
5 | you may not use this file except in compliance with the License. |
6 | You may obtain a copy of the License at |
7 | |
8 | http://www.apache.org/licenses/LICENSE-2.0 |
9 | |
10 | Unless required by applicable law or agreed to in writing, software |
11 | distributed under the License is distributed on an "AS IS" BASIS, |
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | See the License for the specific language governing permissions and |
14 | limitations under the License. |
15 | */ |
16 | |
17 | /** |
18 | * Some more useful math functions for image processing. |
19 | * These are becoming obsolete as we move to Java2D. Use MiscComposite instead. |
20 | */ |
21 | sclass PixelUtils { |
22 | public final static int REPLACE = 0; |
23 | public final static int NORMAL = 1; |
24 | public final static int MIN = 2; |
25 | public final static int MAX = 3; |
26 | public final static int ADD = 4; |
27 | public final static int SUBTRACT = 5; |
28 | public final static int DIFFERENCE = 6; |
29 | public final static int MULTIPLY = 7; |
30 | public final static int HUE = 8; |
31 | public final static int SATURATION = 9; |
32 | public final static int VALUE = 10; |
33 | public final static int COLOR = 11; |
34 | public final static int SCREEN = 12; |
35 | public final static int AVERAGE = 13; |
36 | public final static int OVERLAY = 14; |
37 | public final static int CLEAR = 15; |
38 | public final static int EXCHANGE = 16; |
39 | public final static int DISSOLVE = 17; |
40 | public final static int DST_IN = 18; |
41 | public final static int ALPHA = 19; |
42 | public final static int ALPHA_TO_GRAY = 20; |
43 | |
44 | private static Random randomGenerator = new Random(); |
45 | |
46 | /** |
47 | * Clamp a value to the range 0..255 |
48 | */ |
49 | static int _clamp(int c) { |
50 | if (c < 0) |
51 | return 0; |
52 | if (c > 255) |
53 | return 255; |
54 | return c; |
55 | } |
56 | |
57 | public static int interpolate(int v1, int v2, float f) { |
58 | return _clamp((int)(v1+f*(v2-v1))); |
59 | } |
60 | |
61 | public static int brightness(int rgb) { |
62 | int r = (rgb >> 16) & 0xff; |
63 | int g = (rgb >> 8) & 0xff; |
64 | int b = rgb & 0xff; |
65 | return (r+g+b)/3; |
66 | } |
67 | |
68 | public static boolean nearColors(int rgb1, int rgb2, int tolerance) { |
69 | int r1 = (rgb1 >> 16) & 0xff; |
70 | int g1 = (rgb1 >> 8) & 0xff; |
71 | int b1 = rgb1 & 0xff; |
72 | int r2 = (rgb2 >> 16) & 0xff; |
73 | int g2 = (rgb2 >> 8) & 0xff; |
74 | int b2 = rgb2 & 0xff; |
75 | return Math.abs(r1-r2) <= tolerance && Math.abs(g1-g2) <= tolerance && Math.abs(b1-b2) <= tolerance; |
76 | } |
77 | |
78 | private final static float hsb1[] = new float[3];//FIXME-not thread safe |
79 | private final static float hsb2[] = new float[3];//FIXME-not thread safe |
80 | |
81 | // Return rgb1 painted onto rgb2 |
82 | public static int combinePixels(int rgb1, int rgb2, int op) { |
83 | return combinePixels(rgb1, rgb2, op, 0xff); |
84 | } |
85 | |
86 | public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha, int channelMask) { |
87 | return (rgb2 & ~channelMask) | combinePixels(rgb1 & channelMask, rgb2, op, extraAlpha); |
88 | } |
89 | |
90 | public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha) { |
91 | if (op == REPLACE) |
92 | return rgb1; |
93 | int a1 = (rgb1 >> 24) & 0xff; |
94 | int r1 = (rgb1 >> 16) & 0xff; |
95 | int g1 = (rgb1 >> 8) & 0xff; |
96 | int b1 = rgb1 & 0xff; |
97 | int a2 = (rgb2 >> 24) & 0xff; |
98 | int r2 = (rgb2 >> 16) & 0xff; |
99 | int g2 = (rgb2 >> 8) & 0xff; |
100 | int b2 = rgb2 & 0xff; |
101 | |
102 | switch (op) { |
103 | case NORMAL: |
104 | break; |
105 | case MIN: |
106 | r1 = Math.min(r1, r2); |
107 | g1 = Math.min(g1, g2); |
108 | b1 = Math.min(b1, b2); |
109 | break; |
110 | case MAX: |
111 | r1 = Math.max(r1, r2); |
112 | g1 = Math.max(g1, g2); |
113 | b1 = Math.max(b1, b2); |
114 | break; |
115 | case ADD: |
116 | r1 = _clamp(r1+r2); |
117 | g1 = _clamp(g1+g2); |
118 | b1 = _clamp(b1+b2); |
119 | break; |
120 | case SUBTRACT: |
121 | r1 = _clamp(r2-r1); |
122 | g1 = _clamp(g2-g1); |
123 | b1 = _clamp(b2-b1); |
124 | break; |
125 | case DIFFERENCE: |
126 | r1 = _clamp(Math.abs(r1-r2)); |
127 | g1 = _clamp(Math.abs(g1-g2)); |
128 | b1 = _clamp(Math.abs(b1-b2)); |
129 | break; |
130 | case MULTIPLY: |
131 | r1 = _clamp(r1*r2/255); |
132 | g1 = _clamp(g1*g2/255); |
133 | b1 = _clamp(b1*b2/255); |
134 | break; |
135 | case DISSOLVE: |
136 | if ((randomGenerator.nextInt() & 0xff) <= a1) { |
137 | r1 = r2; |
138 | g1 = g2; |
139 | b1 = b2; |
140 | } |
141 | break; |
142 | case AVERAGE: |
143 | r1 = (r1+r2)/2; |
144 | g1 = (g1+g2)/2; |
145 | b1 = (b1+b2)/2; |
146 | break; |
147 | case HUE: |
148 | case SATURATION: |
149 | case VALUE: |
150 | case COLOR: |
151 | Color.RGBtoHSB(r1, g1, b1, hsb1); |
152 | Color.RGBtoHSB(r2, g2, b2, hsb2); |
153 | switch (op) { |
154 | case HUE: |
155 | hsb2[0] = hsb1[0]; |
156 | break; |
157 | case SATURATION: |
158 | hsb2[1] = hsb1[1]; |
159 | break; |
160 | case VALUE: |
161 | hsb2[2] = hsb1[2]; |
162 | break; |
163 | case COLOR: |
164 | hsb2[0] = hsb1[0]; |
165 | hsb2[1] = hsb1[1]; |
166 | break; |
167 | } |
168 | rgb1 = Color.HSBtoRGB(hsb2[0], hsb2[1], hsb2[2]); |
169 | r1 = (rgb1 >> 16) & 0xff; |
170 | g1 = (rgb1 >> 8) & 0xff; |
171 | b1 = rgb1 & 0xff; |
172 | break; |
173 | case SCREEN: |
174 | r1 = 255 - ((255 - r1) * (255 - r2)) / 255; |
175 | g1 = 255 - ((255 - g1) * (255 - g2)) / 255; |
176 | b1 = 255 - ((255 - b1) * (255 - b2)) / 255; |
177 | break; |
178 | case OVERLAY: |
179 | int m, s; |
180 | s = 255 - ((255 - r1) * (255 - r2)) / 255; |
181 | m = r1 * r2 / 255; |
182 | r1 = (s * r1 + m * (255 - r1)) / 255; |
183 | s = 255 - ((255 - g1) * (255 - g2)) / 255; |
184 | m = g1 * g2 / 255; |
185 | g1 = (s * g1 + m * (255 - g1)) / 255; |
186 | s = 255 - ((255 - b1) * (255 - b2)) / 255; |
187 | m = b1 * b2 / 255; |
188 | b1 = (s * b1 + m * (255 - b1)) / 255; |
189 | break; |
190 | case CLEAR: |
191 | r1 = g1 = b1 = 0xff; |
192 | break; |
193 | case DST_IN: |
194 | r1 = _clamp((r2*a1)/255); |
195 | g1 = _clamp((g2*a1)/255); |
196 | b1 = _clamp((b2*a1)/255); |
197 | a1 = _clamp((a2*a1)/255); |
198 | return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; |
199 | case ALPHA: |
200 | a1 = a1*a2/255; |
201 | return (a1 << 24) | (r2 << 16) | (g2 << 8) | b2; |
202 | case ALPHA_TO_GRAY: |
203 | int na = 255-a1; |
204 | return (a1 << 24) | (na << 16) | (na << 8) | na; |
205 | } |
206 | if (extraAlpha != 0xff || a1 != 0xff) { |
207 | a1 = a1*extraAlpha/255; |
208 | int a3 = (255-a1)*a2/255; |
209 | r1 = _clamp((r1*a1+r2*a3)/255); |
210 | g1 = _clamp((g1*a1+g2*a3)/255); |
211 | b1 = _clamp((b1*a1+b2*a3)/255); |
212 | a1 = _clamp(a1+a3); |
213 | } |
214 | return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; |
215 | } |
216 | |
217 | } |
download show line numbers debug dex old transpilations
Travelled to 6 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1024654 |
Snippet name: | PixelUtils |
Eternal ID of this version: | #1024654/2 |
Text MD5: | 4c34676ad22a3a5ae087549799f714f0 |
Author: | stefan |
Category: | javax / imaging |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2019-08-22 00:48:00 |
Source code size: | 6445 bytes / 217 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 261 / 626 |
Version history: | 1 change(s) |
Referenced in: | [show references] |