/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016–2017, 2019–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package javax.microedition.lcdui;
import java.io.*;
import javax.microedition.lcdui.game.*;
import malik.emulator.fileformats.graphics.*;
import malik.emulator.io.jar.*;
import malik.emulator.media.graphics.*;
import malik.emulator.microedition.*;
import malik.emulator.util.*;
public class Image extends Object
{
public static Image createImage(int width, int height) {
int area;
int[] pixels;
if(width <= 0)
{
throw new IllegalArgumentException("Image.createImage: аргумент width может быть только положительным.");
}
if(height <= 0)
{
throw new IllegalArgumentException("Image.createImage: аргумент height может быть только положительным.");
}
Array.fill(pixels = new int[area = width * height], 0, area, 0xffffffff);
return new Image(pixels, width, height, true);
}
public static Image createImage(byte[] src, int offset, int length) {
int width;
int height;
int[] pixels;
ImageDecoder decoder;
if(src == null)
{
throw new NullPointerException("Image.createImage: аргумент src равен нулевой ссылке.");
}
Array.checkBound("Image.createImage", src.length, offset, length);
try
{
InputStream stream = new ByteArrayInputStream(src, offset, length);
(decoder = DeviceManager.getInstance().openImageDecoder(stream)).loadFromInputStream(stream);
}
catch(Exception e)
{
throw new IllegalArgumentException("Image.createImage: не удалось декодировать изображение.");
}
width = decoder.getWidth();
height = decoder.getHeight();
pixels = decoder.getPixels();
if(!decoder.alphaSupported()) for(int i = width * height; i-- > 0; pixels[i] |= 0xff000000);
return new Image(pixels, width, height, false);
}
public static Image createImage(InputStream stream) throws IOException {
int width;
int height;
int[] pixels;
ImageDecoder decoder;
if(stream == null)
{
throw new NullPointerException("Image.createImage: аргумент stream равен нулевой ссылке.");
}
(decoder = DeviceManager.getInstance().openImageDecoder(stream)).loadFromInputStream(stream);
width = decoder.getWidth();
height = decoder.getHeight();
pixels = decoder.getPixels();
if(!decoder.alphaSupported()) for(int i = width * height; i-- > 0; pixels[i] |= 0xff000000);
return new Image(pixels, width, height, false);
}
public static Image createImage(String resourceName) throws IOException {
int width;
int height;
int[] pixels;
ImageDecoder decoder;
InputStream stream;
if(resourceName == null)
{
throw new NullPointerException("Image.createImage: аргумент resourceName равен нулевой ссылке.");
}
if((stream = resourceName.getClass().getResourceAsStream(resourceName.length() > 0 && resourceName.charAt(0) == '/' ? resourceName : "/".concat(resourceName))) == null)
{
throw new ResourceNotFoundException((new StringBuilder()).append("Image.createImage: ресурс ").append(resourceName).append(" не найден.").toString());
}
(decoder = DeviceManager.getInstance().openImageDecoder(stream)).loadFromInputStream(stream);
width = decoder.getWidth();
height = decoder.getHeight();
pixels = decoder.getPixels();
if(!decoder.alphaSupported()) for(int i = width * height; i-- > 0; pixels[i] |= 0xff000000);
return new Image(pixels, width, height, false);
}
public static Image createImage(Image source) {
int area;
int width;
int height;
int[] pixels;
if(source == null)
{
throw new NullPointerException("Image.createImage: аргумент source равен нулевой ссылке.");
}
if(!source.mutable) return source;
Array.copy(source.pixels, 0, pixels = new int[area = (width = source.width) * (height = source.height)], 0, area);
return new Image(pixels, width, height, false);
}
public static Image createImage(Image source, int left, int top, int width, int height, int transform) {
int lim;
int area;
int xinc;
int yinc;
int start;
int srcWidth;
int srcHeight;
int[] srcPixels;
int[] dstPixels;
if(source == null)
{
throw new NullPointerException("Image.createImage: аргумент source равен нулевой ссылке.");
}
srcWidth = source.width;
srcHeight = source.height;
if(!source.mutable && (left | top) == 0 && width == srcWidth && height == srcHeight && transform == Sprite.TRANS_NONE) return source;
if(width <= 0)
{
throw new IllegalArgumentException("Image.createImage: аргумент width может быть только положительным.");
}
if(height <= 0)
{
throw new IllegalArgumentException("Image.createImage: аргумент height может быть только положительным.");
}
if((lim = left + width) > srcWidth || lim < left || left > srcWidth || left < 0 || (lim = top + height) > srcHeight || lim < top || top > srcHeight || top < 0)
{
throw new IllegalArgumentException("Image.createImage: заданный регион выходит за пределы изображения.");
}
if((transform & (-8)) != 0)
{
throw new IllegalArgumentException("Image.createImage: аргумент transform имеет недопустимое значение.");
}
srcPixels = source.pixels;
dstPixels = new int[area = width * height];
for(int i = left + top * srcWidth, j = 0, cy = height; cy-- > 0; i += srcWidth, j += width) Array.copy(srcPixels, i, dstPixels, j, width);
srcPixels = dstPixels;
dstPixels = new int[area];
if((transform & 1) != 0)
{
yinc = -width;
start = area - width;
} else
{
yinc = width;
start = 0;
}
if((transform & 2) != 0)
{
xinc = -1;
start += width - 1;
} else
{
xinc = 1;
}
if((transform & 4) != 0)
{
for(int i = 0, cx = width; cx-- > 0; start += xinc) for(int j = start, cy = height; cy-- > 0; j += yinc)
{
dstPixels[i++] = srcPixels[j];
}
return new Image(dstPixels, height, width, false);
}
for(int i = 0, cy = height; cy-- > 0; start += yinc) for(int j = start, cx = width; cx-- > 0; j += xinc) dstPixels[i++] = srcPixels[j];
return new Image(dstPixels, width, height, false);
}
public static Image createRGBImage(int[] pixels, int width, int height, boolean alpha) {
return createRGBImage(pixels, width, height, alpha, false);
}
public static Image createRGBImage(int[] pixels, int width, int height, boolean alpha, boolean mutable) {
int area;
if(pixels == null)
{
throw new NullPointerException("Image.createRGBImage: аргумент pixels равен нулевой ссылке.");
}
if(width <= 0)
{
throw new IllegalArgumentException("Image.createRGBImage: аргумент width может быть только положительным.");
}
if(height <= 0)
{
throw new IllegalArgumentException("Image.createRGBImage: аргумент height может быть только положительным.");
}
if((long) pixels.length < (long) width * (long) height)
{
throw new ArrayIndexOutOfBoundsException("Image.createRGBImage: длина массива pixels меньше заданной площади изображения.");
}
Array.copy(pixels, 0, pixels = new int[area = width * height], 0, area);
if(!alpha) for(int i = area; i-- > 0; pixels[i] |= 0xff000000);
return new Image(pixels, width, height, mutable);
}
private final boolean mutable;
final int width;
final int height;
private final int[] pixels;
final RasterBuffer buffer;
private Image(int[] pixels, int width, int height, boolean mutable) {
this.mutable = mutable;
this.width = width;
this.height = height;
this.pixels = pixels;
this.buffer = RasterBuffer.create(pixels, 0, width, width, height, false);
}
public void getRGB(int[] pixels, int offset, int scanlength, int left, int top, int width, int height) {
int lim;
int len;
int pixelsOffset;
int pixelsLength;
int srcWidth = this.width;
int[] srcPixels = this.pixels;
if(scanlength >= 0)
{
pixelsOffset = offset;
pixelsLength = width + (height - 1) * scanlength;
} else
{
pixelsOffset = offset + (height - 1) * scanlength;
pixelsLength = width + offset - pixelsOffset;
}
if((lim = left + width) > (len = srcWidth) || lim < left || left > len || left < 0 || (lim = top + height) > (len = this.height) || lim < top || top > len || top < 0)
{
throw new IllegalArgumentException("Image.getRGB: заданный регион выходит за пределы изображения.");
}
if(scanlength > -width && scanlength < width)
{
throw new IllegalArgumentException("Image.getRGB: аргумент scanlength выходит из диапазона.");
}
if(pixels == null)
{
throw new NullPointerException("Image.getRGB: аргумент pixels равен нулевой ссылке.");
}
Array.checkBound("Image.getRGB", pixels.length, pixelsOffset, pixelsLength);
for(int i = left + top * srcWidth, j = offset, cy = height; cy-- > 0; i += srcWidth, j += scanlength) Array.copy(srcPixels, i, pixels, j, width);
}
public boolean isMutable() {
return mutable;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Graphics getGraphics() {
if(!mutable)
{
throw new IllegalStateException("Image.getGraphics: неизменяемое изображение.");
}
return new Graphics(buffer);
}
}