Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.awt.*;
- import java.net.URL;
- import java.util.Stack;
- import java.awt.Point;
- import java.io.*;
- /**
- * A class that represents a picture. This class inherits from SimplePicture
- * and allows the student to add functionality and picture effects.
- *
- * @author Barb Ericson (ericson@cc.gatech.edu)
- * (Copyright Georgia Institute of Technology 2004)
- * @author Modified by Colleen Lewis (colleenl@berkeley.edu),
- * Jonathan Kotker (jo_ko_berkeley@berkeley.edu),
- * Kaushik Iyer (kiyer@berkeley.edu), George Wang (georgewang@berkeley.edu),
- * and David Zeng (davidzeng@berkeley.edu), for use in CS61BL, the data
- * structures course at University of California, Berkeley.
- */
- public class Picture extends SimplePicture
- {
- /////////////////////////// Static Variables //////////////////////////////
- // Different axes available to flip a picture.
- public static final int HORIZONTAL = 1;
- public static final int VERTICAL = 2;
- public static final int FORWARD_DIAGONAL = 3;
- public static final int BACKWARD_DIAGONAL = 4;
- // Different Picture objects for the bitmaps used in ASCII art conversion.
- private static Picture BMP_AMPERSAND;
- private static Picture BMP_APOSTROPHE;
- private static Picture BMP_AT;
- private static Picture BMP_BAR;
- private static Picture BMP_COLON;
- private static Picture BMP_DOLLAR;
- private static Picture BMP_DOT;
- private static Picture BMP_EXCLAMATION;
- private static Picture BMP_GRAVE;
- private static Picture BMP_HASH;
- private static Picture BMP_PERCENT;
- private static Picture BMP_SEMICOLON;
- private static Picture BMP_SPACE;
- //////////////////////////// Constructors /////////////////////////////////
- /**
- * A constructor that takes no arguments.
- */
- public Picture () {
- super();
- }
- /**
- * Creates a Picture from the file name provided.
- *
- * @param fileName The name of the file to create the picture from.
- */
- public Picture(String fileName) {
- // Let the parent class handle this fileName.
- super(fileName);
- }
- /**
- * Creates a Picture from the width and height provided.
- *
- * @param width the width of the desired picture.
- * @param height the height of the desired picture.
- */
- public Picture(int width, int height) {
- // Let the parent class handle this width and height.
- super(width, height);
- }
- /**
- * Creates a copy of the Picture provided.
- *
- * @param pictureToCopy Picture to be copied.
- */
- public Picture(Picture pictureToCopy) {
- // Let the parent class do the copying.
- super(pictureToCopy);
- }
- /**
- * Creates a copy of the SimplePicture provided.
- *
- * @param pictureToCopy SimplePicture to be copied.
- */
- public Picture(SimplePicture pictureToCopy) {
- // Let the parent class do the copying.
- super(pictureToCopy);
- }
- /////////////////////////////// Methods ///////////////////////////////////
- /**
- * @return A string with information about the picture, such as
- * filename, height, and width.
- */
- public String toString() {
- String output = "Picture, filename = " + this.getFileName() + "," +
- " height = " + this.getHeight() + ", width = " + this.getWidth();
- return output;
- }
- /////////////////////// PROJECT 1 BEGINS HERE /////////////////////////////
- /* Each of the methods below is constructive: in other words, each of
- * the methods below generates a new Picture, without permanently
- * modifying the original Picture. */
- //////////////////////////////// Level 1 //////////////////////////////////
- /**
- * Converts the Picture into grayscale. Since any variation of gray
- * is obtained by setting the red, green, and blue components to the same
- * value, a Picture can be converted into its grayscale component
- * by setting the red, green, and blue components of each pixel in the
- * new picture to the same value: the average of the red, green, and blue
- * components of the same pixel in the original.
- *
- * @return A new Picture that is the grayscale version of this Picture.
- */
- public Picture grayscale() {
- Picture newPicture = new Picture(this);
- int pictureHeight = this.getHeight();
- int pictureWidth = this.getWidth();
- for(int x = 0; x < pictureWidth; x++) {
- for(int y = 0; y < pictureHeight; y++) {
- newPicture.setPixelToGray(x, y);
- }
- }
- return newPicture;
- }
- /**
- * Helper method for grayscale() to set a pixel at (x, y) to be gray.
- *
- * @param x The x-coordinate of the pixel to be set to gray.
- * @param y The y-coordinate of the pixel to be set to gray.
- */
- private void setPixelToGray(int x, int y) {
- Pixel currentPixel = this.getPixel(x, y);
- //Set the RGB value of colors to the average of the colors.
- int average = currentPixel.getAverage();
- currentPixel.setRed(average);
- currentPixel.setGreen(average);
- currentPixel.setBlue(average);
- }
- /**
- * Test method for setPixelToGray. This method is called by
- * the JUnit file through the public method Picture.helpersWork().
- */
- private static boolean setPixelToGrayWorks()
- {
- Picture bg = Picture.loadPicture("Creek.bmp");
- Pixel focalPixel = bg.getPixel(10, 10);
- bg.setPixelToGray(10, 10);
- int goalColor = (int) focalPixel.getAverage();
- int originalAlpha = focalPixel.getColor().getAlpha();
- boolean redCorrect = focalPixel.getRed() == goalColor;
- boolean greenCorrect = focalPixel.getGreen() == goalColor;
- boolean blueCorrect = focalPixel.getBlue() == goalColor;
- boolean alphaCorrect = focalPixel.getAlpha() == originalAlpha;
- return redCorrect && greenCorrect && blueCorrect && alphaCorrect;
- }
- /**
- * This method provide JUnit access to the testing methods written
- * within Picture.java
- */
- public static boolean helpersWork()
- {
- if (!Picture.setPixelToGrayWorks())
- {
- return false;
- }
- if( !Picture.setPixelToLightenWorks() )
- {
- return false;
- }
- // You could put other tests here..
- if( !Picture.convertChunkToAsciiWorks() )
- {
- return false;
- }
- //Test for Negate
- if (!Picture.setPixelToNegateWorks())
- {
- return false;
- }
- //Tests for adding blue
- if (!Picture. setPixelToAddBlueWorks(0)) // Tests to see if adding no extra blue will work
- {
- return false;
- }
- if (!Picture. setPixelToAddBlueWorks(255)) //Tests to see if completely saturating the blue will work
- {
- return false;
- }
- if (!Picture. setPixelToAddBlueWorks(1)) //Tests to see if adding some value of blue will work
- {
- return false;
- }
- //Tests for adding green
- if (!Picture. setPixelToAddGreenWorks(0)) // Tests to see if adding no extra green will work
- {
- return false;
- }
- if (!Picture. setPixelToAddGreenWorks(255)) //Tests to see if completely saturating the green will work
- {
- return false;
- }
- if (!Picture. setPixelToAddGreenWorks(1)) //Tests to see if adding some value of green will work
- {
- return false;
- }
- //Tests for adding red
- if (!Picture. setPixelToAddRedWorks(0)) // Tests to see if adding no extra red will work
- {
- return false;
- }
- if (!Picture. setPixelToAddRedWorks(255)) //Tests to see if completely saturating the red will work
- {
- return false;
- }
- if (!Picture. setPixelToAddRedWorks(1)) //Tests to see if adding some value of red will work
- {
- return false;
- }
- //Tests for Chromakey
- if (!Picture. setChromakeySize()) //Tests to see if the right sized image will be returned
- {
- return false;
- }
- //if (!Picture. checkExceedsThreshold(-5)) //Tests to see that threshold will be exceeded no matter what
- {
- // return false;
- }
- //if (Picture. checkExceedsThreshold(442)) //Tests to see that threshold will not be exceeded no matter what
- //(This is a little larger than the maximum color distance)
- {
- // return false;
- }
- return true;
- }
- /**
- * Converts the Picture into its photonegative version. The photonegative
- * version of an image is obtained by setting each of the red, green,
- * and blue components of every pixel to a value that is 255 minus their
- * current values.
- *
- * @return A new Picture that is the photonegative version of this Picture.
- */
- public Picture negate() {
- Picture newPicture = new Picture(this);
- int pictureHeight = this.getHeight();
- int pictureWidth = this.getWidth();
- for(int x = 0; x < pictureWidth; x++) {
- for(int y = 0; y < pictureHeight; y++)
- {
- newPicture.setPixelToNegate(x, y);
- }
- }
- return newPicture;
- }
- /**
- * Helper method for negate() to set a pixel at (x, y) to be photo negative.
- *
- * @param x The x-coordinate of the pixel to be set to gray.
- * @param y The y-coordinate of the pixel to be set to gray.
- */
- private void setPixelToNegate(int x, int y) {
- Pixel currentPixel = this.getPixel(x, y);
- currentPixel.setRed( 255 - currentPixel.getRed());
- currentPixel.setGreen(255 - currentPixel.getGreen());
- currentPixel.setBlue(255 - currentPixel.getBlue());
- }
- /**
- * Test method for setPixelToNegate. This method is called by
- * the JUnit file through the public method Picture.helpersWork().
- */
- private static boolean setPixelToNegateWorks()
- {
- Picture bg = Picture.loadPicture("Creek.bmp");
- Pixel focalPixel = bg.getPixel(10, 10);
- int goalRed = (255 - focalPixel.getRed());
- int goalGreen = (255 - focalPixel.getGreen());
- int goalBlue = (255 - focalPixel.getBlue());
- int originalAlpha = focalPixel.getColor().getAlpha();
- bg.setPixelToNegate(10, 10);
- boolean redCorrect = focalPixel.getRed() == goalRed;
- boolean greenCorrect = focalPixel.getGreen() == goalGreen;
- boolean blueCorrect = focalPixel.getBlue() == goalBlue;
- boolean alphaCorrect = focalPixel.getAlpha() == originalAlpha;
- return redCorrect && greenCorrect && blueCorrect && alphaCorrect;
- }
- /**
- * Creates an image that is lighter than the original image by amount. The range of
- * each color component should be between 0 and 255 in the new image. The
- * alpha value should not be changed.
- *
- * @return A new Picture that has every color value of the Picture increased
- * by the lightenAmount.
- */
- public Picture lighten(int lightenAmount) {
- Picture newPicture = new Picture(this);
- int pictureHeight = this.getHeight();
- int pictureWidth = this.getWidth();
- for(int x = 0; x < pictureWidth; x++)
- {
- for(int y = 0; y < pictureHeight; y++)
- {
- newPicture.setPixelToLighten(x, y , lightenAmount);
- }
- }
- return newPicture;
- }
- /**
- * Helper method for Lighten() to set a pixel at (x, y) to be lighter by amount.
- *
- * @param x The x-coordinate of the pixel to be set to gray.
- * @param y The y-coordinate of the pixel to be set to gray.
- */
- private void setPixelToLighten(int x, int y , int amount) {
- Pixel currentPixel = this.getPixel(x, y);
- currentPixel.setRed( amount + currentPixel.getRed());
- currentPixel.setGreen(amount + currentPixel.getGreen());
- currentPixel.setBlue( amount + currentPixel.getBlue());
- }
- /**
- * Test method for setPixelToLighten. This method is called by
- * the JUnit file through the public method Picture.helpersWork().
- */
- private static boolean setPixelToLightenWorks()
- {
- // Test the general case.
- Picture bg = Picture.loadPicture("Creek.bmp");
- Pixel focalPixel = bg.getPixel(10, 10);
- int originalRed = focalPixel.getRed();
- int originalGreen = focalPixel.getGreen();
- int originalBlue = focalPixel.getBlue();
- int originalAlpha = focalPixel.getAlpha();
- bg.setPixelToLighten(10, 10 , 30);
- Pixel newPixel = bg.getPixel(10, 10 );
- boolean redCorrect = newPixel.getRed() == originalRed + 30;
- boolean greenCorrect = newPixel.getGreen() == originalGreen + 30;
- boolean blueCorrect = newPixel.getBlue() == originalBlue + 30;
- boolean alphaCorrect = newPixel.getAlpha() == originalAlpha;
- if( ! (redCorrect && greenCorrect && blueCorrect && alphaCorrect) )
- {
- return false;
- }
- //Test the end cases.
- bg = Picture.loadPicture("Creek.bmp");
- focalPixel = bg.getPixel( bg.getWidth() -1 , bg.getHeight() -1 );
- originalRed = focalPixel.getRed();
- originalGreen = focalPixel.getGreen();
- originalBlue = focalPixel.getBlue();
- originalAlpha = focalPixel.getAlpha();
- bg.setPixelToLighten( bg.getWidth() -1 , bg.getHeight() -1, 30);
- newPixel = bg.getPixel(bg.getWidth() -1 , bg.getHeight() -1 );
- redCorrect = newPixel.getRed() == originalRed + 30;
- greenCorrect = newPixel.getGreen() == originalGreen + 30;
- blueCorrect = newPixel.getBlue() == originalBlue + 30;
- alphaCorrect = newPixel.getAlpha() == originalAlpha;
- if( ! (redCorrect && greenCorrect && blueCorrect && alphaCorrect) )
- {
- return false;
- }
- //Test the near-white pixels.
- bg = Picture.loadPicture("colleen.bmp");
- focalPixel = bg.getPixel( 40 , 10 );
- originalRed = focalPixel.getRed();
- originalGreen = focalPixel.getGreen();
- originalBlue = focalPixel.getBlue();
- originalAlpha = focalPixel.getAlpha();
- bg.setPixelToLighten( 40 , 10 , 30);
- redCorrect = 255 == originalRed;
- greenCorrect = 255 == originalGreen;
- blueCorrect = 255 == originalBlue;
- alphaCorrect = focalPixel.getAlpha() == originalAlpha;
- if( ! (redCorrect && greenCorrect && blueCorrect && alphaCorrect) )
- {
- return true;
- }
- return true;
- }
- /**
- * Creates an image that is darker than the original image by amount. The range of
- * each color component should be between 0 and 255 in the new image. The
- * alpha value should not be changed.
- *
- * @return A new Picture that has every color value of the Picture increased
- * by the lightenAmount.
- */
- public Picture darken(int darkenAmount) {
- Picture newPicture = new Picture(this);
- int pictureHeight = this.getHeight();
- int pictureWidth = this.getWidth();
- for(int x = 0; x < pictureWidth; x++) {
- for(int y = 0; y < pictureHeight; y++) {
- newPicture.setPixelToDarken(x, y , darkenAmount);
- }
- }
- return newPicture;
- }
- /**
- * Helper method for Darken() to set a pixel at (x, y) to be a darker by amount.
- *
- * @param x The x-coordinate of the pixel to be set to gray.
- * @param y The y-coordinate of the pixel to be set to gray.
- */
- private void setPixelToDarken(int x, int y , int amount) {
- Pixel currentPixel = this.getPixel(x, y);
- currentPixel.setRed( currentPixel.getRed() - amount);
- currentPixel.setGreen(currentPixel.getGreen() - amount);
- currentPixel.setBlue( currentPixel.getBlue() - amount);
- }
- /**
- * Creates an image where the blue value has been increased by amount.The range of
- * each color component should be between 0 and 255 in the new image. The
- * alpha value should not be changed.
- *
- * @return A new Picture that has every blue value of the Picture increased
- * by amount.
- */
- public Picture addBlue(int amount) {
- Picture newPicture = new Picture(this);
- int pictureHeight = this.getHeight();
- int pictureWidth = this.getWidth();
- for(int x = 0; x < pictureWidth; x++) {
- for(int y = 0; y < pictureHeight; y++) {
- newPicture.setPixelToAddBlue(x, y , amount);
- }
- }
- return newPicture;
- }
- /**
- * Helper method for addBlue() to set a pixel at (x, y) to be more Blue by blueAmount.
- *
- * @param x The x-coordinate of the pixel to be set to gray.
- * @param y The y-coordinate of the pixel to be set to gray.
- */
- private void setPixelToAddBlue(int x, int y , int blueAmount) {
- Pixel currentPixel = this.getPixel(x, y);
- currentPixel.setBlue( currentPixel.getBlue() + blueAmount);
- }
- /**
- * Test method for setPixelToAddBlue. This method is called by
- * the JUnit file through the public method Picture.helpersWork().
- */
- private static boolean setPixelToAddBlueWorks(int amount)
- {
- Picture bg = Picture.loadPicture("Creek.bmp");
- Pixel focalPixel = bg.getPixel(10, 10);
- int goalBlue = (focalPixel.getBlue() + amount);
- if(goalBlue > 255){
- goalBlue = 255; //The individual RGB and alpha values cannot exceed 255.
- }
- int originalAlpha = focalPixel.getColor().getAlpha();
- bg.setPixelToAddBlue(10, 10, amount);
- boolean blueCorrect = focalPixel.getBlue() == goalBlue;
- boolean alphaCorrect = focalPixel.getAlpha() == originalAlpha;
- return blueCorrect && alphaCorrect;
- }
- /**
- * Creates an image where the red value has been increased by amount. The range of
- * each color component should be between 0 and 255 in the new image. The
- * alpha value should not be changed.
- *
- * @return A new Picture that has every red value of the Picture increased
- * by amount.
- */
- public Picture addRed(int amount) {
- Picture newPicture = new Picture(this);
- int pictureHeight = this.getHeight();
- int pictureWidth = this.getWidth();
- for(int x = 0; x < pictureWidth; x++) {
- for(int y = 0; y < pictureHeight; y++) {
- newPicture.setPixelToAddRed(x, y , amount);
- }
- }
- return newPicture;
- }
- /**
- * Helper method for addRed() to set a pixel at (x, y) to be more red by redAmount.
- *
- * @param x The x-coordinate of the pixel to be set to gray.
- * @param y The y-coordinate of the pixel to be set to gray.
- */
- private void setPixelToAddRed(int x, int y , int redAmount) {
- Pixel currentPixel = this.getPixel(x, y);
- currentPixel.setRed( currentPixel.getRed() + redAmount);
- }
- /**
- * Test method for setPixelToAddRed. This method is called by
- * the JUnit file through the public method Picture.helpersWork().
- */
- private static boolean setPixelToAddRedWorks(int amount)
- {
- Picture bg = Picture.loadPicture("Creek.bmp");
- Pixel focalPixel = bg.getPixel(10, 10);
- int goalRed = (focalPixel.getRed() + amount);
- if(goalRed > 255){
- goalRed = 255; //The individual RGB and alpha values cannot exceed 255.
- }
- int originalAlpha = focalPixel.getColor().getAlpha();
- bg.setPixelToAddRed(10, 10, amount);
- boolean redCorrect = focalPixel.getRed() == goalRed;
- boolean alphaCorrect = focalPixel.getAlpha() == originalAlpha;
- return redCorrect && alphaCorrect;
- }
- /**
- * Creates an image where the green value has been increased by amount. The range of
- * each color component should be between 0 and 255 in the new image. The
- * alpha value should not be changed.
- *
- * @return A new Picture that has every green value of the Picture increased
- * by amount.
- */
- public Picture addGreen(int amount) {
- Picture newPicture = new Picture(this);
- int pictureHeight = this.getHeight();
- int pictureWidth = this.getWidth();
- for(int x = 0; x < pictureWidth; x++) {
- for(int y = 0; y < pictureHeight; y++) {
- newPicture.setPixelToAddGreen(x, y , amount);
- }
- }
- return newPicture;
- }
- /**
- * Helper method for addGreen() to set a pixel at (x, y) to be more green by greenAmount.
- *
- * @param x The x-coordinate of the pixel to be set to gray.
- * @param y The y-coordinate of the pixel to be set to gray.
- */
- private void setPixelToAddGreen(int x, int y , int greenAmount) {
- Pixel currentPixel = this.getPixel(x, y);
- currentPixel.setGreen( currentPixel.getGreen() + greenAmount);
- }
- /**
- * Test method for setPixelToAddBlue. This method is called by
- * the JUnit file through the public method Picture.helpersWork().
- */
- private static boolean setPixelToAddGreenWorks(int amount)
- {
- Picture bg = Picture.loadPicture("Creek.bmp");
- Pixel focalPixel = bg.getPixel(10, 10);
- int goalGreen = (focalPixel.getGreen() + amount);
- if(goalGreen > 255){
- goalGreen = 255; //The individual RGB and alpha values cannot exceed 255.
- }
- int originalAlpha = focalPixel.getColor().getAlpha();
- bg.setPixelToAddGreen(10, 10, amount);
- boolean greenCorrect = focalPixel.getGreen() == goalGreen;
- boolean alphaCorrect = focalPixel.getAlpha() == originalAlpha;
- return greenCorrect && alphaCorrect;
- }
- /**
- * @param x x-coordinate of the pixel currently selected.
- * @param y y-coordinate of the pixel currently selected.
- * @param background Picture to use as the background.
- * @param threshold Threshold within which to replace pixels.
- *
- * @return A new Picture where all the pixels in the original Picture,
- * which differ from the currently selected pixel within the provided
- * threshold (in terms of color distance), are replaced with the
- * corresponding pixels in the background picture provided.
- *
- * If the two Pictures are of different dimensions, the new Picture will
- * have length equal to the smallest of the two Pictures being combined,
- * and height equal to the smallest of the two Pictures being combined.
- * In this case, the Pictures are combined as if they were aligned at
- * the top left corner (0, 0).
- */
- public Picture chromaKey(int xRef, int yRef, Picture background, int threshold) {
- //Make a new picture with the dimensions of the smallest.
- int newWidth = Math.min(this.getWidth(), background.getWidth() );
- int newHeight = Math.min(this.getHeight(), background.getHeight() );
- Picture newPicture = new Picture(newWidth , newHeight);
- Color newColor = this.getPixel(xRef, yRef).getColor();
- for(int x = 0; x < newWidth; x++) {
- for(int y = 0; y < newHeight; y++) {
- int newAlpha, newRed , newGreen, newBlue;
- if( this.getPixel(x, y).colorDistance(newColor) < threshold )
- {
- //Replace the pixel with the correspondin one from the background.
- newAlpha = background.getPixel(x , y).getAlpha();
- newRed = background.getPixel(x , y).getRed();
- newGreen = background.getPixel(x , y).getGreen();
- newBlue = background.getPixel(x , y).getBlue();
- }
- else
- {
- //The Pixel comes from the foreground.
- newAlpha = this.getPixel(x , y).getAlpha();
- newRed = this.getPixel(x , y).getRed();
- newGreen = this.getPixel(x , y).getGreen();
- newBlue = this.getPixel(x , y).getBlue();
- }
- //Update the picture.
- newPicture.getPixel(x, y).updatePicture(newAlpha,newRed , newGreen, newBlue);
- }
- }
- return newPicture;
- }
- private static boolean setChromakeySize()
- {
- Picture bg1 = Picture.loadPicture("Creek.bmp");
- Picture bg2 = Picture.loadPicture("Colleen.bmp");
- int goalWidth = Math.min(bg1.getWidth(), bg2.getWidth() );
- int goalHeight = Math.min(bg1.getHeight(), bg2.getHeight() );
- Picture finalPic = bg2.chromaKey(1, 2, bg1, 30); //The only argument that really matters here is the third one: what the second picture is.
- boolean widthCorrect = finalPic.getWidth() == goalWidth;
- boolean heightCorrect = finalPic.getHeight() == goalHeight;
- return widthCorrect && heightCorrect;
- }
- //////////////////////////////// Level 2 //////////////////////////////////
- /**
- * Rotates this Picture by the integer multiple of 90 degrees provided.
- * If the number of rotations provided is positive, then the picture
- * is rotated clockwise; else, the picture is rotated counterclockwise.
- * Multiples of four rotations (including zero) correspond to no
- * rotation at all.
- *
- * @param rotations The number of 90-degree rotations to rotate this
- * image by.
- *
- * @return A new Picture that is the rotated version of this Picture.
- */
- public Picture rotate(int rotations) {
- int newWidth;
- int newHeight;
- //Get the dimensions of the new picture.
- if( rotations % 2 == 0 ) //The length and width do not change.
- {
- newWidth = this.getWidth();
- newHeight = this.getHeight();
- }else //The length and width are exchanged.
- {
- newWidth = this.getHeight();
- newHeight = this.getWidth();
- }
- Picture newPicture = new Picture( newWidth , newHeight );
- //Move every pixel.
- for( int x = 0 ; x < newPicture.getWidth() ; x++ )
- {
- for(int y = 0 ; y < newPicture.getHeight() ; y++ )
- {
- newPicture.rotatePixel( x , y , this, rotations );
- }
- }
- return newPicture;
- }
- /**
- * Helper method for Rotate(). Updates the pixel at (x,y) with color and
- * transparency information from the correct pixel in fromPicture according
- * to number of 90-degree rotations specified.
- *
- * @param x The x-coordinate of the pixel being updated.
- * @param y The y-coordinate of the pixel being updated.
- * @param fromPicture: the from which to get the corresponding pixel information.
- * @param rotations: The number of 90-degree rotations to rotate this
- * image by.
- */
- private void rotatePixel( int x , int y , Picture fromPicture, int rotations) {
- int fromX = x;
- int fromY = y;
- rotations %= 4;
- switch (rotations)
- {
- //No rotation is done.
- case 0:
- break;
- // Rotatate by +90deg = rotate by -270deg.
- case 1:
- case -3:
- fromX = y;
- fromY = fromPicture.getHeight() - x - 1;
- break;
- // Rotatate by +180deg = rotate by -180deg.
- case 2:
- case -2:
- fromX = fromPicture.getWidth() - x - 1;
- fromY = fromPicture.getHeight() - y - 1;
- break;
- // Rotatate by +270deg = rotate by -90deg.
- case 3:
- case -1:
- fromX = fromPicture.getWidth() - y - 1;
- fromY = x;
- break;
- //No rotation is done.
- default:
- break;
- }
- Pixel fromPixel = fromPicture.getPixel( fromX, fromY );
- //Get the color and transparancy information from Pixel.
- int newAlpha = fromPixel.getAlpha();
- int newRed = fromPixel.getRed();
- int newGreen = fromPixel.getGreen();
- int newBlue = fromPixel.getBlue();
- //Update the color and transparency of the pixel at (x,y) .
- this.getPixel( x , y ).updatePicture(newAlpha,newRed , newGreen, newBlue);
- }
- /**
- * Test method for rotatePixel. This method is called by
- * the JUnit file through the public method Picture.helpersWork().
- */
- private static boolean rotatePixelWorks()
- {
- // Test rotation by +90.
- Picture bg = Picture.loadPicture("Creek.bmp");
- int xOld = 43;
- int yOld = 23;
- Pixel focalPixel = bg.getPixel( xOld , yOld );
- int xNew = Math.pow( xOld , yOld)*Math.cos( Math.PI );
- int yNew = Math.pow( xOld , yOld)*Math.sin( Math.PI );
- int originalRed = focalPixel.getRed();
- int originalGreen = focalPixel.getGreen();
- int originalBlue = focalPixel.getBlue();
- int originalAlpha = focalPixel.getAlpha();
- bg.setPixelToLighten(10, 10 , 30);
- Pixel newPixel = bg.getPixel(10, 10 );
- boolean redCorrect = newPixel.getRed() == originalRed + 30;
- boolean greenCorrect = newPixel.getGreen() == originalGreen + 30;
- boolean blueCorrect = newPixel.getBlue() == originalBlue + 30;
- boolean alphaCorrect = newPixel.getAlpha() == originalAlpha;
- if( ! (redCorrect && greenCorrect && blueCorrect && alphaCorrect) )
- {
- return false;
- }
- //Test the end cases.
- bg = Picture.loadPicture("Creek.bmp");
- focalPixel = bg.getPixel( bg.getWidth() -1 , bg.getHeight() -1 );
- originalRed = focalPixel.getRed();
- originalGreen = focalPixel.getGreen();
- originalBlue = focalPixel.getBlue();
- originalAlpha = focalPixel.getAlpha();
- bg.setPixelToLighten( bg.getWidth() -1 , bg.getHeight() -1, 30);
- newPixel = bg.getPixel(bg.getWidth() -1 , bg.getHeight() -1 );
- redCorrect = newPixel.getRed() == originalRed + 30;
- greenCorrect = newPixel.getGreen() == originalGreen + 30;
- blueCorrect = newPixel.getBlue() == originalBlue + 30;
- alphaCorrect = newPixel.getAlpha() == originalAlpha;
- if( ! (redCorrect && greenCorrect && blueCorrect && alphaCorrect) )
- {
- return false;
- }
- //Test the near-white pixels.
- bg = Picture.loadPicture("colleen.bmp");
- focalPixel = bg.getPixel( 40 , 10 );
- originalRed = focalPixel.getRed();
- originalGreen = focalPixel.getGreen();
- originalBlue = focalPixel.getBlue();
- originalAlpha = focalPixel.getAlpha();
- bg.setPixelToLighten( 40 , 10 , 30);
- redCorrect = 255 == originalRed;
- greenCorrect = 255 == originalGreen;
- blueCorrect = 255 == originalBlue;
- alphaCorrect = focalPixel.getAlpha() == originalAlpha;
- if( ! (redCorrect && greenCorrect && blueCorrect && alphaCorrect) )
- {
- return true;
- }
- return true;
- }
- /**
- * Flips this Picture about the given axis. The axis can be one of
- * four static integer constants:
- *
- * (a) Picture.HORIZONTAL: The picture should be flipped about
- * a horizontal axis passing through the center of the picture.
- * (b) Picture.VERTICAL: The picture should be flipped about
- * a vertical axis passing through the center of the picture.
- * (c) Picture.FORWARD_DIAGONAL: The picture should be flipped about
- * an axis that passes through the north-east and south-west
- * corners of the picture.
- * (d) Picture.BACKWARD_DIAGONAL: The picture should be flipped about
- * an axis that passes through the north-west and south-east
- * corners of the picture.
- *
- * @param axis Axis about which to flip the Picture provided.
- *
- * @return A new Picture flipped about the axis provided.
- */
- public Picture flip(int axis) {
- int newWidth = 0;
- int newHeight = 0;;
- //Calculate the dimensions to fit the new picture.
- if( axis == VERTICAL || axis == HORIZONTAL )
- {
- //The Height and width dimensions stay the same
- newWidth = this.getWidth();
- newHeight = this.getHeight();
- }else if( axis == BACKWARD_DIAGONAL || axis == FORWARD_DIAGONAL )
- {
- //The Height and Width dimensions are exchanged.
- newWidth = this.getHeight();
- newHeight = this.getWidth();
- }
- Picture newPicture = new Picture( newWidth , newHeight );
- //Perform a transformation on each pixel.
- for( int x = 0 ; x < newPicture.getWidth() ; x++ )
- {
- for(int y = 0 ; y < newPicture.getHeight() ; y++ )
- {
- newPicture.flipPixel( x , y , this, axis );
- }
- }
- return newPicture;
- }
- /**
- * Helper method for Flip(). Updates the pixel at (x,y) with color and
- * transparency information from the correct pixel in fromPicture according
- * to axis. Where axis is an integer Representation of the axis of flip
- * (Horizontal , vertical, forward_Diagonal or backward_Diagonal ).
- *
- * @param x The x-coordinate of the pixel being updated.
- * @param y The y-coordinate of the pixel being updated.
- * @param fromPicture: the from which to get the corresponding pixel information.
- * @param axis: the axis of reflection, can be Horizontal , vertical or diagonal.
- */
- private void flipPixel( int x , int y , Picture fromPicture, int axis) {
- int fromX = x;
- int fromY = y;
- switch (axis)
- {
- case HORIZONTAL: //Flip along a horizontal axis.
- fromY = this.getHeight() - y - 1;
- break;
- case VERTICAL: //Flip along a vertical axis.
- fromX = this.getWidth() - x - 1;
- break;
- case BACKWARD_DIAGONAL: //Flip along a diagonal that passes through the
- //north-east and south-west corners of the picture
- fromX = y;
- fromY = x;
- break;
- case FORWARD_DIAGONAL: //Flip along a diagonal that passes through the
- //north-west and south-East corners of the picture
- fromX = this.getHeight() - y - 1;
- fromY = this.getWidth() - x - 1;
- break;
- default: //The current pixel does not change.
- fromX = x;
- fromY = y;
- }
- Pixel fromPixel = fromPicture.getPixel( fromX, fromY );
- //Get the color and transparancy information from Pixel.
- int newAlpha = fromPixel.getAlpha();
- int newRed = fromPixel.getRed();
- int newGreen = fromPixel.getGreen();
- int newBlue = fromPixel.getBlue();
- //Update the color and transparency of the pixel at (x,y) .
- this.getPixel( x , y ).updatePicture(newAlpha,newRed , newGreen, newBlue);
- }
- /**
- * @param threshold
- * Threshold to use to determine the presence of edges.
- *
- * @return A new Picture that contains only the edges of this Picture. For
- * each pixel, we separately consider the color distance between
- * that pixel and the one pixel to its left, and also the color
- * distance between that pixel and the one pixel to the north, where
- * applicable. As an example, we would compare the pixel at (3, 4)
- * with the pixels at (3, 3) and the pixels at (2, 4). Also, since
- * the pixel at (0, 4) only has a pixel to its north, we would only
- * compare it to that pixel. If either of the color distances is
- * larger than the provided color threshold, it is set to black
- * (with an alpha of 255); otherwise, the pixel is set to white
- * (with an alpha of 255). The pixel at (0, 0) will always be set to
- * white.
- */
- public Picture showEdges(int threshold) {
- Picture newPicture = new Picture(this);
- threshold = threshold + 1;
- int pictureHeight = this.getHeight() - 1;
- int pictureWidth = this.getWidth() - 1;
- for (int x = pictureWidth; x > 0; x--){
- for (int y = pictureHeight; y > 0; y--){
- Color upPixelColor = this.getPixel(x, y-1).getColor();
- Color leftPixelColor = this.getPixel(x-1, y).getColor();
- if( (this.getPixel(x, y).colorDistance(upPixelColor) < threshold) && (this.getPixel(x, y).colorDistance(leftPixelColor) < threshold) ){
- newPicture.getPixel( x , y ).updatePicture(255,255 , 255, 255);
- }
- else{
- newPicture.getPixel( x , y ).updatePicture(255, 0 , 0, 0);
- }
- }
- if(this.getPixel(x, 0).colorDistance( this.getPixel(x-1, 0).getColor()) < threshold){
- newPicture.getPixel( x , 0).updatePicture(255,255 , 255, 255);
- }
- else{
- newPicture.getPixel( x , 0).updatePicture(255, 0 , 0, 0);
- }
- }
- for(int y = pictureHeight; y > 0; y--){
- if(this.getPixel(0, y).colorDistance( this.getPixel(0, y-1).getColor()) < threshold){
- newPicture.getPixel( 0 , y ).updatePicture(255,255 , 255, 255);
- }
- else{
- newPicture.getPixel( 0 , y ).updatePicture(255, 0 , 0, 0);
- }
- }
- newPicture.getPixel( 0 , 0 ).updatePicture(255, 255, 255, 255);
- return newPicture;
- }
- //////////////////////////////// Level 3 //////////////////////////////////
- /**
- * @return A new Picture that is the ASCII art version of this Picture. To
- * implement this, the Picture is first converted into its grayscale
- * equivalent. Then, starting from the top left, the average color
- * of every chunk of 10 pixels wide by 20 pixels tall is computed.
- * Based on the average value obtained, this chunk will be replaced
- * by the corresponding ASCII character specified by the table
- * below.
- *
- * The ASCII characters to be used are available as Picture objects,
- * also of size 10 pixels by 20 pixels. The following characters
- * should be used, depending on the average value obtained:
- *
- * 0 to 18: # (Picture.BMP_POUND)
- * 19 to 37: @ (Picture.BMP_AT)
- * 38 to 56: & (Picture.BMP_AMPERSAND)
- * 57 to 75: $ (Picture.BMP_DOLLAR)
- * 76 to 94: % (Picture.BMP_PERCENT)
- * 95 to 113: | (Picture.BMP_BAR)
- * 114 to 132: ! (Picture.BMP_EXCLAMATION)
- * 133 to 151: ; (Picture.BMP_SEMICOLON)
- * 152 to 170: : (Picture.BMP_COLON)
- * 171 to 189: ' (Picture.BMP_APOSTROPHE)
- * 190 to 208: ` (Picture.BMP_GRAVE)
- * 209 to 227: . (Picture.BMP_DOT)
- * 228 to 255: (Picture.BMP_SPACE)
- *
- * We provide a getAsciiPic method to obtain the Picture object
- * corresponding to a character, given any of the static Strings
- * mentioned above.
- *
- * Note that the resultant Picture should be the exact same size
- * as the original Picture; this might involve characters being
- * partially copied to the final Picture.
- */
- public Picture convertToAscii() {
- Picture newPicture = new Picture( this );
- // Default chunk size
- int chunkSizeX = 10;
- int chunkSizeY = 20;
- //Convert to grayscale
- newPicture = newPicture.grayscale();
- //Convert chunks to ascii.
- for( int x = 0 ; x < newPicture.getWidth() ; x+= chunkSizeX )
- {
- for(int y = 0 ; y < newPicture.getHeight() ; y+= chunkSizeY )
- {
- newPicture.convertChunkToAscii( x , y , chunkSizeX ,chunkSizeY );
- }
- }
- return newPicture;
- }
- /**
- * Helper method for convertToAscii(). Updates the pixel at (x,y) with color and
- * transparency information from the correct pixel in fromPicture according
- * to axis. Where axis is an integer Representation of the axis of flip
- * (Horizontal , vertical, forward_Diagonal or backward_Diagonal ).
- *
- * @param x The x-coordinate of the pixel being updated.
- * @param y The y-coordinate of the pixel being updated.
- * @param fromPicture: the from which to get the corresponding pixel information.
- * @param axis: the axis of reflection, can be Horizontal , vertical or diagonal.
- */
- private void convertChunkToAscii( int x , int y , int chunkSizeX, int chunkSizeY) {
- int totalAverage = 0;
- int numPixels = 0;
- //Calculate the average color for the chunk.
- for(int Xsq = x ; Xsq < Math.min( x + chunkSizeX , this.getWidth() ) ; Xsq++ )
- {
- for(int Ysq = y ; Ysq < Math.min( y + chunkSizeY , this.getHeight() ) ; Ysq++ )
- {
- Pixel fromPixel = this.getPixel( Xsq, Ysq );
- totalAverage += fromPixel.getRed();
- numPixels++;
- }
- }
- int chunkAverageColor = totalAverage/numPixels;
- //Get the Ascii
- Picture asciiPic = Picture.getAsciiPic(chunkAverageColor);
- //Replace a chunk of picture with an ascii picture.
- for(int Xsq = x ; Xsq < Math.min( x + chunkSizeX , this.getWidth() ) ; Xsq++ )
- {
- for(int Ysq = y ; Ysq < Math.min( y + chunkSizeY , this.getHeight() ); Ysq++ )
- {
- Pixel fromPixel = asciiPic.getPixel( Xsq % 10 , Ysq % 20);
- int newAlpha = fromPixel.getAlpha();
- int newRed = fromPixel.getRed();
- int newGreen = fromPixel.getGreen();
- int newBlue = fromPixel.getBlue();
- //Update the color and transparency of the pixel at (x,y) .
- this.getPixel( Xsq , Ysq ).updatePicture( newAlpha, newRed , newGreen, newBlue);
- }
- }
- }
- /**
- * Test method for rotatePixel. This method is called by
- * the JUnit file through the public method Picture.helpersWork().
- */
- private static boolean convertChunkToAsciiWorks()
- {
- // Test the general Case:
- // The chunck is somewhere in the middle.
- int total = 0;
- Picture mickey = Picture.loadPicture("mickey.bmp");
- //Get the average of the colors.
- for( int i = 100 ; i < 100 + 10 ; i++ )
- {
- for( int j = 80 ; j < 80 + 20 ; j++ )
- {
- total += mickey.getPixel(i, j).getAverage();
- }
- }
- int ave = total / 200;
- Picture asciiPic = Picture.getAsciiPic(ave);
- mickey.convertChunkToAscii( 100 , 80 , 10 , 20 );
- asciiPic.show();
- for( int i = 100 ; i < 100 + 10 ; i++ )
- {
- for( int j = 80 ; j < 80 + 20 ; j++ )
- {
- Pixel currentPixel = mickey.getPixel(i, j);
- if( currentPixel.getColor().equals( asciiPic.getPixel(i - 100, j - 80) ) )
- {
- continue;
- }else
- {
- return false;
- }
- }
- }
- //Test when chunk is at the edge;
- return true;
- }
- /**
- * Blurs this Picture. To achieve this, the algorithm takes a pixel, and
- * sets it to the average value of all the pixels in a square of side (2 *
- * blurThreshold) + 1, centered at that pixel. For example, if blurThreshold
- * is 2, and the current pixel is at location (8, 10), then we will consider
- * the pixels in a 5 by 5 square that has corners at pixels (6, 8), (10, 8),
- * (6, 12), and (10, 12). If there are not enough pixels available -- if the
- * pixel is at the edge, for example, or if the threshold is larger than the
- * image -- then the missing pixels are ignored, and the average is taken
- * only of the pixels available.
- *
- * The red, blue, green and alpha values should each be averaged separately.
- *
- * @param blurThreshold
- * Size of the blurring square around the pixel.
- *
- * @return A new Picture that is the blurred version of this Picture, using
- * a blurring square of size (2 * threshold) + 1.
- */
- public Picture blur(int blurThreshold ) {
- Picture newPicture = new Picture( this );
- //Blur all pixels.
- for( int x = 0 ; x < newPicture.getWidth() ; x++ )
- {
- for(int y = 0 ; y < newPicture.getHeight() ; y++ )
- {
- newPicture.blurPixel( x , y , this, blurThreshold );
- }
- }
- return newPicture;
- }
- /**
- * Helper method for Blur(). Updates the pixel at (x,y) with average color and
- * transparency information of all the pixels in a square of side (2 *
- * blurThreshold) + 1 around it.
- *
- * @param x The x-coordinate of the pixel being blurred.
- * @param y The y-coordinate of the pixel being blurred.
- * @param fromPicture: the from which to get the corresponding pixel information.
- * @param threshold: Size of the blurring square around the pixel.
- */
- private void blurPixel( int x , int y , Picture fromPicture, int blurThreshold ) {
- int totalAlpha = 0;
- int totalRed = 0;
- int totalGreen = 0;
- int totalBlue = 0;
- int numPixels = 0;
- //for the square side (2T+1), Compute average of the colors.
- for(int Xsq = x - blurThreshold ; Xsq <= x + blurThreshold ; Xsq++ )
- {
- for(int Ysq = y - blurThreshold ; Ysq <= y + blurThreshold ; Ysq++ )
- {
- // Skip those unavailable pixels.
- if( Xsq < 0 || Xsq >= this.getWidth() || Ysq < 0 || Ysq >= this.getHeight() )
- {
- continue;
- }else
- {
- Pixel fromPixel = fromPicture.getPixel( Xsq, Ysq );
- //Get the color and transparancy information from the Pixel.
- totalAlpha += fromPixel.getAlpha();
- totalRed += fromPixel.getRed();
- totalGreen += fromPixel.getGreen();
- totalBlue += fromPixel.getBlue();
- numPixels++;
- }
- }
- }
- //Get the Average color and transparancy information from Pixel.
- int newAlpha = totalAlpha/numPixels;
- int newRed = totalRed/numPixels;
- int newGreen = totalGreen/numPixels;
- int newBlue = totalBlue/numPixels;
- //Update the color and transparency of the pixel at (x,y) .
- this.getPixel( x , y ).updatePicture(newAlpha,newRed , newGreen, newBlue);
- }
- /**
- * @param x x-coordinate of the pixel currently selected.
- * @param y y-coordinate of the pixel currently selected.
- * @param threshold Threshold within which to delete pixels.
- * @param newColor New color to color pixels.
- *
- * @return A new Picture where all the pixels connected to the currently
- * selected pixel, and which differ from the selected pixel within the
- * provided threshold (in terms of color distance), are colored with
- * the new color provided.
- */
- public Picture paintBucket(int x, int y, int threshold, Color newColor) {
- Pixel refPixel = this.getPixel(x, y);
- Picture newPicture = new Picture( this );
- Stack toStartVisitAt = new Stack();
- toStartVisitAt.push( new Point(x , y) ); //Stores Pixels yet to be processed.
- while( !toStartVisitAt.empty() ){ //While there are still pixels to be processed.
- Point nextPoint = (Point)toStartVisitAt.pop();
- x = (int)nextPoint.getX();
- y = (int)nextPoint.getY();
- newPicture.getPixel(x, y).setColor(newColor); //Fill the pixel.
- //Store EAST Pixel
- if( x + 1 < newPicture.getWidth() && refPixel.colorDistance( newPicture.getPixel(x + 1 , y).getColor() ) <= threshold )
- {
- toStartVisitAt.push( new Point( x + 1 , y ) );
- }
- //Store NORTH Pixel
- if( y + 1 < newPicture.getHeight() && refPixel.colorDistance( newPicture.getPixel(x , y + 1 ).getColor() ) <= threshold )
- {
- toStartVisitAt.push( new Point( x , y + 1 ) );
- }
- //Store WEST Pixel
- if( x - 1 >= 0 && refPixel.colorDistance( newPicture.getPixel(x - 1 , y).getColor() ) <= threshold )
- {
- toStartVisitAt.push( new Point( x - 1 , y ) );
- }
- //Store SOUTH Pixel
- if( y - 1 >= 0 && refPixel.colorDistance( newPicture.getPixel(x , y -1).getColor() ) <= threshold )
- {
- toStartVisitAt.push( new Point( x , y - 1) );
- }
- //Store NORTH-East Pixel
- if( x + 1 < newPicture.getWidth() && y + 1 < newPicture.getHeight()
- && refPixel.colorDistance( newPicture.getPixel(x + 1 , y + 1).getColor() ) < threshold )
- {
- toStartVisitAt.push( new Point( x + 1 , y + 1) );
- }
- //Store South-West Pixel
- if( x - 1 >= 0 && y - 1 >= 0
- && refPixel.colorDistance( newPicture.getPixel(x -1, y - 1 ).getColor() ) < threshold )
- {
- toStartVisitAt.push( new Point( x - 1, y - 1 ) );
- }
- //Store North-West Pixel
- if( x - 1 >= 0 && y + 1 < newPicture.getHeight()
- && refPixel.colorDistance( newPicture.getPixel(x - 1 , y + 1).getColor() ) < threshold )
- {
- toStartVisitAt.push( new Point( x - 1 , y + 1 ) );
- }
- //Store South-East Pixel
- if( x + 1 < newPicture.getWidth() && y - 1 >= 0
- && refPixel.colorDistance( newPicture.getPixel(x + 1 , y -1).getColor() ) < threshold )
- {
- toStartVisitAt.push( new Point( x +1 , y - 1) );
- }
- }
- return newPicture;
- }
- ///////////////////////// PROJECT 1 ENDS HERE /////////////////////////////
- public boolean equals(Object obj) {
- if (!(obj instanceof Picture)) {
- return false;
- }
- Picture p = (Picture) obj;
- // Check that the two pictures have the same dimensions.
- if ((p.getWidth() != this.getWidth()) ||
- (p.getHeight() != this.getHeight())) {
- return false;
- }
- // Check each pixel.
- for (int x = 0; x < this.getWidth(); x++) {
- for(int y = 0; y < this.getHeight(); y++) {
- if (!this.getPixel(x, y).equals(p.getPixel(x, y))) {
- return false;
- }
- }
- }
- return true;
- }
- /**
- * Helper method for loading a picture in the current directory.
- */
- protected static Picture loadPicture(String pictureName) {
- URL url = Picture.class.getResource(pictureName);
- return new Picture(url.getFile().replaceAll("%20", " "));
- }
- /**
- * Helper method for loading the pictures corresponding to each character
- * for the ASCII art conversion.
- */
- private static Picture getAsciiPic(int grayValue) {
- int asciiIndex = (int) grayValue / 19;
- if (BMP_AMPERSAND == null) {
- BMP_AMPERSAND = Picture.loadPicture("ampersand.bmp");
- BMP_APOSTROPHE = Picture.loadPicture("apostrophe.bmp");
- BMP_AT = Picture.loadPicture("at.bmp");
- BMP_BAR = Picture.loadPicture("bar.bmp");
- BMP_COLON = Picture.loadPicture("colon.bmp");
- BMP_DOLLAR = Picture.loadPicture("dollar.bmp");
- BMP_DOT = Picture.loadPicture("dot.bmp");
- BMP_EXCLAMATION = Picture.loadPicture("exclamation.bmp");
- BMP_GRAVE = Picture.loadPicture("grave.bmp");
- BMP_HASH = Picture.loadPicture("hash.bmp");
- BMP_PERCENT = Picture.loadPicture("percent.bmp");
- BMP_SEMICOLON = Picture.loadPicture("semicolon.bmp");
- BMP_SPACE = Picture.loadPicture("space.bmp");
- }
- switch(asciiIndex) {
- case 0:
- return Picture.BMP_HASH;
- case 1:
- return Picture.BMP_AT;
- case 2:
- return Picture.BMP_AMPERSAND;
- case 3:
- return Picture.BMP_DOLLAR;
- case 4:
- return Picture.BMP_PERCENT;
- case 5:
- return Picture.BMP_BAR;
- case 6:
- return Picture.BMP_EXCLAMATION;
- case 7:
- return Picture.BMP_SEMICOLON;
- case 8:
- return Picture.BMP_COLON;
- case 9:
- return Picture.BMP_APOSTROPHE;
- case 10:
- return Picture.BMP_GRAVE;
- case 11:
- return Picture.BMP_DOT;
- default:
- return Picture.BMP_SPACE;
- }
- }
- public static void main(String[] args) {
- Picture initialPicture = new Picture(
- FileChooser.pickAFile(FileChooser.OPEN));
- initialPicture.explore();
- }
- } // End of Picture class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement