001: /*
002: * $RCSfile: NioImageBuffer.java,v $
003: *
004: * Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
006: *
007: * This code is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License version 2 only, as
009: * published by the Free Software Foundation. Sun designates this
010: * particular file as subject to the "Classpath" exception as provided
011: * by Sun in the LICENSE file that accompanied this code.
012: *
013: * This code is distributed in the hope that it will be useful, but WITHOUT
014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: * version 2 for more details (a copy is included in the LICENSE file that
017: * accompanied this code).
018: *
019: * You should have received a copy of the GNU General Public License version
020: * 2 along with this work; if not, write to the Free Software Foundation,
021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
024: * CA 95054 USA or visit www.sun.com if you need additional information or
025: * have any questions.
026: *
027: * $Revision: 1.4 $
028: * $Date: 2008/02/28 20:17:26 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import java.nio.Buffer;
035: import java.nio.ByteBuffer;
036: import java.nio.ByteOrder;
037: import java.nio.IntBuffer;
038:
039: /**
040: * The NioImageBuffer class is a container for an image whose DataBuffer
041: * is specified via a java.nio.Buffer. An an NioImageBuffer can be wrapped by
042: * an ImageComponent and used for texture mapping, or for rendering Raster
043: * objects or background images. An NioImageBuffer must not be used as the
044: * buffer of an off-screen Canvas3D, or for reading back a raster image.
045: *
046: * @see ImageComponent2D
047: * @see ImageComponent3D
048: *
049: * @since Java 3D 1.5
050: */
051: public class NioImageBuffer {
052:
053: /**
054: * Used to specify the type of the image.
055: */
056: public enum ImageType {
057: /**
058: * Represents an image with 8-bit RGB color components,
059: * corresponding to a Windows-style BGR color model, with the
060: * colors Blue, Green, and Red stored in 3 consecutive
061: * bytes for each pixel.
062: * The data buffer must be a ByteBuffer when using this imageType.
063: */
064: TYPE_3BYTE_BGR,
065:
066: /**
067: * Represents an image with 8-bit RGB color components with
068: * Red, Green, and Blue, stored in 3 consecutive
069: * bytes for each pixel.
070: * The data buffer must be a ByteBuffer when using this imageType.
071: */
072: TYPE_3BYTE_RGB,
073:
074: /**
075: * Represents an image with 8-bit RGBA color components with
076: * Alpha, Blue, Green, and Red stored in 4 consecutive
077: * bytes for each pixel.
078: * The data buffer must be a ByteBuffer when using this imageType.
079: */
080: TYPE_4BYTE_ABGR,
081:
082: /**
083: * Represents an image with 8-bit RGBA color components with
084: * Red, Green, Blue, and Alpha stored in 4 consecutive
085: * bytes for each pixel.
086: * The data buffer must be a ByteBuffer when using this imageType.
087: */
088: TYPE_4BYTE_RGBA,
089:
090: /**
091: * Represents a unsigned byte grayscale image, non-indexed.
092: * The data buffer must be a ByteBuffer when using this imageType.
093: */
094: TYPE_BYTE_GRAY,
095:
096: /**
097: * Represents an image with 8-bit RGBA color components packed
098: * into integer pixels.
099: * The data buffer must be an IntBuffer when using this imageType.
100: */
101: TYPE_INT_ARGB,
102:
103: /**
104: * Represents an image with 8-bit RGB color components,
105: * corresponding to a Windows- or Solaris- style BGR color model,
106: * with the colors Blue, Green, and Red packed into integer
107: * pixels.
108: * The data buffer must be an IntBuffer when using this imageType.
109: */
110: TYPE_INT_BGR,
111:
112: /**
113: * Represents an image with 8-bit RGB color components packed into
114: * integer pixels.
115: * The data buffer must be an IntBuffer when using this imageType.
116: */
117: TYPE_INT_RGB,
118:
119: }
120:
121: /**
122: * Enum for type of buffer
123: */
124: enum BufferType {
125: BYTE_BUFFER, INT_BUFFER,
126: }
127:
128: // Width and height of image
129: int width;
130: int height;
131:
132: // TYpe of image
133: ImageType imageType;
134:
135: // Cached buffer
136: Buffer buffer;
137:
138: // Type of NIO Buffer: byte or int
139: BufferType bufferType;
140:
141: // Number of bytes allocated per pixel
142: int bytesPerPixel;
143:
144: // Number of byte or int elements per pixel
145: int elementsPerPixel;
146:
147: /**
148: * Constructs an NIO image buffer of the specified size and type.
149: * A direct NIO buffer of the correct type (ByteBuffer or IntBuffer)
150: * and size to match the input parameters
151: * is allocated.
152: *
153: * @param width width of the image
154: * @param height height of the image
155: * @param imageType type of the image.
156: *
157: * @exception IllegalArgumentException if width < 1 or height < 1
158: * @exception NullPointerException if imageType is null
159: */
160: public NioImageBuffer(int width, int height, ImageType imageType) {
161:
162: processParams(width, height, imageType);
163:
164: ByteBuffer tmpBuffer = ByteBuffer.allocateDirect(width * height
165: * bytesPerPixel);
166: switch (bufferType) {
167: case BYTE_BUFFER:
168: buffer = tmpBuffer;
169: break;
170:
171: case INT_BUFFER:
172: buffer = tmpBuffer.order(ByteOrder.nativeOrder())
173: .asIntBuffer();
174: break;
175:
176: default:
177: // We should never get here
178: throw new AssertionError("missing case statement");
179: }
180: }
181:
182: /**
183: * Constructs an NIO image buffer of the specified size and type, using
184: * the specified dataBuffer.
185: * The the byte order of the specified dataBuffer must match the native
186: * byte order of the underlying platform.
187: * For best performance, the NIO buffer should be a direct buffer.
188: *
189: * @param width width of the image
190: * @param height height of the image
191: * @param imageType type of the image.
192: * @param dataBuffer an NIO buffer of the correct type (ByteBuffer or
193: * IntBuffer) to match the specified imageType.
194: * This constructor will create a new view of
195: * the buffer, and will call <code>rewind</code> on that view,
196: * such that elements 0 through <code>dataBuffer.limit()-1</code>
197: * will be available internally. The number of elements in
198: * the buffer must be exactly <code>width*height*numElementsPerPixel</code>,
199: * where <code>numElementsPerPixel</code> is
200: * 3 for TYPE_3BYTE_BGR and TYPE_3BYTE_RGB,
201: * 4 for TYPE_4BYTE_ABGR and TYPE_4BYTE_RGBA,
202: * and 1 for all other types.
203: *
204: * @exception IllegalArgumentException if width < 1 or height < 1
205: * @exception NullPointerException if imageType or dataBuffer is null
206: * @exception IllegalArgumentException if the type of the dataBuffer does
207: * not match the imageType
208: * @exception IllegalArgumentException if <code>dataBuffer.limit() !=
209: * width*height*numElementsPerPixel</code>
210: * @exception IllegalArgumentException if the byte order of the specified
211: * dataBuffer does not match the native byte order of the underlying
212: * platform.
213: */
214: public NioImageBuffer(int width, int height, ImageType imageType,
215: Buffer dataBuffer) {
216:
217: processParams(width, height, imageType);
218: setDataBuffer(dataBuffer);
219: }
220:
221: /**
222: * Gets the width of this data buffer.
223: *
224: * @return the width of this data buffer.
225: */
226: public int getWidth() {
227: return width;
228: }
229:
230: /**
231: * Gets the height of this data buffer.
232: *
233: * @return the width of this data buffer.
234: */
235: public int getHeight() {
236: return height;
237: }
238:
239: /**
240: * Gets the image type of this data buffer.
241: *
242: * @return the image type of this data buffer.
243: */
244: public ImageType getImageType() {
245: return imageType;
246: }
247:
248: /**
249: * Sets the data buffer to the specified input data buffer.
250: * The the byte order of the specified dataBuffer must match the native
251: * byte order of the underlying platform.
252: * For best performance, the NIO buffer should be a direct buffer.
253: *
254: * @param dataBuffer an NIO buffer of the correct type (ByteBuffer or
255: * IntBuffer) to match the imageType of this
256: * NioImageBuffer. This method will create a new view of
257: * the buffer, and will call <code>rewind</code> on that view,
258: * such that elements 0 through <code>dataBuffer.limit()-1</code>
259: * will be available internally. The number of elements in
260: * the buffer must be exactly <code>width*height*numElementsPerPixel</code>,
261: * where <code>numElementsPerPixel</code> is
262: * 3 for TYPE_3BYTE_BGR and TYPE_3BYTE_RGB,
263: * 4 for TYPE_4BYTE_ABGR and TYPE_4BYTE_RGBA,
264: * and 1 for all other types.
265: *
266: * @exception NullPointerException if dataBuffer is null
267: * @exception IllegalArgumentException if the type of the dataBuffer does
268: * not match the imageType
269: * @exception IllegalArgumentException if <code>dataBuffer.limit() !=
270: * width*height*numElementsPerPixel</code>
271: * @exception IllegalArgumentException if the byte order of the specified
272: * dataBuffer does not match the native byte order of the underlying
273: * platform.
274: */
275: public void setDataBuffer(Buffer dataBuffer) {
276: if (dataBuffer == null) {
277: throw new NullPointerException();
278: }
279:
280: if (dataBuffer.limit() != width * height * elementsPerPixel) {
281: throw new IllegalArgumentException(J3dI18N
282: .getString("NioImageBuffer3"));
283: }
284:
285: switch (bufferType) {
286: case BYTE_BUFFER:
287: if (!(dataBuffer instanceof ByteBuffer)) {
288: throw new IllegalArgumentException(J3dI18N
289: .getString("NioImageBuffer4"));
290: }
291: buffer = ((ByteBuffer) dataBuffer).duplicate().rewind();
292: break;
293:
294: case INT_BUFFER:
295: if (!(dataBuffer instanceof IntBuffer)) {
296: throw new IllegalArgumentException(J3dI18N
297: .getString("NioImageBuffer4"));
298: }
299:
300: if (((IntBuffer) dataBuffer).order() != ByteOrder
301: .nativeOrder()) {
302: throw new IllegalArgumentException(J3dI18N
303: .getString("NioImageBuffer5"));
304: }
305: buffer = ((IntBuffer) dataBuffer).duplicate().rewind();
306: break;
307:
308: default:
309: // We should never get here
310: throw new AssertionError("missing case statement");
311: }
312: }
313:
314: /**
315: * Gets the data buffer to the specified input data buffer.
316: *
317: * @return a view of the current data buffer for this NIO image buffer.
318: * This view will be rewound such that elements 0
319: * through <code>dataBuffer.limit()-1</code> are available.
320: */
321: public Buffer getDataBuffer() {
322: Buffer tmpBuffer = null;
323:
324: switch (bufferType) {
325: case BYTE_BUFFER:
326: tmpBuffer = ((ByteBuffer) buffer).duplicate();
327: break;
328:
329: case INT_BUFFER:
330: tmpBuffer = ((IntBuffer) buffer).duplicate();
331: break;
332:
333: default:
334: // We should never get here
335: throw new AssertionError("missing case statement");
336: }
337:
338: return tmpBuffer.rewind();
339: }
340:
341: // Sanity check the input parameters, calculate the buffer type and
342: // the number of bytes per pixel
343: private void processParams(int width, int height,
344: ImageType imageType) {
345: if (width < 1) {
346: throw new IllegalArgumentException(J3dI18N
347: .getString("NioImageBuffer0"));
348: }
349:
350: if (height < 1) {
351: throw new IllegalArgumentException(J3dI18N
352: .getString("NioImageBuffer1"));
353: }
354:
355: switch (imageType) {
356: case TYPE_3BYTE_BGR:
357: bufferType = BufferType.BYTE_BUFFER;
358: bytesPerPixel = 3;
359: elementsPerPixel = 3;
360: break;
361:
362: case TYPE_3BYTE_RGB:
363: bufferType = BufferType.BYTE_BUFFER;
364: bytesPerPixel = 3;
365: elementsPerPixel = 3;
366: break;
367:
368: case TYPE_4BYTE_ABGR:
369: bufferType = BufferType.BYTE_BUFFER;
370: bytesPerPixel = 4;
371: elementsPerPixel = 4;
372: break;
373:
374: case TYPE_4BYTE_RGBA:
375: bufferType = BufferType.BYTE_BUFFER;
376: bytesPerPixel = 4;
377: elementsPerPixel = 4;
378: break;
379:
380: case TYPE_BYTE_GRAY:
381: bufferType = BufferType.BYTE_BUFFER;
382: bytesPerPixel = 1;
383: elementsPerPixel = 1;
384: break;
385:
386: case TYPE_INT_ARGB:
387: case TYPE_INT_BGR:
388: case TYPE_INT_RGB:
389: bufferType = BufferType.INT_BUFFER;
390: bytesPerPixel = 4;
391: elementsPerPixel = 1;
392: break;
393:
394: default:
395: // We should never get here
396: throw new AssertionError("missing case statement");
397: }
398:
399: this.width = width;
400: this.height = height;
401: this.imageType = imageType;
402: }
403:
404: }
|