Hi. I've been in development of a simple GUI that converts image files into patterns usable within the popular game Minecraft.
The image files are read in, the ImagePixelate class sections up the image, and then the ColorAlgorithm class finds the nearest color in the palette available for each section of the image.
The problem is that after the first pixel in each section, the image reads in black pixels for the rest of the section. I assume that this is due to the image not loading completely. I've been using a MediaTracker to help with this, but to no avail. Can anyone help me fix this problem?
import java.awt.*; import java.awt.Image; import javax.swing.*; import java.awt.event.*; import java.io.*; import javax.swing.border.*; import javax.imageio.ImageIO; import java.awt.image.*; //---------------------------------------------------------- // ColorAlgorithm() - The algorithm by which the program determines // the closest color for each section of the image. // Author - Drew Murphy // April 14, 2011 //---------------------------------------------------------- public class ColorAlgorithm { private Color colorReturned; private byte result; public ColorAlgorithm(int[] pixels) { Color[] palette = { new Color(182,50,45), //red new Color(222,207,42), //yellow new Color(38,50,151), //blue new Color(53,74,23), //green new Color(0,0,0), //black new Color(255,255,255), //white new Color(81,48,26), //brown new Color(234,125,51), //orange new Color(41,121,154), //cyan new Color(125,48,193), //purple new Color(68,68,68), //gray new Color(142,168,223), //lightblue new Color(223,152,171), //pink new Color(61,200,49), //aquagreen new Color(192,76,203), //magenta new Color(155,162,162) //lightgray }; int[] colorBin = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //-------------------------------------------------- // Determines RGB values of each pixel in the array //-------------------------------------------------- for (int i=0; i < pixels.length; i+=25) { int c = pixels[i]; int redValue = (c & 0x00ff0000) >> 16; int greenValue = (c & 0x0000ff00) >> 8; int blueValue = c & 0x000000ff; Color colorPixel = new Color(redValue,greenValue,blueValue); result = findNearestColor(colorPixel, palette); colorBin[result] += 1; } int maxIndex = 0; //--------------------------------------- // Finds the bin with the maximum amount //--------------------------------------- for (int i = 0; i < colorBin.length; i++) { if (colorBin[i] >= colorBin[maxIndex]) maxIndex = i; } colorReturned = palette[maxIndex]; } public Color getColor() { return colorReturned; } //-------------------------------------------------------------------------------------------- // Uses straight line minimum distance algorithm to determine the closest color in the palette //-------------------------------------------------------------------------------------------- private static byte findNearestColor(Color color, Color[] palette) { int maxDistanceSquared = (255*255) + (255*255) + (255*255) + 1; byte bestIndex = 0; for (byte i = 0; i < palette.length; i++) { int Rdiff = color.getRed() - palette[i].getRed(); int Gdiff = color.getGreen() - palette[i].getGreen(); int Bdiff = color.getBlue() - palette[i].getBlue(); int distanceSquared = (Rdiff*Rdiff) + (Gdiff*Gdiff) + (Bdiff*Bdiff); if (distanceSquared < maxDistanceSquared) { maxDistanceSquared = distanceSquared; bestIndex = i; } } return bestIndex; } }
import java.awt.*; import java.awt.Image; import javax.swing.*; import java.awt.event.*; import java.io.*; import javax.swing.border.*; import javax.imageio.ImageIO; import java.awt.image.*; //---------------------------------------------------------- // ImagePixelate() - Sections the image and feeds the pixels // from each section into the algorithm. // Author - Drew Murphy // April 14, 2011 //---------------------------------------------------------- public class ImagePixelate { private Image renderedImage; //image returned to PixelFrame private Color[][] colorSchematic; //schematic determined from calling ColorAlgorithm //---------------- // Constructor //---------------- public ImagePixelate(Image toRender) { int height = -1; int width = -1; //-------------------- // MediaTracker call //-------------------- JLabel testCase = new JLabel(); MediaTracker tracker = new MediaTracker(testCase); tracker.addImage(toRender,1); try{ tracker.waitForAll(); height = toRender.getHeight(null); width = toRender.getWidth(null); } catch (InterruptedException e) { } renderedImage = toRender; //------------------------------------------------------------------------------------------ // Determining the size of each block given the user specified width of the image in blocks //------------------------------------------------------------------------------------------ float ratio = (float) width / (float) height; int numColumns = 24; float rowCalc = (float) numColumns / ratio; int numRows = (int) rowCalc; colorSchematic = new Color[numColumns][numRows]; int blockWidth = width / numColumns; int blockHeight = blockWidth; //------------------------------------------------------------------------------------------------ // Get the pixels of each block, and then use the algorithm to determine the closest palette color //------------------------------------------------------------------------------------------------ for (int x = 0; x < numColumns; x++) { for (int y = 0; y < numRows; y++) { int[] pixels = new int[blockWidth*blockHeight]; PixelGrabber grabber = new PixelGrabber(toRender, x*blockWidth, y*blockHeight, blockWidth, blockHeight, pixels, 0, blockWidth); try { grabber.grabPixels(); } catch (InterruptedException e) {} ColorAlgorithm currentSection = new ColorAlgorithm(pixels); colorSchematic[x][y] = currentSection.getColor(); } } System.out.println("Conversion complete."); } public Image getRenderedImage() { return renderedImage; } }
import java.awt.*; import java.awt.Image; import javax.swing.*; import java.awt.event.*; import java.io.*; import javax.swing.border.*; //---------------------------------------------------------- // PixelFrame() - Sets up the GUI for PixelCraft. // Author - Drew Murphy // April 14, 2011 //---------------------------------------------------------- public class PixelFrame{ private JTextArea fileSelected; private JLabel image; public PixelFrame() { JFrame frame = new JFrame ("Pixelcraft"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(1000,600); JPanel settings = new JPanel(); JPanel images = new JPanel(); JPanel window = new JPanel(); JPanel chooseFile = new JPanel(); JPanel updatePanel = new JPanel(); JPanel preferences = new JPanel(); //-------------- // ChooseFile panel //-------------- JButton browse = new JButton ("Browse"); browse.setBorder(BorderFactory.createLineBorder(Color.black,1)); browse.addActionListener(new FileListener()); fileSelected = new JTextArea ("C:\\"); fileSelected.setBorder(BorderFactory.createLineBorder(Color.black, 1)); fileSelected.setPreferredSize(new Dimension(200,18)); chooseFile.add(fileSelected); chooseFile.add(browse); //------------------- // Preferences panel //------------------- preferences.setLayout(new BoxLayout(preferences, BoxLayout.Y_AXIS)); preferences.setPreferredSize(new Dimension(100,500)); preferences.setBackground(Color.white); preferences.setBorder(BorderFactory.createLineBorder(Color.black,1)); JCheckBox red = new JCheckBox("Red Wool",true); JCheckBox yellow = new JCheckBox("Yellow Wool",true); JCheckBox blue = new JCheckBox("Blue Wool",true); JCheckBox green = new JCheckBox("Green Wool",true); JCheckBox black = new JCheckBox("Black Wool",true); JCheckBox white = new JCheckBox("White Wool",true); JCheckBox brown = new JCheckBox("Brown Wool",true); JCheckBox orange = new JCheckBox("Orange Wool",true); JCheckBox cyan = new JCheckBox("Cyan Wool",true); JCheckBox purple = new JCheckBox("Purple Wool",true); JCheckBox gray = new JCheckBox("Gray Wool",true); JCheckBox lightblue = new JCheckBox("Light Blue Wool",true); JCheckBox pink = new JCheckBox("Pink Wool",true); JCheckBox aquagreen = new JCheckBox("Aqua Green Wool",true); JCheckBox magenta = new JCheckBox("Magenta Wool",true); JCheckBox lightgray = new JCheckBox("Light Gray Wool",true); red.setBackground(Color.white); yellow.setBackground(Color.white); blue.setBackground(Color.white); green.setBackground(Color.white); black.setBackground(Color.white); white.setBackground(Color.white); brown.setBackground(Color.white); orange.setBackground(Color.white); cyan.setBackground(Color.white); purple.setBackground(Color.white); gray.setBackground(Color.white); lightblue.setBackground(Color.white); pink.setBackground(Color.white); aquagreen.setBackground(Color.white); magenta.setBackground(Color.white); lightgray.setBackground(Color.white); preferences.add(red); preferences.add(yellow); preferences.add(blue); preferences.add(green); preferences.add(black); preferences.add(white); preferences.add(brown); preferences.add(orange); preferences.add(cyan); preferences.add(purple); preferences.add(gray); preferences.add(lightblue); preferences.add(pink); preferences.add(aquagreen); preferences.add(magenta); preferences.add(lightgray); //------------- // UpdatePanel //------------- updatePanel.setLayout(new BorderLayout()); JLabel blockdescrip = new JLabel("Width in blocks: "); blockdescrip.setBorder(BorderFactory.createEmptyBorder(8,8,8,8)); blockdescrip.setPreferredSize(new Dimension(150,25)); JTextArea blockwidth = new JTextArea(); blockwidth.setPreferredSize(new Dimension(50,20)); blockwidth.setBorder(BorderFactory.createLineBorder(Color.black,1)); JButton create = new JButton("Create image!"); create.setBackground(Color.cyan); create.setPreferredSize(new Dimension(150,25)); create.addActionListener(new ButtonListener()); updatePanel.add(blockdescrip,BorderLayout.WEST); updatePanel.add(blockwidth,BorderLayout.CENTER); updatePanel.add(create,BorderLayout.EAST); //----------------- // Nested Panels //----------------- settings.setLayout(new BorderLayout()); settings.add(chooseFile,BorderLayout.NORTH); settings.add(preferences,BorderLayout.CENTER); settings.add(updatePanel,BorderLayout.SOUTH); images.setPreferredSize(new Dimension(800,600)); images.setBorder(BorderFactory.createEmptyBorder(8,8,8,8)); image= new JLabel(); images.add(image); window.setLayout(new BorderLayout()); window.add(settings,BorderLayout.WEST); window.add(images,BorderLayout.EAST); frame.add(window); frame.pack(); frame.setVisible(true); } //--------------- // File Selection //--------------- private class FileListener implements ActionListener{ public void actionPerformed (ActionEvent event) { JFileChooser choose = new JFileChooser(); int status = choose.showOpenDialog(null); if (status != JFileChooser.APPROVE_OPTION) fileSelected.setText("No File Chosen"); else { File file = choose.getSelectedFile(); fileSelected.setText(file.getAbsolutePath()); } } } //-------------------------------------------------------- // Runs the programs main function of pixelating the image //-------------------------------------------------------- private class ButtonListener implements ActionListener{ public void actionPerformed(ActionEvent event) { String fileName = fileSelected.getText(); Image resizedPicture = Toolkit.getDefaultToolkit().getImage(fileName); ImageIcon picture = new ImageIcon(fileName); JLabel test = new JLabel(); MediaTracker tracker = new MediaTracker(test); //-------------------------------------------- // Scale picture to fit on-screen, if necessary. //-------------------------------------------- if (resizedPicture.getWidth(null) > 800 || resizedPicture.getHeight(null) > 600) { if (resizedPicture.getWidth(null) > 800) { float ratio = 800 / (float)resizedPicture.getWidth(null); double width = 800.0; float height = (float)resizedPicture.getHeight(null) * ratio; resizedPicture = resizedPicture.getScaledInstance((int)width,(int)height,Image.SCALE_SMOOTH); } if (resizedPicture.getHeight(null) > 600) { float ratio = 600 / (float)resizedPicture.getHeight(null); double height = 600.0; float width = (float)resizedPicture.getWidth(null) * ratio; resizedPicture = resizedPicture.getScaledInstance((int)width,(int)height,Image.SCALE_SMOOTH); } } //------------------------------------------------------------------------------------- // Makes sure the image is loaded completely before invoking the ImagePixelate() class //------------------------------------------------------------------------------------- tracker.addImage(resizedPicture, 0); try{ tracker.waitForAll(); } catch (InterruptedException e) {} //-------------------------------------------------- // ImagePixelate call - Program's main function //-------------------------------------------------- ImagePixelate renderedPicture = new ImagePixelate(resizedPicture); Image renderedFinal = renderedPicture.getRenderedImage(); picture.setImage(renderedFinal); image.setIcon(picture); } } }
import java.awt.*; import javax.swing.*; import java.awt.event.*; import java.io.*; import javax.swing.border.*; //---------------------------------------------------------- // PixelCraft() - Simple class to call a PixelFrame object. // Author - Drew Murphy // April 14, 2011 //---------------------------------------------------------- public class PixelCraft extends PixelFrame { public static void main(String[] args) { PixelFrame frame = new PixelFrame(); } }