• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Java image manipulation class

FL

Pokémon Island Creator
2,451
Posts
13
Years
    • Seen today
    This is the code that I made to resize, divide and correctly format for Essentials use the Chaos Rush sprites at http://www.pokecommunity.com/showthread.php?t=320775. There some useful methods for image manipulation.

    Code:
    import java.awt.Color;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Pattern;
    
    import javax.imageio.ImageIO;
    
    /**
     * This class facilitates the image manipulation.
     * Use factoryImageObject to create a instance loading from a string with the path.
     * An example that doubles the image size: <br>
     * 
     * ImageObject variableNameHere = ImageObject.factoryImageObject("imagename.png");
     * variableNameHere.multiplySize(2);
     * variableNameHere.writeFile("newimagename.png");
     * 
     * @author FL
    **/
    public class ImageObject implements Cloneable{
    	private int width;
    	private int height;
    	private int[][][] rgbaArray;
    	
    	private ImageObject(int width, int height){
    		this.width = width;
    		this.height = height;
    		rgbaArray = new int[width][height][4];
    	}
    	
    	/** 
    	 * Factory method that reads the file from a path
    	**/
    	public static ImageObject factoryImageObject(String filename) throws IOException {
    		BufferedImage bufferedImage = ImageIO.read(new File(filename));
    		ImageObject ret = new ImageObject(bufferedImage.getWidth(),bufferedImage.getHeight());
    		for (int line = 0; line < ret.height; line++) {
    			for (int column = 0; column < ret.width; column++) {
    				Color pixel = new Color(bufferedImage.getRGB(column, line),true);
    				ret.rgbaArray[column][line][0] = pixel.getRed();
    				ret.rgbaArray[column][line][1] = pixel.getGreen();
    				ret.rgbaArray[column][line][2] = pixel.getBlue();
    				ret.rgbaArray[column][line][3] = pixel.getAlpha();
    			}
    		}
    		return ret;
    	}
    
    	/**
    	 * Saves the image at a filename location. 
    	**/
    	public void writeFile(String filename) throws IOException {
    		File file = new File(filename);
    		BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    		for (int line = 0; line < height; line++) {
    			for (int column = 0; column < width; column++) {
    				int r = rgbaArray[column][line][0];
    				int g = rgbaArray[column][line][1];
    				int b = rgbaArray[column][line][2];
    				int a = rgbaArray[column][line][3];
    				Color pixel = new Color(r, g, b,a);
    				bufferedImage.setRGB(column, line, pixel.getRGB());
    			}
    		}
    		String[] splited = filename.split(Pattern.quote(".")); // Split at "." to get the extension
    		String extension = splited[splited.length-1].toUpperCase();
    		ImageIO.write(bufferedImage, extension, file);
    	}
    	
    	
    	/**
    	 * Concatenates imageObjects horizontally or vertically to create a new instance.
    	**/
    	public ImageObject(ImageObject[] imageObjectArray, boolean horizontally){
    		int number = imageObjectArray.length;
    		// Define size 
    		width = imageObjectArray[0].width;
    		height = imageObjectArray[0].height;
    		for (int i = 1; i < number; i++) {
    			if(horizontally){
    				width+=imageObjectArray[i].width;
    			}else{
    				height+=imageObjectArray[i].height;
    			}
    		}
    		rgbaArray = new int[width][height][4];
    		// Combine
    		for (int i = 0; i < number; i++) {
    			for (int line = 0; line < height; line++) {
    				for (int column = 0; column < width; column++) {
    					int x = column;
    					int y = line;
    					if(horizontally){
    						x += i*width;
    					}else{
    						y += i*height;
    					}
    					for (int color = 0; color < 4; color++) {
    						rgbaArray[x][y][color] = imageObjectArray[i].rgbaArray[column][line][color];
    					}
    				}
    			}
    		}
    	}	
    	
    	/**
    	 *  Divides the image in equals proportions
    	**/
    	public ImageObject[] divide(int number, boolean horizontally){ 
    		ImageObject[] ret = new ImageObject[number];
    		for (int i = 0; i < number; i++) {
    			ret[i] = new ImageObject(horizontally ? width/number : width, horizontally ? height : height/number);
    			for (int line = 0; line < ret[i].height; line++) {
    				for (int column = 0; column < ret[i].width; column++) {
    					int x = column;
    					int y = line;
    					if(horizontally){
    						x += i*width/number;
    					}else{
    						y += i*height/number;
    					}
    					for (int color = 0; color < 4; color++) {
    						ret[i].rgbaArray[column][line][color] = rgbaArray[x][y][color];
    					}
    				}
    			}
    		}
    		return ret;
    	}	
    	
    	/**
    	 * Resize the image size. 
    	 * Only accept multipler divisors like 2, 4, 0.5, 0.25
    	**/
    	public void multiplySize(double factor){ 
    		width *= factor;
    		height *= factor;
    		int multipler = factor > 1 ? (int)Math.round(factor) : 1;
    		int divider = factor < 1 ? (int)Math.round(1/factor) : 1;
    		int[][][] rgbaArrayNew = new int[width][height][4];
    		for (int line = 0; line < height; line++) {
    			for (int column = 0; column < width; column++) {
    				for (int color = 0; color < 4; color++) {
    					rgbaArrayNew[column/divider][line/divider][color] = rgbaArray[column/multipler][line/multipler][color];
    				}
    			}
    		}
    		rgbaArray = rgbaArrayNew;
    	}	
    	
    	/**
    	 * Remove the background.
    	 * Detects the background as the color that the most appears at the first line.
    	 * 
    	 * @return Number of pixel affected.
    	**/
    	public int removeBackground(){
    		return makeBackgroundTransparent(pickBackgroundRGB(0,0,width-1,0));
    	}
    	
    	/**
    	 * Picks the pixel that most appears at the param coordinates at image 
    	**/
    	protected int[] pickBackgroundRGB(int xstart, int ystart, int xend, int yend){
    		List <int[]> firstLine = new ArrayList<int[]>();
    		for(int y=ystart;y<=yend;y++){
    			for(int x=xstart;x<=xend;x++){
    				firstLine.add(new int[]{rgbaArray[x][y][0],rgbaArray[x][y][1],rgbaArray[x][y][2]});
    			}
    		}
    		int rgbBackground[] = new int[3];
    		int backgroundOccurrences = 0;
    		while(!firstLine.isEmpty()){
    			int rgbBackgroundNew[] = firstLine.get(0);
    			int backgroundOccurrencesNew = 0;
    			for(int i=0;i<firstLine.size();i++){
    				int array[] = firstLine.get(i);
    				if(rgbBackgroundNew[0]==array[0] && rgbBackgroundNew[1]==array[1] && rgbBackgroundNew[2]==array[2]){
    					backgroundOccurrencesNew++;
    					firstLine.remove(i--);
    				}
    			}
    			if(backgroundOccurrencesNew>backgroundOccurrences){
    				rgbBackground = rgbBackgroundNew;
    				backgroundOccurrences = backgroundOccurrencesNew;
    			}
    		}
    		return rgbBackground;
    	}
    	
    	/**
    	 * Search for every rgb equals to rgbTransparent at set the alpha to minimum, making it transparent.
    	 * 
    	 * @return Number of pixel affected.
    	**/
    	public int makeBackgroundTransparent(int[] rgbTransparent){
    		int ret = 0;
    		for (int line = 0; line < height; line++) {
    			for (int column = 0; column < width; column++) {
    				boolean equals = true;
    				for(int color=0;color<rgbTransparent.length;color++){
    					if(rgbaArray[column][line][color]!=rgbTransparent[color])
    						equals = false;
    				}
    				if(equals){
    					rgbaArray[column][line][3]=0;
    					ret++;
    				}	
    			}
    		}
    		return ret;
    	}
    	
    	public int makeBackgroundTransparent(int r, int g, int b){
    		return makeBackgroundTransparent(new int[]{r,g,b});
    	}
    	
    
    	/**
    	 * Increase or decrease the image size.
    	 * Don't mix positive and negative numbers! 
    	**/
    	public void addSize(int left, int up, int right, int down){ 
    		int widthNew = width+left+right;
    		int heightNew = height+up+down;
    		int[][][] rgbaArrayNew = new int[widthNew][heightNew][4];
    		if(left>0 || up>0 || right>0 || down>0){ // If increase the size, make the background transparent
    			int[] backgroundRGB = pickBackgroundRGB(0,0,width-1,height-1);
    			for (int line = 0; line < heightNew; line++) {
    				for (int column = 0; column < widthNew; column++) {
    					rgbaArrayNew[column][line][0] = backgroundRGB[0];
    					rgbaArrayNew[column][line][1] = backgroundRGB[1];
    					rgbaArrayNew[column][line][2] = backgroundRGB[2];
    					rgbaArrayNew[column][line][3] = 0;
    				}
    			}
    		}
    		for (int line = 0; line < (heightNew>height ? height : heightNew); line++) {
    			for (int column = 0; column < (widthNew>width ? width : widthNew); column++) {
    				for (int color = 0; color < 4; color++) {
    					int x = widthNew>width ? column : column-left;
    					int y = heightNew>height ? line : line-up;
    					int xNew = widthNew>width ? column+left : column;
    					int yNew = heightNew>height ? line+up : line;
    					rgbaArrayNew[xNew][yNew][color] = rgbaArray[x][y][color];
    				}
    			}
    		}
    		width = widthNew;
    		height = heightNew;
    		rgbaArray = rgbaArrayNew;
    	}
    	
    	public void addSize(int fourDirections){ 
    		addSize(fourDirections,fourDirections,fourDirections,fourDirections);
    	}
    }


    Code:
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author FL
    **/
    public class FormatImage {
    	public static void main(String[] args) {
    		copyImagesNumered(547,757,53);
    	}
    	
    	/**
    	 * Returns a list with names of all file at dir. 
    	**/
    	public static ArrayList<String> fileNames(String dir){
    		ArrayList<String> ret = new ArrayList<String>();
    		File folder = new File(dir);
    		File[] listOfFiles = folder.listFiles();
    
    	    for (int i = 0; i < listOfFiles.length; i++) {
    	    	if (listOfFiles[i].isFile()) {
    	    		ret.add(listOfFiles[i].getName());
    //	    		System.out.println("File " + listOfFiles[i].getName());
    //	    	} else if (listOfFiles[i].isDirectory()) {
    //	    		System.out.println("Directory " + listOfFiles[i].getName());
    	    	}
    	    }
    	    return ret;
    	}
    	
    	/**
    	 * Copy the numered image at Chaos Rush pack.
    	 * 
    	 * @param firstIndex : Count as image index
    	 * @param lastIndex : Count as image index
    	 * @param correction : Difference between the pokémon index and the image number.
    	**/
    	public static void copyImagesNumered(int firstIndex, int lastIndex, int correction){
    		String dirOriginal="original";
    		String[] dir = new String[]{"front","frontshiny","back","backshiny"};
    		String[] name = new String[]{"","s","b","sb"};
    		
    		String separatorDir = "/";
    		String separatorFile = ".";
    		String extension = "png";
    		
    		List <Integer> femaleSpriteNames = Arrays.asList(new Integer[]{521,592,593}); 
    		Map <Integer,Integer> exceptions = new HashMap<Integer,Integer>();
    		int[] exceptioNames = null;
    		int exceptionFirstIndex = 736;
    		exceptioNames = new int[]{
    				550,555,585,585,585,586,586,586,646,646,648,649,649,649,649,641,642,645,647
    		};
    		for(Integer exception : exceptioNames){
    			exceptions.put(exceptionFirstIndex++,exception);
    			if(exceptionFirstIndex==750+1) // Small numeration fix
    				exceptionFirstIndex += 3;
    		}
    		//exceptions.put(exceptionFirstIndex++,550);
    		//exceptions.put(exceptionFirstIndex++,555);
    		int index = 0;
    		int formIndex = 0;
    		int lastForm = 0;
    		
    		try {
    			index = firstIndex-correction;
    			while(index+correction<=lastIndex){
    				int originIndex = index+correction;
    				String originalLocation = dirOriginal+separatorDir+(originIndex)+separatorFile+extension;
    				ImageObject imageObject = ImageObject.factoryImageObject(originalLocation);
    //				imageObject.removeBackground();
    				imageObject.multiplySize(2);
    				String filename = index+"";
    				if(exceptions.containsKey(originIndex)){
    					int formName = exceptions.get(originIndex);
    					filename = formName+"";
    					formIndex = (formName == lastForm) ? formIndex+1 : 1;
    					lastForm = formName;
    				}else{
    					formIndex = 0;
    				}
    				boolean hadFemaleSprite = femaleSpriteNames.contains(index);
    				// Divides vertically the sprite if there two sprites for gender and add the "f" at the second sprite
    				ImageObject[] imageArrayGender = hadFemaleSprite ? imageObject.divide(2, false) : new ImageObject[]{imageObject};
    				boolean femaleSprite = false;
    				for(ImageObject imageObjectGender : imageArrayGender){
    					ImageObject[] imageObjectArray = imageObjectGender.divide(4, true);
    					for(int i=0;i<dir.length;i++){
    						String saveLocation = dir[i]+separatorDir+filename+(femaleSprite ? "f" : "")+name[i];
    						if(formIndex>0)
    							saveLocation+="_"+formIndex;
    						saveLocation+=separatorFile+extension;
    						imageObjectArray[i].removeBackground();
    						imageObjectArray[i].writeFile(saveLocation);
    					}
    					femaleSprite = true;
    				}
    				if(originIndex==750) // Small numeration fix
    					correction+=3;
    				if(originIndex==702) // Again
    					correction+=33;
    				
    				if(formIndex==0){ // Doesn't has the exception number
    					index++;
    				}else{
    					correction++;
    				}
    			}
    			System.out.println("Success!");
    		} catch (IOException e) {
    			System.out.println("Failed at "+(index+correction)+"!");
    			e.printStackTrace();
    		}
    	}
    }
     
    Last edited:
    378
    Posts
    11
    Years
    • Seen Oct 18, 2017
    Soooo where do I stick this script at?

    It's for Javascript, not Essentials. If you are making a game using Essentials, this is useless. If you're using Java, this is a gift from the gods themselves.
     

    FL

    Pokémon Island Creator
    2,451
    Posts
    13
    Years
    • Seen today
    It's for Javascript, not Essentials. If you are making a game using Essentials, this is useless. If you're using Java, this is a gift from the gods themselves.
    First, this code is written at Java, and Java != JavaScript.

    Second, I really wasn't clear explaining. I updated the Javadoc.

    Third, this code is not to be use directly at a game, but for manipulate images. With this class you can easily remove the background and double the size of all images in a folder, for example.
     
    Back
    Top