com.github.bloodshura.x.assets.image.Image Maven / Gradle / Ivy
/*
* Copyright (c) 2013-2018, João Vitor Verona Biazibetti - All Rights Reserved
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* https://www.github.com/BloodShura
*/
package com.github.bloodshura.x.assets.image;
import com.github.bloodshura.x.assets.Asset;
import com.github.bloodshura.x.assets.AssetManager;
import com.github.bloodshura.x.assets.XAssets;
import com.github.bloodshura.x.assets.exception.AssetException;
import com.github.bloodshura.x.assets.exception.CodecNotFoundException;
import com.github.bloodshura.x.assets.image.codec.ImageCodec;
import com.github.bloodshura.x.assets.image.exception.ImageException;
import com.github.bloodshura.x.assets.image.process.CopyImageProcessor;
import com.github.bloodshura.x.assets.image.process.ImageProcessor;
import com.github.bloodshura.x.assets.util.ImageWorker;
import com.github.bloodshura.x.color.Color;
import com.github.bloodshura.x.geometry.bounds.Bounds;
import com.github.bloodshura.x.geometry.bounds.IBounds;
import com.github.bloodshura.x.geometry.position.IPosition;
import com.github.bloodshura.x.geometry.position.Position;
import com.github.bloodshura.x.io.exception.FileException;
import com.github.bloodshura.x.io.file.TempFile;
import com.github.bloodshura.x.io.stream.FastByteArrayOutputStream;
import com.github.bloodshura.x.object.storable.Storable;
import com.github.bloodshura.x.resource.LocalResource;
import com.github.bloodshura.x.resource.Resource;
import javax.annotation.Nonnull;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import java.awt.Cursor;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Image extends Storable implements Asset, Resource {
protected BufferedImage image;
private int changeCount;
private final ImageCodec codec;
private final ImageFormat format;
public Image() throws CodecNotFoundException {
this(1, 1);
}
public Image(@Nonnull BufferedImage image) throws CodecNotFoundException {
this(ImageFormat.PNG, image);
}
public Image(@Nonnull IBounds bounds) throws CodecNotFoundException {
this((int) bounds.getWidth(), (int) bounds.getHeight());
}
public Image(@Nonnull ImageFormat format, @Nonnull BufferedImage image) throws CodecNotFoundException {
this.codec = XAssets.getManager().getCodec(format);
this.format = format;
this.image = image;
}
public Image(int width, int height) throws CodecNotFoundException {
this(new BufferedImage(width, height, ImageWorker.DEFAULT_TYPE));
}
@Nonnull
@Override
public Image clone() throws CodecNotFoundException {
return new Image(getFormat(), ImageWorker.cloneImage(getImage()));
}
@Nonnull
public Image convert(@Nonnull ImageFormat format) throws AssetException, IOException {
return XAssets.getLoader().getImage(format, readBytes(format));
}
@Nonnull
public int[] createPixels() {
return getImage().getRGB(0, 0, getWidth(), getHeight(), null, 0, getWidth());
}
@Nonnull
public Image cut(int x, int y, int width, int height) {
return new Image(getFormat(), getImage().getSubimage(x, y, width, height));
}
@Nonnull
public Image cut(@Nonnull IPosition position, @Nonnull IBounds bounds) {
return cut((int) position.getX(), (int) position.getY(), (int) bounds.getWidth(), (int) bounds.getHeight());
}
@Nonnull
public Bounds getBounds() {
return new Bounds(getWidth(), getHeight());
}
public int getChangeCount() {
return changeCount;
}
@Nonnull
public ImageCodec getCodec() {
return codec;
}
@Nonnull
public ImageFormat getFormat() {
return format;
}
public int getHeight() {
return getImage().getHeight();
}
@Nonnull
public BufferedImage getImage() {
return image;
}
public int getWidth() {
return getImage().getWidth();
}
@Nonnull
public ImageProcessor newCopyProcessor() {
return new CopyImageProcessor(this).start();
}
@Nonnull
@Override
public InputStream newInputStream() throws IOException {
return new ByteArrayInputStream(readData());
}
@Nonnull
public ImageProcessor newProcessor() {
return new ImageProcessor(this).start();
}
@Nonnull
public Color pixelAt(int x, int y) {
return new Color(getImage().getRGB(x, y));
}
@Nonnull
public Color pixelAt(@Nonnull IPosition position) {
return pixelAt((int) position.getX(), (int) position.getY());
}
@Nonnull
public Color[] pixels() {
return pixelsAt(0, 0, getWidth(), getHeight());
}
@Nonnull
public Color[] pixelsAt(int x, int y, int width, int height) {
int[] rgb = getImage().getRGB(x, y, width, height, null, 0, width);
Color[] pixels = new Color[rgb.length];
for (int i = 0; i < rgb.length; i++) {
pixels[i] = new Color(rgb[i]);
}
return pixels;
}
@Nonnull
public Color[] pixelsAt(@Nonnull IPosition start, @Nonnull IPosition end) {
return pixelsAt((int) start.getX(), (int) start.getY(), (int) (end.getX() - start.getX() + 1), (int) (end.getY() - start.getY() + 1));
}
@Nonnull
@Override
public byte[] readData() throws IOException {
return readBytes(getFormat());
}
@Nonnull
public byte[] readBytes(@Nonnull ImageFormat format) throws IOException {
try (FastByteArrayOutputStream output = new FastByteArrayOutputStream()) {
write(output, format);
return output.toArray();
}
}
public void setImage(@Nonnull BufferedImage image) {
if (image == getImage()) {
return;
}
this.changeCount++;
this.image = image;
}
@Nonnull
public Cursor toCursor() {
return toCursor(new Position());
}
@Nonnull
public Cursor toCursor(@Nonnull IPosition hotSpot) {
return Toolkit.getDefaultToolkit().createCustomCursor(getImage(), hotSpot.toPoint(), "CustomCursorX");
}
@Nonnull
public Icon toIcon() {
return new ImageIcon(getImage());
}
@Nonnull
public TempFile toTempFile() throws FileException, ImageException, IOException {
TempFile file = new TempFile();
write(file);
return file;
}
public void write(@Nonnull LocalResource resource) throws CodecNotFoundException, ImageException, IOException {
write(resource, getFormat());
}
public void write(@Nonnull LocalResource resource, @Nonnull AssetManager manager) throws CodecNotFoundException, ImageException, IOException {
write(resource, manager, getFormat());
}
public void write(@Nonnull LocalResource resource, @Nonnull AssetManager manager, @Nonnull ImageFormat format) throws CodecNotFoundException, ImageException, IOException {
write(resource, manager.getCodec(format), format);
}
public void write(@Nonnull LocalResource resource, @Nonnull ImageCodec codec) throws ImageException, IOException {
write(resource, codec, getFormat());
}
public void write(@Nonnull LocalResource resource, @Nonnull ImageCodec codec, @Nonnull ImageFormat format) throws ImageException, IOException {
try (OutputStream output = resource.newOutputStream()) {
write(output, codec, format);
}
}
public void write(@Nonnull LocalResource resource, @Nonnull ImageFormat format) throws CodecNotFoundException, ImageException, IOException {
write(resource, XAssets.getManager(), format);
}
public void write(@Nonnull OutputStream output) throws CodecNotFoundException, ImageException, IOException {
write(output, getFormat());
}
public void write(@Nonnull OutputStream output, @Nonnull AssetManager manager) throws CodecNotFoundException, ImageException, IOException {
write(output, manager, getFormat());
}
public void write(@Nonnull OutputStream output, @Nonnull AssetManager manager, @Nonnull ImageFormat format) throws CodecNotFoundException, ImageException, IOException {
write(output, manager.getCodec(format), format);
}
public void write(@Nonnull OutputStream output, @Nonnull ImageCodec codec) throws ImageException, IOException {
write(output, codec, getFormat());
}
public void write(@Nonnull OutputStream output, @Nonnull ImageCodec codec, @Nonnull ImageFormat format) throws ImageException, IOException {
if (codec.hasEncoder(format)) {
codec.write(getImage(), format, output);
}
else {
throw new ImageException(codec.getClass().getSimpleName() + "'s encoder for " + format + " format not available");
}
}
public void write(@Nonnull OutputStream output, @Nonnull ImageFormat format) throws CodecNotFoundException, ImageException, IOException {
write(output, XAssets.getManager(), format);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy