View Javadoc

1   package de.desy.acop.video.displayer.timage;
2   
3   import java.awt.Color;
4   import java.awt.Insets;
5   import java.awt.image.BufferedImage;
6   
7   import de.desy.acop.video.displayer.ColorLookupTable;
8   import de.desy.acop.video.displayer.ColorMap;
9   import de.desy.acop.video.displayer.ImageBuffer;
10  import de.desy.acop.video.displayer.ImageFlag;
11  import de.desy.acop.video.displayer.ImageFormat;
12  import de.desy.tine.types.IMAGE;
13  import de.desy.tine.types.IMAGE.FrameHeader;
14  import de.desy.tine.types.IMAGE.SourceHeader;
15  
16  /**
17   * TINE Image <-> Java BufferedImage Converter.<br>
18   * Note: Draft implementation
19   * 
20   * @author mdavid
21   * @deprecated - use {@link TImageConverter} instead
22   */
23  public class TImageConverter {
24  
25  	/**
26  	 * TINE Buffered Image used for creation/normalization images in memory
27  	 * buffer.
28  	 */
29  	private ImageBuffer _imageBuffer = new ImageBuffer();
30  
31  	/**
32  	 * Currently used color map
33  	 */
34  	private ColorMap _colorMap = ColorMap.GRAYSCALE;
35  
36  	/**
37  	 * Currently used false color lookup.
38  	 */
39  	private ColorLookupTable _colorLookup;
40  
41  	/**
42  	 * Default constructor
43  	 */
44  	public TImageConverter() {
45  		super();
46  	}
47  
48  	/**
49  	 * Creates Java Image from TINE IMAGE
50  	 * 
51  	 * @param timage
52  	 *            - a TINE IMAGE
53  	 * @param aoiExpansion
54  	 *            - if <code>true</code>the AOI Image should be surrounded by
55  	 *            black pixels, otherwise not
56  	 * @return java Image
57  	 */
58  	public BufferedImage parseTineImage(final IMAGE timage, boolean aoiExpansion) {
59  		return parseTineImage(timage, aoiExpansion, ColorMap.GRAYSCALE);
60  	}
61  
62  	/**
63  	 * Creates Java Image from TINE IMAGE
64  	 * 
65  	 * @param timage
66  	 *            - a TINE IMAGE
67  	 * @param aoiExpansion
68  	 *            - if <code>true</code>the AOI Image should be surrounded by
69  	 *            black pixels, otherwise not
70  	 * @param colorMap
71  	 *            - colorMap to be used for conversion
72  	 * @return java BufferedImage
73  	 */
74  	public BufferedImage parseTineImage(final IMAGE timage, boolean aoiExpansion, ColorMap colorMap) {
75  		if (timage == null)
76  			throw new IllegalStateException("timage == null!");
77  
78  		if (colorMap == null)
79  			throw new IllegalStateException("colorMap == null!");
80  
81  		final IMAGE ti = timage.clone();
82  
83  		FrameHeader hdr = ti.getFrameHeader();
84  		ImageFormat imageFormat = ImageFormat.valueOf(hdr.imageFormat);
85  
86  		// adjust false color lookup table
87  		if (imageFormat == ImageFormat.IMAGE_FORMAT_GRAY // 
88  				|| (imageFormat == ImageFormat.IMAGE_FORMAT_JPEG && hdr.bytesPerPixel == 1) //
89  				|| (imageFormat == ImageFormat.IMAGE_FORMAT_HUFFYUV && ImageFormat.IMAGE_FORMAT_GRAY
90  						.equals(hdr.sourceFormat))) {
91  			if (_colorLookup == null // 
92  					|| _colorLookup.getBytesPerPixel() != hdr.bytesPerPixel //
93  					|| _colorLookup.getEffBitsPerPixel() != hdr.effectiveBitsPerPixel || _colorMap != colorMap) {
94  				_colorLookup = new ColorLookupTable(colorMap, hdr.bytesPerPixel, hdr.effectiveBitsPerPixel);
95  				_imageBuffer.setColorLookupTable(_colorLookup.getRGB());
96  			}
97  		}
98  		_colorMap = colorMap;
99  		BufferedImage bi = TImageUtils.toBufferedImage(_imageBuffer.createImage(ti));
100 		if (aoiExpansion && (hdr.aoiWidth != -1 || hdr.aoiHeight != -1))
101 			bi = TImageUtils.addInsets(bi, new Insets(hdr.yStart, hdr.xStart, //
102 					hdr.sourceHeight - hdr.aoiHeight - hdr.yStart, //
103 					hdr.sourceWidth - hdr.aoiWidth - hdr.xStart), Color.black);
104 		return bi;
105 	}
106 
107 	/**
108 	 * Creates Java Image from TINE IMAGE.
109 	 * 
110 	 * @see #parseTineImageNoClone(IMAGE, boolean, ColorMap)
111 	 * @param timage
112 	 *            - a TINE IMAGE
113 	 * @param aoiExpansion
114 	 *            - if <code>true</code>the AOI Image should be surrounded by
115 	 *            black pixels, otherwise not
116 	 * @return java Image
117 	 */
118 	public BufferedImage parseTineImageNoClone(final IMAGE timage, boolean aoiExpansion) {
119 		return parseTineImageNoClone(timage, aoiExpansion, ColorMap.GRAYSCALE);
120 	}
121 
122 	/**
123 	 * Creates Java Image from TINE IMAGE without cloning the original image.
124 	 * This methods is much faster in comparison to
125 	 * {@link #parseTineImage(IMAGE, boolean, ColorMap)}, but be careful about
126 	 * thread safe opeartion: if the given image changes during the execution of
127 	 * this method, that could cause troubles.
128 	 * 
129 	 * @param timage
130 	 *            - a TINE IMAGE
131 	 * @param aoiExpansion
132 	 *            - if <code>true</code>the AOI Image should be surrounded by
133 	 *            black pixels, otherwise not
134 	 * @param colorMap
135 	 *            - colorMap to be used for conversion
136 	 * @return java BufferedImage
137 	 */
138 	public BufferedImage parseTineImageNoClone(final IMAGE timage, boolean aoiExpansion, ColorMap colorMap) {
139 		if (timage == null)
140 			throw new IllegalStateException("timage == null!");
141 
142 		if (colorMap == null)
143 			throw new IllegalStateException("colorMap == null!");
144 
145 		FrameHeader hdr = timage.getFrameHeader();
146 		ImageFormat imageFormat = ImageFormat.valueOf(hdr.imageFormat);
147 
148 		// adjust false color lookup table
149 		if (imageFormat == ImageFormat.IMAGE_FORMAT_GRAY // 
150 				|| (imageFormat == ImageFormat.IMAGE_FORMAT_JPEG && hdr.bytesPerPixel == 1) //
151 				|| (imageFormat == ImageFormat.IMAGE_FORMAT_HUFFYUV && ImageFormat.IMAGE_FORMAT_GRAY
152 						.equals(hdr.sourceFormat))) {
153 			if (_colorLookup == null // 
154 					|| _colorLookup.getBytesPerPixel() != hdr.bytesPerPixel //
155 					|| _colorLookup.getEffBitsPerPixel() != hdr.effectiveBitsPerPixel || _colorMap != colorMap) {
156 				_colorLookup = new ColorLookupTable(colorMap, hdr.bytesPerPixel, hdr.effectiveBitsPerPixel);
157 				_imageBuffer.setColorLookupTable(_colorLookup.getRGB());
158 			}
159 		}
160 		_colorMap = colorMap;
161 		BufferedImage bi = TImageUtils.toBufferedImage(_imageBuffer.createImage(timage));
162 		if (aoiExpansion && (hdr.aoiWidth != -1 || hdr.aoiHeight != -1))
163 			bi = TImageUtils.addInsets(bi, new Insets(hdr.yStart, hdr.xStart, //
164 					hdr.sourceHeight - hdr.aoiHeight - hdr.yStart, //
165 					hdr.sourceWidth - hdr.aoiWidth - hdr.xStart), Color.black);
166 		return bi;
167 	}
168 
169 	/**
170 	 * TODO:
171 	 * 
172 	 * @param src
173 	 * @return TINE Image
174 	 */
175 	@SuppressWarnings("deprecation")
176 	public static IMAGE parseBufferedImage(BufferedImage src) {
177 		if (src == null)
178 			throw new IllegalStateException("src == null!");
179 
180 		// System.out.println("Image Type: " + src.getType());
181 
182 		int width = src.getWidth();
183 		int height = src.getHeight();
184 		int numPixels = width * height;
185 		int bytesPerPixel = 3; // RGB
186 		int[] pixels = src.getRGB(0, 0, width, height, null, 0, width);
187 		if (pixels == null)
188 			throw new IllegalArgumentException("Can't get array of RGB pixels from buffered image!");
189 
190 		final IMAGE timage = new IMAGE(0);
191 
192 		IMAGE.FrameHeader frameHeader = timage.getFrameHeader();
193 		frameHeader.bytesPerPixel = bytesPerPixel;
194 		frameHeader.effectiveBitsPerPixel = 24;
195 		frameHeader.imageFormat = frameHeader.sourceFormat = ImageFormat.IMAGE_FORMAT_RGB.getId();
196 		frameHeader.appendedFrameSize = numPixels * bytesPerPixel;
197 		frameHeader.imageFlags |= ImageFlag.IMAGE_LOSSLESS.getId();
198 		frameHeader.sourceHeight = height;
199 		frameHeader.sourceWidth = width;
200 		frameHeader.xScale = frameHeader.yScale = 1;
201 
202 		IMAGE.SourceHeader sourceHeader = timage.getSourceHeader();
203 		sourceHeader.totalLength = IMAGE.HEADER_SIZE + frameHeader.appendedFrameSize;
204 
205 		int pos = 0;
206 		byte[] buf = new byte[frameHeader.appendedFrameSize];
207 		for (int i = 0; i < numPixels; i++) {
208 			buf[pos++] = (byte) ((pixels[i] >> 16) & 0xff); // R
209 			buf[pos++] = (byte) ((pixels[i] >> 8) & 0xff); // G
210 			buf[pos++] = (byte) (pixels[i] & 0xff); // B
211 		}
212 
213 		timage.setImageFrameBuffer(buf);
214 		return timage;
215 	}
216 
217 	/**
218 	 * TODO:
219 	 * 
220 	 * - resets aoi parameters - only for TYPE_INT_RGB/TYPE_INT_GRAY java images
221 	 * - fraHeader and srcHeader are in/out parameters; application developer
222 	 * will preset them and some fields may be changed inside method according
223 	 * to bufferedImage characteristics - bufferedImage should be "easily"
224 	 * converted to IMAGE, e.g. datatype ARGB of BufferedImage will become
225 	 * datatype ARGB in TINE IMAGE (same for Gray8, 16, 24, RGB24...) - fields
226 	 * in fraHeader and srcHeader which cannot be affected by bufferedImage
227 	 * should NOT be touched - fields in fraHeader and srcHeader which are bound
228 	 * to properties (like width, height, ...) of bufferedImage should be
229 	 * changed to bufferedImage "fields" (ie. bufferedImage takes precedence
230 	 * over settings encoded in fraHeader and srcHeader) * - shall flag LOSSLESS
231 	 * in fraHeader be reset (because what's put in here is typically not some
232 	 * thing lossless from the image source on)?
233 	 * 
234 	 * @param bi
235 	 *            - input buffered image
236 	 * @param frameHeader
237 	 *            - in/out TINE frame header
238 	 * @param sourceHeader
239 	 *            - in/out TINE source header
240 	 * @return
241 	 */
242 	@SuppressWarnings("deprecation")
243 	public static IMAGE parseBufferedImage(BufferedImage bi, FrameHeader frameHeader, SourceHeader sourceHeader) {
244 		if (bi == null)
245 			throw new IllegalStateException("bi == null!");
246 
247 		if (frameHeader == null)
248 			throw new IllegalStateException("frameHeader == null!");
249 
250 		if (sourceHeader == null)
251 			throw new IllegalStateException("sourceHeader == null!");
252 
253 		int width = bi.getWidth();
254 		int height = bi.getHeight();
255 		int[] pixels = bi.getRGB(0, 0, width, height, null, 0, width);
256 		if (pixels == null)
257 			throw new IllegalArgumentException("Can't get array of RGB pixels from buffered image!");
258 
259 		int numPixels = width * height;
260 
261 		int itype = bi.getType();
262 
263 		int pos = 0;
264 		byte[] buf;
265 
266 		switch (itype) {
267 		case BufferedImage.TYPE_INT_RGB:
268 			// case BufferedImage.TYPE_INT_ARGB:
269 			frameHeader.bytesPerPixel = 3;
270 			frameHeader.effectiveBitsPerPixel = 24;
271 			frameHeader.imageFormat = frameHeader.sourceFormat = ImageFormat.IMAGE_FORMAT_RGB.getId();
272 			frameHeader.appendedFrameSize = numPixels * frameHeader.bytesPerPixel;
273 
274 			buf = new byte[frameHeader.appendedFrameSize];
275 
276 			for (int i = 0; i < numPixels; i++) {
277 				buf[pos++] = (byte) ((pixels[i] >> 16) & 0xff); // R
278 				buf[pos++] = (byte) ((pixels[i] >> 8) & 0xff); // G
279 				buf[pos++] = (byte) (pixels[i] & 0xff); // B
280 			}
281 			break;
282 
283 		case BufferedImage.TYPE_BYTE_GRAY:
284 			frameHeader.bytesPerPixel = 1;
285 			frameHeader.effectiveBitsPerPixel = 8;
286 			frameHeader.imageFormat = frameHeader.sourceFormat = ImageFormat.IMAGE_FORMAT_GRAY.getId();
287 			frameHeader.appendedFrameSize = numPixels * frameHeader.bytesPerPixel;
288 
289 			buf = new byte[frameHeader.appendedFrameSize];
290 
291 			for (int i = 0; i < numPixels; i++)
292 				buf[i] = (byte) (pixels[i] & 0xff);
293 
294 			break;
295 
296 		default:
297 			throw new IllegalArgumentException("Unsupported type of buffered image: " + itype);
298 		}
299 
300 		frameHeader.sourceWidth = width;
301 		frameHeader.sourceHeight = height;
302 
303 		frameHeader.aoiHeight = frameHeader.aoiWidth = -1;
304 		frameHeader.xStart = frameHeader.yStart = -1;
305 
306 		final IMAGE timage = new IMAGE(0);
307 		TImageUtils.setFrameHeader(timage, frameHeader);
308 		TImageUtils.setSourceHeader(timage, sourceHeader);
309 		timage.setImageFrameBuffer(buf);
310 
311 		return timage;
312 	}
313 }