com.codename1.ui.RGBImage Maven / Gradle / Ivy
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores
* CA 94065 USA or visit www.oracle.com if you need additional information or
* have any questions.
*/
package com.codename1.ui;
/**
* An image that stores its data as an integer RGB array internally,
* this image cannot be manipulated via Graphics primitives however its
* array is accessible and modifiable programmatically. This is very useful
* for 2 distinct use cases.
* The first use case allows us to manipulate images in
* a custom way while still preserving alpha information where applicable.
*
The second use case allows us to store images in the Java heap which is useful
* for some constrained devices. In small devices images are often stored
* in a separate "heap" which runs out eventually, this allows us to place
* the image in the Java heap which is potentially more wasteful but might
* sometimes be more abundant.
*
Note that unless specified otherwise most methods inherited from Image will
* fail when invoked on this subclass often with a NullPointerException. This
* image can be drawn on graphics as usual
*
* @author Shai Almog
*/
public class RGBImage extends Image {
private int width;
private int height;
private int[] rgb;
private boolean opaque;
/**
* Converts an image to an RGB image after which the original image can be GC'd
*
* @param img the image to convert to an RGB image
*/
public RGBImage(Image img) {
super(null);
width = img.getWidth();
height = img.getHeight();
rgb = img.getRGBCached();
}
/**
* Creates an RGB image from scratch the array isn't copied and can be saved
* and manipulated
*
* @param rgb AARRGGBB array
* @param width width of image
* @param height height of image
*/
public RGBImage(int[] rgb, int width, int height) {
super(null);
this.width = width;
this.height = height;
this.rgb = rgb;
}
/**
* {@inheritDoc}
*/
public Image subImage(int x, int y, int width, int height, boolean processAlpha) {
int[] arr = new int[width * height];
int alen = arr.length;
for(int iter = 0 ; iter < alen ; iter++) {
int destY = iter / width;
int destX = iter % width;
int offset = x + destX + ((y + destY) * this.width);
arr[iter] = rgb[offset];
}
return new RGBImage(arr, width, height);
}
/**
* {@inheritDoc}
*/
public Image scaled(int width, int height) {
int srcWidth = getWidth();
int srcHeight = getHeight();
// no need to scale
if(srcWidth == width && srcHeight == height){
return this;
}
int[] currentArray = new int[srcWidth];
int[] destinationArray = new int[width * height];
scaleArray(srcWidth, srcHeight, height, width, currentArray, destinationArray);
// currently we only support byte data...
return new RGBImage(destinationArray, width, height);
}
/**
* {@inheritDoc}
*/
public void scale(int width, int height) {
int srcWidth = getWidth();
int srcHeight = getHeight();
// no need to scale
if(srcWidth == width && srcHeight == height){
return;
}
int[] currentArray = new int[srcWidth];
int[] destinationArray = new int[width * height];
scaleArray(srcWidth, srcHeight, height, width, currentArray, destinationArray);
this.width = width;
this.height = height;
this.rgb = destinationArray;
}
/**
* Unsupported in the current version, this method will be implemented in a future release
*/
public Image rotate(int degrees) {
throw new RuntimeException("The rotate method is not supported by RGB images at the moment");
}
/**
* {@inheritDoc}
*/
public Image modifyAlpha(byte alpha) {
int[] arr = new int[rgb.length];
System.arraycopy(rgb, 0, arr, 0, rgb.length);
int alphaInt = (((int)alpha) << 24) & 0xff000000;
int rlen = rgb.length;
for(int iter = 0 ; iter < rlen ; iter++) {
if((arr[iter] & 0xff000000) != 0) {
arr[iter] = (arr[iter] & 0xffffff) | alphaInt;
}
}
return new RGBImage(arr, width, height);
}
/**
* This method is unsupported in this image type
*/
public Graphics getGraphics() {
throw new RuntimeException("RGBImage objects can't be modified via graphics");
}
/**
* Returns a mutable array that can be used to change the appearance of the image
* arranged as AARRGGBB.
*
* @return ARGB int array
*/
public int[] getRGB() {
return rgb;
}
/**
* {@inheritDoc}
*/
void getRGB(int[] rgbData,
int offset,
int x,
int y,
int width,
int height){
int startPoint = y * this.width + x;
for(int rows = 0 ; rows < height ; rows++) {
int currentRow = rows * width;
for(int columns = 0 ; columns < width ; columns++) {
rgbData[offset + currentRow + columns] = rgb[startPoint + columns];
}
startPoint += this.width;
}
}
/**
* {@inheritDoc}
*/
protected void drawImage(Graphics g, Object nativeGraphics, int x, int y) {
g.drawRGB(rgb, 0, x, y, width, height, !opaque);
}
/**
* {@inheritDoc}
*/
public void setOpaque(boolean opaque) {
this.opaque = opaque;
}
/**
* Indicates if an image should be treated as opaque, this can improve support
* for fast drawing of RGB images without alpha support.
*/
public boolean isOpaque() {
return opaque;
}
/**
* {@inheritDoc}
*/
public int getWidth() {
return width;
}
/**
* {@inheritDoc}
*/
public int getHeight() {
return height;
}
/**
* {@inheritDoc}
*/
@Override
public boolean requiresDrawImage() {
return true;
}
}