All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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