1919/**
2020 * A bitmap image that can be drawn to the screen.
2121 * <p>
22- * An image’s {@link getPosition() position} is the upper left corner of its bounding box.
22+ * An image’s {@link # getPosition() position} is the upper left corner of its bounding box.
2323 * Its size is the size of the underying image file by default, but you can shrink it using
24- * {@link setMaxWidth(double) setMaxWidth()} and {@link setMaxHeight(double) setMaxHeight()}.
24+ * {@link # setMaxWidth(double) setMaxWidth()} and {@link # setMaxHeight(double) setMaxHeight()}.
2525 *
2626 * @author Bret Jackson, Paul Cantrell
2727 */
@@ -139,7 +139,7 @@ public Image(int width, int height, float[] pixels, PixelFormat format) {
139139 }
140140
141141 /**
142- * Creates a new image using raw pixel data from the given array. This method interprets bytes
142+ * Creates a new image using raw pixel data from the given array. This interprets bytes
143143 * as unsigned: zero intensity is 0, and full intensity is 255 (but Java represents this as -1,
144144 * because the language does not have unsigned primitive types).
145145 * There is one array element per color channel, with channels interleaved
@@ -157,13 +157,23 @@ public Image(int width, int height, byte[] pixels, PixelFormat format) {
157157 this (format .makeBufferedImage (pixels , width , height ));
158158 }
159159
160+ /**
161+ * Creates a new image using raw pixel data from the given array, one int per pixel. Each pixel
162+ * is in 32-bit ARGB format.
163+ *
164+ * @param width Image width in pixels
165+ * @param height Image height in pixels
166+ * @param pixels Raw pixel data. Length must exactly match the number of required samples.
167+ */
168+ public Image (int width , int height , int [] pixels ) {
169+ this (createBufferFromRawPixelData (width , height , pixels ));
170+ }
171+
160172 /**
161173 * Creates a bitmap image from the given BufferedImage, positioned at (0, 0).
162174 * Note that changing the BufferedImage externally does not automatically
163175 * force it to redraw. You will need to call {@link CanvasWindow#draw()}
164176 * to see the changes.
165- *
166- * @param image
167177 */
168178 public Image (BufferedImage image ){
169179 this (0 , 0 , image );
@@ -173,12 +183,10 @@ public Image(BufferedImage image){
173183 * Creates a bitmap image from the given BufferedImage. Note that changing
174184 * the BufferedImage externally does not automatically force it to redraw.
175185 * You will need to call {@link CanvasWindow#draw()} to see the changes.
176- *
177- * @param image
178186 */
179187 public Image (double x , double y , BufferedImage image ){
180188 setPosition (x , y );
181- this .path = "In memory BufferedImage@" +Integer .toHexString (image .hashCode ());
189+ this .path = "In- memory BufferedImage@" +Integer .toHexString (image .hashCode ());
182190 this .img = image ;
183191 }
184192
@@ -282,7 +290,8 @@ private double getScaleToFit() {
282290 * produces results that correspond poorly to perceived brightness.
283291 *
284292 * @see #Image(int,int,byte[],PixelFormat)
285- * @see #toFloatArray(PixelFormat)
293+ * @see #toFloatArray(PixelFormat)
294+ * @see #toIntArray()
286295 */
287296 public byte [] toByteArray (PixelFormat format ) {
288297 return format .makeByteArray (img );
@@ -308,6 +317,37 @@ public float[] toFloatArray(PixelFormat format) {
308317 return floats ;
309318 }
310319
320+ /**
321+ * Returns the pixels in this image as an array of ints, one int per <b>pixel</b>. Pixels use
322+ * 32-bit ARGB encoding.
323+ * <p>
324+ * Note that the other methods that convert images to arrays return one array entry per
325+ * <b>color channel</b>, while this method returns one array entry <b>per pixel</b>.
326+ *
327+ * @see #Image(int,int,byte[],PixelFormat)
328+ * @see #toFloatArray(PixelFormat)
329+ */
330+ public int [] toIntArray () {
331+ return getRawPixelData (img );
332+ }
333+
334+ private static int [] getRawPixelData (BufferedImage buf ) {
335+ return buf .getRGB (0 , 0 , buf .getWidth (), buf .getHeight (), null , 0 , buf .getWidth ());
336+ }
337+
338+ private static BufferedImage createBufferFromRawPixelData (int width , int height , int [] pixels ) {
339+ int expectedArrayLen = width * height ;
340+ if (pixels .length != expectedArrayLen ) {
341+ throw new IllegalArgumentException (
342+ "Invalid input array length: expected " + width + " w * " + height + " h = "
343+ + expectedArrayLen + ", but got " + pixels .length );
344+ }
345+
346+ BufferedImage buf = new BufferedImage (width , height , BufferedImage .TYPE_INT_ARGB );
347+ buf .setRGB (0 , 0 , width , height , pixels , 0 , width );
348+ return buf ;
349+ }
350+
311351 @ Override
312352 protected Object getEqualityAttributes () {
313353 return List .of (path , maxWidth , maxHeight ); // Not ideally performant, but life goes on
@@ -407,9 +447,9 @@ private BufferedImage makeBufferedImage(
407447 }
408448
409449 private byte [] makeByteArray (BufferedImage buf ) {
410- int width = buf .getWidth (), height = buf .getHeight ();
411- int [] rawData = buf .getRGB (0 , 0 , width , height , null , 0 , width );
450+ int [] rawData = getRawPixelData (buf );
412451
452+ int width = buf .getWidth (), height = buf .getHeight ();
413453 byte [] pixels = new byte [width * height * externalChans ];
414454 int i = 0 ;
415455 for (int pix : rawData ) {
0 commit comments