diff --git a/src/org/recompile/mobile/PlatformGraphics.java b/src/org/recompile/mobile/PlatformGraphics.java index 890f5524..19c1eb84 100644 --- a/src/org/recompile/mobile/PlatformGraphics.java +++ b/src/org/recompile/mobile/PlatformGraphics.java @@ -26,13 +26,11 @@ import java.awt.*; import java.awt.image.BufferedImage; -import java.awt.image.WritableRaster; -import java.awt.BasicStroke; +import java.awt.image.DataBufferInt; public class PlatformGraphics extends javax.microedition.lcdui.Graphics implements DirectGraphics { protected BufferedImage canvas; - private WritableRaster raster; protected Graphics2D gc; protected Color awtColor; @@ -224,8 +222,8 @@ public void drawRGB(int[] rgbData, int offset, int scanlength, int x, int y, int } BufferedImage temp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - raster = temp.getRaster(); - final int[] pixels = new int[width * height]; + // Let's get the target pixel array directly from the image's DataBuffer, saving us an array copy and the overhead of setDataElements(). + final int[] pixels = ((DataBufferInt) temp.getRaster().getDataBuffer()).getData(); int s, d, pixel; for (int i = 0; i < height; i++) @@ -240,8 +238,6 @@ public void drawRGB(int[] rgbData, int offset, int scanlength, int x, int y, int } } - raster.setDataElements(0, 0, width, height, pixels); - gc.drawImage(temp, x, y, null); } @@ -458,49 +454,51 @@ public void drawPixels(byte[] pixels, byte[] transparencyMask, int offset, int s { int[] Type1 = {0xFFFFFFFF, 0xFF000000, 0x00FFFFFF, 0x00000000}; int c = 0; - int[] data = null; BufferedImage temp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - raster = temp.getRaster(); - switch(format) + final int[] data = ((DataBufferInt) temp.getRaster().getDataBuffer()).getData(); + + switch (format) { - case -1: // TYPE_BYTE_1_GRAY_VERTICAL // used by Monkiki's Castles - data = new int[width*height]; + case -1: // TYPE_BYTE_1_GRAY_VERTICAL - Used by Munkiki's Castles int ods = offset / scanlength; int oms = offset % scanlength; - int b = ods % 8; //Bit offset in a byte - for (int yj = 0; yj < height; yj++) + int b = ods % 8; // Bit offset in a byte + for (int yj = 0; yj < height; yj++) { int ypos = yj * width; - int tmp = (ods + yj) / 8 * scanlength+oms; - for (int xj = 0; xj < width; xj++) + int tmp = (ods + yj) / 8 * scanlength + oms; + for (int xj = 0; xj < width; xj++) { - c = ((pixels[tmp + xj]>>b)&1); - if(transparencyMask!=null) { c |= (((transparencyMask[tmp + xj]>>b)&1)^1)<<1; } - data[(yj*width)+xj] = Type1[c]; + c = ((pixels[tmp + xj] >> b) & 1); + if (transparencyMask != null) + { + c |= (((transparencyMask[tmp + xj] >> b) & 1) ^ 1) << 1; + } + data[ypos + xj] = Type1[c]; // Set pixel directly in the DataBuffer also removing the need for setDataElements } b++; - if(b>7) b=0; + if (b > 7) b = 0; } - break; - - case 1: // TYPE_BYTE_1_GRAY // used by Munkiki's Castles - data = new int[pixels.length*8]; - - for(int i=(offset/8); i=0; j--) + for (int j = 7; j >= 0; j--) { - c = ((pixels[i]>>j)&1); - if(transparencyMask!=null) { c |= (((transparencyMask[i]>>j)&1)^1)<<1; } - data[(i*8)+(7-j)] = Type1[c]; + c = ((pixels[i] >> j) & 1); + if (transparencyMask != null) + { + c |= (((transparencyMask[i] >> j) & 1) ^ 1) << 1; + } + data[(i * 8) + (7 - j)] = Type1[c]; // Same as above } } - break; + break; default: Mobile.log(Mobile.LOG_WARNING, PlatformGraphics.class.getPackage().getName() + "." + PlatformGraphics.class.getSimpleName() + ": " + "drawPixels A : Format " + format + " Not Implemented"); } - raster.setDataElements(0, 0, width, height, data); gc.drawImage(manipulateImage(temp, manipulation), x, y, null); } @@ -519,12 +517,9 @@ public void drawPixels(int[] pixels, boolean transparency, int offset, int scanl if (offset + width > pixels.length || offset + scanlength * (height - 1) < 0) { throw new ArrayIndexOutOfBoundsException(); } } - // Create the temporary BufferedImage and get its WritableRaster + // Create the temporary BufferedImage and get its DataBuffer to manipulate it directly. BufferedImage temp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - raster = temp.getRaster(); - - // Prepare pixel data - final int[] data = new int[width * height]; + int[] data = ((DataBufferInt) temp.getRaster().getDataBuffer()).getData(); for (int row = 0; row < height; row++) { @@ -537,16 +532,14 @@ public void drawPixels(int[] pixels, boolean transparency, int offset, int scanl } } - raster.setDataElements(0, 0, width, height, data); gc.drawImage(manipulateImage(temp, manipulation), x, y, null); } public void drawPixels(short[] pixels, boolean transparency, int offset, int scanlength, int x, int y, int width, int height, int manipulation, int format) { BufferedImage temp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - raster = temp.getRaster(); + int[] data = ((DataBufferInt) temp.getRaster().getDataBuffer()).getData(); - final int[] data = new int[pixels.length]; // Prepare the pixel data for (int row = 0; row < height; row++) { @@ -555,12 +548,9 @@ public void drawPixels(short[] pixels, boolean transparency, int offset, int sca int index = offset + row * scanlength + col; data[row * width + col] = pixelToColor(pixels[index], format); if (!transparency) { data[row * width + col] &= 0x00FFFFFF; } // Clear the alpha channel - } } - // Set the pixel data directly into the raster - raster.setDataElements(0, 0, width, height, data); gc.drawImage(manipulateImage(temp, manipulation), x, y, null); } diff --git a/src/org/recompile/mobile/PlatformImage.java b/src/org/recompile/mobile/PlatformImage.java index a091a252..aac4a0a6 100644 --- a/src/org/recompile/mobile/PlatformImage.java +++ b/src/org/recompile/mobile/PlatformImage.java @@ -36,11 +36,9 @@ import java.awt.image.BufferedImage; import java.awt.image.DataBuffer; import java.awt.image.DataBufferInt; -import java.awt.image.WritableRaster; public class PlatformImage extends javax.microedition.lcdui.Image { - private WritableRaster raster; protected BufferedImage canvas; protected PlatformGraphics gc; @@ -198,7 +196,22 @@ public PlatformImage(int[] rgb, int Width, int Height, boolean processAlpha) public PlatformImage(Image image, int x, int y, int Width, int Height, int transform) { // Create Image From Sub-Image, Transformed // - BufferedImage sub = image.platformImage.canvas.getSubimage(x, y, Width, Height); + BufferedImage sub = new BufferedImage(Width, Height, BufferedImage.TYPE_INT_ARGB); + + // Get the original pixel data from the source image + final int[] sourcePixels = ((DataBufferInt) image.platformImage.canvas.getRaster().getDataBuffer()).getData(); + + // Create an array to hold the sub-image pixel data + final int[] subPixels = new int[Width * Height]; + + // Copy pixel data directly + for (int j = 0; j < Height; j++) + { + System.arraycopy(sourcePixels, (y + j) * image.platformImage.canvas.getWidth() + x, subPixels, j * Width, Width); + } + + // Set the pixel data for the new sub-image + sub.getRaster().setDataElements(0, 0, Width, Height, subPixels); canvas = transformImage(sub, transform); createGraphics(); @@ -215,7 +228,7 @@ public void getRGB(int[] rgbData, int offset, int scanlength, int x, int y, int if (width <= 0 || height <= 0) { return; } // No pixels to copy if (x < 0 || y < 0 || x + width > canvas.getWidth() || y + height > canvas.getHeight()) { - throw new IllegalArgumentException("Requested area exceeds bounds of the image"); + throw new IllegalArgumentException("getRGB Requested area exceeds bounds of the image"); } if (Math.abs(scanlength) < width) { @@ -223,11 +236,7 @@ public void getRGB(int[] rgbData, int offset, int scanlength, int x, int y, int } // Temporary array to hold the raw pixel data - int[] tempData = new int[width * height]; - - raster = canvas.getRaster(); - raster.getDataElements(x, y, width, height, tempData); - + int[] tempData = ((DataBufferInt) canvas.getRaster().getDataBuffer()).getData(); // Copy the data into rgbData, taking scanlength into account for (int row = 0; row < height; row++) { @@ -238,18 +247,30 @@ public void getRGB(int[] rgbData, int offset, int scanlength, int x, int y, int } } - public int getARGB(int x, int y) { return canvas.getRGB(x, y); } - - public int getPixel(int x, int y) - { - int[] rgbData = { 0 }; - canvas.getRGB(x, y, 1, 1, rgbData, 0, 1); - return rgbData[0]; + public int getARGB(int x, int y) + { + if (x < 0 || y < 0 || x >= canvas.getWidth() || y >= canvas.getHeight()) + { + throw new IllegalArgumentException("Requested area exceeds bounds of the image"); + } + + // Get the raw pixel data array directly from the canvas + int[] pixels = ((DataBufferInt) canvas.getRaster().getDataBuffer()).getData(); + return pixels[y * canvas.getWidth() + x]; } + public int getPixel(int x, int y) { return getARGB(x, y); } + public void setPixel(int x, int y, int color) { - canvas.setRGB(x, y, color); + if (x < 0 || y < 0 || x >= canvas.getWidth() || y >= canvas.getHeight()) + { + throw new IllegalArgumentException("Requested area exceeds bounds of the image"); + } + + // Get the raw pixel data array directly from the canvas + int[] pixels = ((DataBufferInt) canvas.getRaster().getDataBuffer()).getData(); + pixels[y * canvas.getWidth() + x] = color; } public static final BufferedImage transformImage(final BufferedImage image, final int transform) @@ -263,9 +284,9 @@ public static final BufferedImage transformImage(final BufferedImage image, fina BufferedImage transimage = null; if(transform == Sprite.TRANS_ROT90 || transform == Sprite.TRANS_ROT270 || transform == Sprite.TRANS_MIRROR_ROT90 || transform == Sprite.TRANS_MIRROR_ROT270) { - transimage = new BufferedImage(height, width, BufferedImage.TYPE_INT_ARGB); // Non-Math.PI rotations require width and height to be swapped + transimage = new BufferedImage(height, width, image.getType()); // Non-Math.PI rotations require width and height to be swapped } - else { transimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); } + else { transimage = new BufferedImage(width, height, image.getType()); } // We know the data is of TYPE_INT_ARGB, so just get it directly instead of checking for its type final int[] sourceData = ((DataBufferInt)image.getRaster().getDataBuffer()).getData(); @@ -284,7 +305,7 @@ public static final BufferedImage transformImage(final BufferedImage image, fina } //dumpImage(image, ""); //dumpImage(transimage, "_rot90"); - return transimage; + break; case Sprite.TRANS_ROT180: for (int y = 0; y < height; y++) @@ -297,7 +318,7 @@ public static final BufferedImage transformImage(final BufferedImage image, fina } //dumpImage(image, ""); //dumpImage(transimage, "_rot180"); - return transimage; + break; case Sprite.TRANS_ROT270: for (int y = 0; y < height; y++) @@ -309,7 +330,7 @@ public static final BufferedImage transformImage(final BufferedImage image, fina } //dumpImage(image, ""); //dumpImage(transimage, "_rot270"); - return transimage; + break; case Sprite.TRANS_MIRROR: /* @@ -340,7 +361,7 @@ public static final BufferedImage transformImage(final BufferedImage image, fina } //dumpImage(image, ""); //dumpImage(transimage, "_mirror"); - return transimage; + break; case Sprite.TRANS_MIRROR_ROT90: for (int y = 0; y < height; y++) @@ -353,7 +374,7 @@ public static final BufferedImage transformImage(final BufferedImage image, fina } //dumpImage(image, ""); //dumpImage(transimage, "_mirror90"); - return transimage; + break; case Sprite.TRANS_MIRROR_ROT180: // Basically mirror vertically (an arrow pointing up will then point down). for (int y = 0; y < height; y++) // Due to this, we copy entire rows at once instead of going pixel by pixel @@ -362,7 +383,7 @@ public static final BufferedImage transformImage(final BufferedImage image, fina } //dumpImage(image, ""); //dumpImage(transimage, "_mirror180"); - return transimage; + break; case Sprite.TRANS_MIRROR_ROT270: @@ -376,9 +397,10 @@ public static final BufferedImage transformImage(final BufferedImage image, fina } //dumpImage(image, ""); //dumpImage(transimage, "_mirror270"); - return transimage; + break; } - return image; + + return transimage; } // TODO: Turn this into a setting. Being able to dump image data would be nice.