/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package javax.microedition.lcdui;
import java.io.*;
import malik.emulator.fileformats.*;
import malik.emulator.fileformats.graphics.*;
import malik.emulator.io.j2me.*;
import malik.emulator.io.jar.*;
import malik.emulator.media.graphics.*;
public class Image extends Object
{
private static final long MAX_AREA = 1L << 20;
public static Image createImage(int width, int height)
{
int i;
long area;
int[] pixels;
if(width <= 0 || height <= 0)
{
throw new IllegalArgumentException("Image.createImage: " +
"размеры могут быть только положительными.");
}
if((area = ((long) width) * (long) height) > MAX_AREA)
{
throw new IllegalArgumentException("Image.createImage: " +
"размеры очень большие.");
}
for(pixels = new int[i = (int) area]; i-- > 0; pixels[i] = -1);
return new Image(new GraphicBuffer(pixels, 0, width, width, height), true);
}
public static Image createImage(Image src)
{
int area;
int width;
int height;
int[] pixels;
GraphicBuffer buffer;
if(src == null)
{
throw new NullPointerException("Image.createImage: " +
"параметр src равен нулевой ссылке.");
}
if(!src.mutable)
{
return src;
}
Array.copy((buffer = src.buffer).getPixels(), 0, pixels = new int[area =
(width = buffer.getWidth()) * (height = buffer.getHeight())], 0, area);
return new Image(new GraphicBuffer(pixels, 0, width, width, height));
}
public static Image createImage(Image src, int left, int top, int width, int height,
int transform)
{
int lim;
int len;
int w;
int h;
GraphicBuffer buffer;
if(src == null)
{
throw new NullPointerException("Image.createImage: " +
"параметр src равен нулевой ссылке.");
}
if(width <= 0 || height <= 0)
{
throw new IllegalArgumentException("Image.createImage: " +
"размеры могут быть только положительными.");
}
if((lim = left + width) > (len = w = src.getWidth()) ||
lim < left || left > len || left < 0 ||
(lim = top + height) > (len = h = src.getHeight()) ||
lim < top || top > len || top < 0)
{
throw new IllegalArgumentException("Image.createImage: " +
"заданная прямоугольная область выходит за пределы исходного изображения.");
}
if((transform = Graphics.spriteTransformToMalik(transform)) < 0)
{
throw new IllegalArgumentException("Image.createImage: " +
"недопустимое значение параметра transform.");
}
if((!src.mutable) && left == 0 && top == 0 && width == w && height == h &&
transform == RasterCanvas.TRANSFORM_NONE)
{
return src;
}
buffer = (transform & 1) == 0 ?
new GraphicBuffer(new int[width * height], 0, width, w = width, h = height) :
new GraphicBuffer(new int[width * height], 0, height, w = height, h = width);
(new RasterCanvas(buffer)).drawPixelsArea(0, 0, w, h,
src.buffer, left, top, width, height, transform, 0, 0, w, h, true);
return new Image(buffer);
}
public static Image createImage(byte[] src, int offset, int length)
{
int i;
int lim;
int len;
int[] pixels;
InputStream stream;
ImageDecoder decoder;
GraphicBuffer buffer;
if(src == null)
{
throw new NullPointerException("Image.createImage: " +
"параметр src равен нулевой ссылке.");
}
if((lim = offset + length) > (len = src.length) ||
lim < offset || offset > len || offset < 0)
{
throw new ArrayIndexOutOfBoundsException("Image.createImage: " +
"индекс выходит из диапазона.");
}
try
{
if((decoder = ImplementationManager.getImageDecoder(stream =
new ByteArrayInputStream(src, offset, length))) == null)
{
throw new IllegalArgumentException("Image.createImage: " +
"ошибка декодирования изображения.");
}
decoder.loadFromInputStream(stream);
}
catch(IOException e)
{
throw new IllegalArgumentException("Image.createImage: " +
"ошибка декодирования изображения.");
}
if(decoder.isEmpty())
{
throw new IllegalArgumentException("Image.createImage: " +
"ошибка декодирования изображения.");
}
buffer = new GraphicBuffer(pixels = decoder.getPixels(), 0,
i = decoder.getWidth(), i, decoder.getHeight());
if(!decoder.isAlphaSupported())
{
for(i = pixels.length; i-- > 0; pixels[i] |= 0xff000000);
}
return new Image(buffer);
}
public static Image createImage(InputStream stream)
throws IOException
{
int i;
int[] pixels;
ImageDecoder decoder;
GraphicBuffer buffer;
if(stream == null)
{
throw new NullPointerException("Image.createImage: " +
"параметр stream равен нулевой ссылке.");
}
if((decoder = ImplementationManager.getImageDecoder(stream)) == null)
{
throw new InvalidDataFormatException("Image.createImage: " +
"неизвестный формат изображения.");
}
decoder.loadFromInputStream(stream);
if(decoder.isEmpty())
{
throw new InvalidDataFormatException("Image.createImage: " +
"неизвестный формат изображения.");
}
buffer = new GraphicBuffer(pixels = decoder.getPixels(), 0,
i = decoder.getWidth(), i, decoder.getHeight());
if(!decoder.isAlphaSupported())
{
for(i = pixels.length; i-- > 0; pixels[i] |= 0xff000000);
}
return new Image(buffer);
}
public static Image createImage(String resourceName)
throws IOException
{
int i;
int[] pixels;
InputStream stream;
ImageDecoder decoder;
GraphicBuffer buffer;
if(resourceName == null)
{
throw new NullPointerException("Image.createImage: " +
"параметр resourceName равен нулевой ссылке.");
}
if((stream = resourceName.getClass().getResourceAsStream(
resourceName.length() <= 0 || resourceName.charAt(0) != '/' ?
(resourceName = "/".concat(resourceName)) : resourceName)) == null)
{
throw new ResourceNotFoundException("Image.createImage: " +
"ресурс " + resourceName + " не найден.");
}
if((decoder = ImplementationManager.getImageDecoder(stream)) == null)
{
throw new InvalidDataFormatException("Image.createImage: " +
"неизвестный формат изображения.");
}
decoder.loadFromInputStream(stream);
if(decoder.isEmpty())
{
throw new InvalidDataFormatException("Image.createImage: " +
"неизвестный формат изображения.");
}
buffer = new GraphicBuffer(pixels = decoder.getPixels(), 0,
i = decoder.getWidth(), i, decoder.getHeight());
if(!decoder.isAlphaSupported())
{
for(i = pixels.length; i-- > 0; pixels[i] |= 0xff000000);
}
return new Image(buffer);
}
public static Image createRGBImage(int[] src, int width, int height, boolean alpha)
{
int i;
long area;
int[] pixels;
if(src == null)
{
throw new NullPointerException("Image.createRGBImage: " +
"параметр src равен нулевой ссылке.");
}
if(width <= 0 || height <= 0)
{
throw new IllegalArgumentException("Image.createRGBImage: " +
"размеры могут быть только положительными.");
}
if((area = ((long) width) * (long) height) > MAX_AREA)
{
throw new IllegalArgumentException("Image.createRGBImage: " +
"размеры очень большие.");
}
if(area > (long) src.length)
{
throw new ArrayIndexOutOfBoundsException("Image.createRGBImage: " +
"индекс выходит из диапазона.");
}
Array.copy(src, 0, pixels = new int[i = (int) area], 0, i);
if(!alpha)
{
for(; i-- > 0; pixels[i] |= 0xff000000);
}
return new Image(new GraphicBuffer(pixels, 0, width, width, height));
}
private boolean mutable;
private GraphicBuffer buffer;
private Image(GraphicBuffer buffer)
{
this.mutable = false;
this.buffer = buffer;
}
private Image(GraphicBuffer buffer, boolean mutable)
{
this.mutable = mutable;
this.buffer = buffer;
}
public void getRGB(int[] dst, int offset, int scanlength,
int left, int top, int width, int height)
{
int i;
int lim;
int len;
int length;
int srcScan;
int srcLine;
int dstLine;
int[] src;
GraphicBuffer buffer;
if(dst == null)
{
throw new NullPointerException("Image.getRGB: " +
"параметр dst равен нулевой ссылке.");
}
if(width <= 0 || height <= 0)
{
return;
}
if((lim = left + width) > (len = (buffer = this.buffer).getWidth()) ||
lim < left || left > len || left < 0 ||
(lim = top + height) > (len = buffer.getHeight()) ||
lim < top || top > len || top < 0)
{
throw new IllegalArgumentException("Image.getRGB: " +
"заданная прямоугольная область выходит за пределы растровой канвы.");
}
if(Math.abs(scanlength) < width)
{
throw new IllegalArgumentException("Image.getRGB: " +
"длина линии сканирования не может быть меньше ширины.");
}
if(scanlength >= 0)
{
i = 0;
length = width + (height - 1) * scanlength;
} else
{
i = (-scanlength) * (height - 1);
length = width + i;
}
offset -= i;
if((lim = offset + length) > (len = dst.length) ||
lim < offset || offset > len || offset < 0)
{
throw new ArrayIndexOutOfBoundsException("Image.getRGB: " +
"индекс выходит из диапазона.");
}
offset += i;
src = buffer.getPixels();
srcLine = buffer.getOffset() + left + top * (srcScan = buffer.getScanlength());
dstLine = offset;
for(i = 0; i < height; srcLine += srcScan, dstLine += scanlength, i++)
{
Array.copy(src, srcLine, dst, dstLine, width);
}
}
public boolean isMutable()
{
return mutable;
}
public int getWidth()
{
return buffer.getWidth();
}
public int getHeight()
{
return buffer.getHeight();
}
public Graphics getGraphics()
{
if(!mutable)
{
throw new IllegalStateException("Image.getGraphics: " +
"изображение неизменяемо.");
}
return new Graphics(buffer);
}
public final GraphicBuffer getBuffer()
{
return buffer;
}
}