97 int height; |
97 int height; |
98 int nextRowOffset; |
98 int nextRowOffset; |
99 int offset; |
99 int offset; |
100 |
100 |
101 Object dataArray; |
101 Object dataArray; |
102 private LCMSImageLayout(int np, int pixelType, int pixelSize) { |
102 private int dataArrayLength; /* in bytes */ |
|
103 |
|
104 private LCMSImageLayout(int np, int pixelType, int pixelSize) |
|
105 throws ImageLayoutException |
|
106 { |
103 this.pixelType = pixelType; |
107 this.pixelType = pixelType; |
104 width = np; |
108 width = np; |
105 height = 1; |
109 height = 1; |
106 nextRowOffset = np*pixelSize; |
110 nextRowOffset = safeMult(pixelSize, np); |
107 offset = 0; |
111 offset = 0; |
108 } |
112 } |
109 |
113 |
110 private LCMSImageLayout(int width, int height, int pixelType, |
114 private LCMSImageLayout(int width, int height, int pixelType, |
111 int pixelSize) { |
115 int pixelSize) |
|
116 throws ImageLayoutException |
|
117 { |
112 this.pixelType = pixelType; |
118 this.pixelType = pixelType; |
113 this.width = width; |
119 this.width = width; |
114 this.height = height; |
120 this.height = height; |
115 nextRowOffset = width*pixelSize; |
121 nextRowOffset = safeMult(pixelSize, width); |
116 offset = 0; |
122 offset = 0; |
117 } |
123 } |
118 |
124 |
119 |
125 |
120 public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) { |
126 public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) |
|
127 throws ImageLayoutException |
|
128 { |
121 this(np, pixelType, pixelSize); |
129 this(np, pixelType, pixelSize); |
122 dataType = DT_BYTE; |
130 dataType = DT_BYTE; |
123 dataArray = data; |
131 dataArray = data; |
124 } |
132 dataArrayLength = data.length; |
125 |
133 |
126 public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize) { |
134 verify(); |
|
135 } |
|
136 |
|
137 public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize) |
|
138 throws ImageLayoutException |
|
139 { |
127 this(np, pixelType, pixelSize); |
140 this(np, pixelType, pixelSize); |
128 dataType = DT_SHORT; |
141 dataType = DT_SHORT; |
129 dataArray = data; |
142 dataArray = data; |
130 } |
143 dataArrayLength = 2 * data.length; |
131 |
144 |
132 public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize) { |
145 verify(); |
|
146 } |
|
147 |
|
148 public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize) |
|
149 throws ImageLayoutException |
|
150 { |
133 this(np, pixelType, pixelSize); |
151 this(np, pixelType, pixelSize); |
134 dataType = DT_INT; |
152 dataType = DT_INT; |
135 dataArray = data; |
153 dataArray = data; |
|
154 dataArrayLength = 4 * data.length; |
|
155 |
|
156 verify(); |
136 } |
157 } |
137 |
158 |
138 public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) |
159 public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) |
|
160 throws ImageLayoutException |
139 { |
161 { |
140 this(np, pixelType, pixelSize); |
162 this(np, pixelType, pixelSize); |
141 dataType = DT_DOUBLE; |
163 dataType = DT_DOUBLE; |
142 dataArray = data; |
164 dataArray = data; |
143 } |
165 dataArrayLength = 8 * data.length; |
144 |
166 |
145 public LCMSImageLayout(BufferedImage image) { |
167 verify(); |
|
168 } |
|
169 |
|
170 public LCMSImageLayout(BufferedImage image) throws ImageLayoutException { |
146 ShortComponentRaster shortRaster; |
171 ShortComponentRaster shortRaster; |
147 IntegerComponentRaster intRaster; |
172 IntegerComponentRaster intRaster; |
148 ByteComponentRaster byteRaster; |
173 ByteComponentRaster byteRaster; |
149 switch (image.getType()) { |
174 switch (image.getType()) { |
150 case BufferedImage.TYPE_INT_RGB: |
175 case BufferedImage.TYPE_INT_RGB: |
184 switch (image.getType()) { |
209 switch (image.getType()) { |
185 case BufferedImage.TYPE_INT_RGB: |
210 case BufferedImage.TYPE_INT_RGB: |
186 case BufferedImage.TYPE_INT_ARGB: |
211 case BufferedImage.TYPE_INT_ARGB: |
187 case BufferedImage.TYPE_INT_BGR: |
212 case BufferedImage.TYPE_INT_BGR: |
188 intRaster = (IntegerComponentRaster)image.getRaster(); |
213 intRaster = (IntegerComponentRaster)image.getRaster(); |
189 nextRowOffset = intRaster.getScanlineStride()*4; |
214 |
190 offset = intRaster.getDataOffset(0)*4; |
215 nextRowOffset = safeMult(4, intRaster.getScanlineStride()); |
|
216 |
|
217 offset = safeMult(4, intRaster.getDataOffset(0)); |
|
218 |
191 dataArray = intRaster.getDataStorage(); |
219 dataArray = intRaster.getDataStorage(); |
|
220 dataArrayLength = 4 * intRaster.getDataStorage().length; |
192 dataType = DT_INT; |
221 dataType = DT_INT; |
193 break; |
222 break; |
194 |
223 |
195 case BufferedImage.TYPE_3BYTE_BGR: |
224 case BufferedImage.TYPE_3BYTE_BGR: |
196 case BufferedImage.TYPE_4BYTE_ABGR: |
225 case BufferedImage.TYPE_4BYTE_ABGR: |
197 byteRaster = (ByteComponentRaster)image.getRaster(); |
226 byteRaster = (ByteComponentRaster)image.getRaster(); |
198 nextRowOffset = byteRaster.getScanlineStride(); |
227 nextRowOffset = byteRaster.getScanlineStride(); |
199 int firstBand = image.getSampleModel().getNumBands() - 1; |
228 int firstBand = image.getSampleModel().getNumBands() - 1; |
200 offset = byteRaster.getDataOffset(firstBand); |
229 offset = byteRaster.getDataOffset(firstBand); |
201 dataArray = byteRaster.getDataStorage(); |
230 dataArray = byteRaster.getDataStorage(); |
|
231 dataArrayLength = byteRaster.getDataStorage().length; |
202 dataType = DT_BYTE; |
232 dataType = DT_BYTE; |
203 break; |
233 break; |
204 |
234 |
205 case BufferedImage.TYPE_BYTE_GRAY: |
235 case BufferedImage.TYPE_BYTE_GRAY: |
206 byteRaster = (ByteComponentRaster)image.getRaster(); |
236 byteRaster = (ByteComponentRaster)image.getRaster(); |
207 nextRowOffset = byteRaster.getScanlineStride(); |
237 nextRowOffset = byteRaster.getScanlineStride(); |
208 offset = byteRaster.getDataOffset(0); |
238 offset = byteRaster.getDataOffset(0); |
209 dataArray = byteRaster.getDataStorage(); |
239 dataArray = byteRaster.getDataStorage(); |
|
240 dataArrayLength = byteRaster.getDataStorage().length; |
210 dataType = DT_BYTE; |
241 dataType = DT_BYTE; |
211 break; |
242 break; |
212 |
243 |
213 case BufferedImage.TYPE_USHORT_GRAY: |
244 case BufferedImage.TYPE_USHORT_GRAY: |
214 shortRaster = (ShortComponentRaster)image.getRaster(); |
245 shortRaster = (ShortComponentRaster)image.getRaster(); |
215 nextRowOffset = shortRaster.getScanlineStride()*2; |
246 nextRowOffset = safeMult(2, shortRaster.getScanlineStride()); |
216 offset = shortRaster.getDataOffset(0) * 2; |
247 offset = safeMult(2, shortRaster.getDataOffset(0)); |
217 dataArray = shortRaster.getDataStorage(); |
248 dataArray = shortRaster.getDataStorage(); |
|
249 dataArrayLength = 2 * shortRaster.getDataStorage().length; |
218 dataType = DT_SHORT; |
250 dataType = DT_SHORT; |
219 break; |
251 break; |
220 } |
252 } |
|
253 verify(); |
221 } |
254 } |
222 |
255 |
223 public static boolean isSupported(BufferedImage image) { |
256 public static boolean isSupported(BufferedImage image) { |
224 switch (image.getType()) { |
257 switch (image.getType()) { |
225 case BufferedImage.TYPE_INT_RGB: |
258 case BufferedImage.TYPE_INT_RGB: |
231 case BufferedImage.TYPE_USHORT_GRAY: |
264 case BufferedImage.TYPE_USHORT_GRAY: |
232 return true; |
265 return true; |
233 } |
266 } |
234 return false; |
267 return false; |
235 } |
268 } |
|
269 |
|
270 private void verify() throws ImageLayoutException { |
|
271 |
|
272 if (offset < 0 || offset >= dataArrayLength) { |
|
273 throw new ImageLayoutException("Invalid image layout"); |
|
274 } |
|
275 |
|
276 int lastPixelOffset = safeMult(nextRowOffset, (height - 1)); |
|
277 |
|
278 lastPixelOffset = safeAdd(lastPixelOffset, (width - 1)); |
|
279 |
|
280 int off = safeAdd(offset, lastPixelOffset); |
|
281 |
|
282 if (off < 0 || off >= dataArrayLength) { |
|
283 throw new ImageLayoutException("Invalid image layout"); |
|
284 } |
|
285 } |
|
286 |
|
287 static int safeAdd(int a, int b) throws ImageLayoutException { |
|
288 long res = a; |
|
289 res += b; |
|
290 if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) { |
|
291 throw new ImageLayoutException("Invalid image layout"); |
|
292 } |
|
293 return (int)res; |
|
294 } |
|
295 |
|
296 static int safeMult(int a, int b) throws ImageLayoutException { |
|
297 long res = a; |
|
298 res *= b; |
|
299 if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) { |
|
300 throw new ImageLayoutException("Invalid image layout"); |
|
301 } |
|
302 return (int)res; |
|
303 } |
|
304 |
|
305 public static class ImageLayoutException extends Exception { |
|
306 public ImageLayoutException(String message) { |
|
307 super(message); |
|
308 } |
|
309 } |
236 } |
310 } |