1  import java.awt.Color;
  2  import java.io.File;
  3  import java.net.URL;
  4  import java.awt.geom.AffineTransform;
  5  import java.awt.image.AffineTransformOp;
  6  import java.awt.image.BufferedImage;
  7  import java.awt.image.BufferedImageOp;
  8  import java.awt.image.ColorModel;
  9  import java.awt.image.Raster;
 10  import java.awt.image.WritableRaster;
 11  import javax.imageio.ImageIO;
 12  import javax.swing.ImageIcon;
 13  import javax.swing.JFileChooser;
 14  import javax.swing.JFrame;
 15  import javax.swing.JLabel;
 16  
 17  /**
 18   * This class allows you to view and edit pictures.
 19   */
 20  public class Picture
 21  { 
 22     private String source;
 23     private JFrame frame;
 24     private JLabel label;
 25     private BufferedImage image;
 26  
 27     /**
 28        Constructs a blank picture.
 29     */
 30     public Picture()
 31     {
 32        frame = new JFrame();
 33        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 34        label = new JLabel("(No image)");
 35        frame.add(label);
 36        frame.pack();
 37        frame.setVisible(true);      
 38     }
 39    
 40     /**
 41        Gets the width of this picture.
 42        @return the width
 43      */
 44     public int getWidth() { return image.getWidth(); }
 45     
 46     /**
 47        Gets the height of this picture.
 48        @return the height
 49      */
 50     public int getHeight() { return image.getHeight(); }
 51     
 52     /**
 53        Loads a picture from a given source. 
 54        @param source the image source. If the source starts
 55        with http://, it is a URL, otherwise, a filename.
 56      */
 57     public void load(String source)
 58     {
 59        try 
 60        {
 61           this.source = source;
 62           BufferedImage img;
 63           if (source.startsWith("http://"))
 64              img = ImageIO.read(new URL(source).openStream());
 65           else
 66              img = ImageIO.read(new File(source));
 67  
 68           setImage(img);        
 69        }
 70        catch (Exception ex)
 71        {
 72           this.source = null;
 73           ex.printStackTrace();
 74        }
 75     }      
 76  
 77     /**
 78        Reloads this picture, undoing any manipulations.
 79      */
 80     public void reload()
 81     {
 82        load(source);
 83     }
 84     
 85     /**
 86        Displays a file chooser for picking a picture.
 87      */
 88     public void pick()
 89     {
 90        JFileChooser chooser = new JFileChooser(".");
 91        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
 92        {
 93           load(chooser.getSelectedFile().getAbsolutePath());
 94        }
 95     }   
 96  
 97     /**
 98        Moves this picture by the given amount in x- and y-direction. 
 99        @param dx the offset in the x-direction
100        @param dy the offset in the y-direction
101      */
102     public void move(int dx, int dy)
103     {
104        BufferedImageOp op = new AffineTransformOp(
105           AffineTransform.getTranslateInstance(dx, dy), 
106           AffineTransformOp.TYPE_BILINEAR);
107        BufferedImage filteredImage
108           = new BufferedImage(image.getWidth(), image.getHeight(), 
109              BufferedImage.TYPE_INT_ARGB);
110        op.filter(image, filteredImage);
111        setImage(filteredImage);
112     }
113  
114     /**
115        Scales this picture to a new size. If the new size is smaller 
116        than the old size, the remainder is filled with transparent 
117        pixels. If it is larger, it is clipped.
118        @param newWidth the new width of the picture
119        @param newHeight the new height of the picture
120     */
121     public void scale(int newWidth, int newHeight)
122     {
123        double dx = newWidth * 1.0 / image.getWidth();
124        double dy = newHeight * 1.0 / image.getHeight();
125        BufferedImageOp op = new AffineTransformOp(
126           AffineTransform.getScaleInstance(dx, dy), 
127           AffineTransformOp.TYPE_BILINEAR);
128        BufferedImage filteredImage
129           = new BufferedImage(image.getWidth(), image.getHeight(), 
130              BufferedImage.TYPE_INT_ARGB);
131        op.filter(image, filteredImage);
132        setImage(filteredImage);
133     }
134  
135     /**
136        Adds a black border to the image.
137        @param width the border width
138     */
139     public void border(int width)
140     {
141        for (int x = 0; x < width; x++)
142        {
143           for (int y = 0; y < image.getHeight(); y++)
144           {
145              setColorAt(x, y, Color.BLACK);
146              setColorAt(image.getWidth() - 1 - x, y, Color.BLACK);      
147           }
148        }
149        for (int y = 0;  y < width; y++)
150        {
151           for (int x = width; x < image.getWidth() - width; x++)
152           {
153              setColorAt(x, y, Color.BLACK);
154              setColorAt(x, image.getHeight() - 1 - y, Color.BLACK);      
155           }
156        }
157     }
158  
159     /**
160        Gets the color of a pixel.
161        @param x the column index (between 0 and getWidth() - 1)
162        @param y the row index (between 0 and getHeight() - 1)
163        @return the color of the pixel at position (x, y)
164     */
165     public Color getColorAt(int x, int y)
166     {
167        Raster raster = image.getRaster();
168        ColorModel model = image.getColorModel();
169        int argb = model.getRGB(raster.getDataElements(x, y, null));
170        return new Color(argb, true);
171     }
172  
173     /**
174        Sets the color of a pixel.
175        @param x the column index (between 0 and getWidth() - 1)
176        @param y the row index (between 0 and getHeight() - 1)
177        @param c the color for the pixel at position (x, y)
178     */
179     public void setColorAt(int x, int y, Color c)
180     {
181        WritableRaster raster = image.getRaster();
182        ColorModel model = image.getColorModel();
183        Object colorData = model.getDataElements(c.getRGB(), null);
184        raster.setDataElements(x, y, colorData);
185        label.repaint();
186     }
187  
188     private void setImage(BufferedImage image)
189     {
190        this.image = image;
191        label.setIcon(new ImageIcon(image));
192        label.setText("");
193        label.setSize(image.getWidth(), image.getHeight());
194        frame.pack();
195     }
196  }