ASCII

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.awt.Graphics2D;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;

public class Pics {
    private final String inDir = "images/"; // location of images
    private final String outDir = "images/tmp/";  // location of created files
    private String inFile;
    private String resizedFile;
    private String asciiFile; 
    private String ext;   // extension of file
    private long bytes;
    private int width;
    private int height;

    // Constructor obtains attributes of picture
    public Pics(String name, String ext) {
        this.ext = ext;
        this.inFile = this.inDir + name + "." + ext;
        this.resizedFile = this.outDir + name + "." + ext;
        this.asciiFile = this.outDir + name + ".txt";
        this.setStats();
    }

    
    // An image contains metadata, namely size, width, and height
    public void setStats() {
        BufferedImage img;
        try {
            Path path = Paths.get(this.inFile);
            this.bytes = Files.size(path);
            img = ImageIO.read(new File(this.inFile));
            this.width = img.getWidth();
            this.height = img.getHeight();
        } catch (IOException e) {
        }
    }

    // Console print of data
    public void printStats(String msg) {
        System.out.println(msg + ": " + this.bytes + " " + this.width + "x" + this.height + "  " + this.inFile);
    }

    // Convert scaled image into buffered image
    public static BufferedImage convertToBufferedImage(Image img) {

        // Create a buffered image with transparency
        BufferedImage bi = new BufferedImage(
                img.getWidth(null), img.getHeight(null),
                BufferedImage.TYPE_INT_ARGB);

        // magic?
        Graphics2D graphics2D = bi.createGraphics();
        graphics2D.drawImage(img, 0, 0, null);
        graphics2D.dispose();

        return bi;
    }
    
    // Scale or reduce to "scale" percentage provided
    public void resize(int scale) {
        BufferedImage img = null;
        Image resizedImg = null;  

        int width = (int) (this.width * (scale/100.0) + 0.5);
        int height = (int) (this.height * (scale/100.0) + 0.5);

        try {
            // read an image to BufferedImage for processing
            img = ImageIO.read(new File(this.inFile));  // set buffer of image data
            // create a new BufferedImage for drawing
            resizedImg = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        } catch (IOException e) {
            return;
        }

        try {
            ImageIO.write(convertToBufferedImage(resizedImg), this.ext, new File(resizedFile));
        } catch (IOException e) {
            return;
        }
        
        this.inFile = this.resizedFile;  // use scaled file vs original file in Class
        this.setStats();
    }
    
    // convert every pixel to an ascii character (ratio does not seem correct)
    public void convertToAscii() {
        BufferedImage img = null;
        PrintWriter asciiPrt = null;
        FileWriter asciiWrt = null;

        try {
            File file = new File(this.asciiFile);
            Files.deleteIfExists(file.toPath()); 
        } catch (IOException e) {
            System.out.println("Delete File error: " + e);
        }

        try {
            asciiPrt = new PrintWriter(asciiWrt = new FileWriter(this.asciiFile, true));
        } catch (IOException e) {
            System.out.println("ASCII out file create error: " + e);
        }

        try {
            img = ImageIO.read(new File(this.inFile));
        } catch (IOException e) {
        }

        for (int i = 0; i < img.getHeight(); i+=2) {
            for (int j = 0; j < img.getWidth(); j+=1) {
                Color col = new Color(img.getRGB(j, i));
                double pixVal = (((col.getRed() * 0.30) + (col.getBlue() * 0.59) + (col
                        .getGreen() * 0.11)));
                try {
                    asciiPrt.print(asciiChar(pixVal));
                    asciiPrt.flush();
                    asciiWrt.flush();
                } catch (Exception ex) {
                }
            }
            try {
                asciiPrt.println("");
                asciiPrt.flush();
                asciiWrt.flush();
            } catch (Exception ex) {
            }
        }
    }

    // conversion table, there may be better out there ie https://www.billmongan.com/Ursinus-CS173-Fall2020/Labs/ASCIIArt
    public String asciiChar(double g) {
        String str = " ";
        if (g >= 240) {
            str = " ";
        } else if (g >= 210) {
            str = ".";
        } else if (g >= 190) {
            str = "-";
        } else if (g >= 170) {
            str = "*";
        } else if (g >= 160) {
            str = "+";
        } else if (g >= 150) {
            str = "j";
        }else if (g >= 140) {
            str = "n";
        }else if (g >= 130) {
            str = "V";
        } else if (g >= 120) {
            str = "3";
        } else if (g >= 110) {
            str = "5";
        } else if (g >= 100) {
            str = "&"; 
        } else if (g >= 90) {
            str = "g"; 
        }else if (g >= 80) {
            str = "8";
        } else if (g >= 60) {
            str = "#";
        } else {
            str = "@";
        }
        return str;
    }

    // tester/driver
    public static void main(String[] args) throws IOException {
        Pics monaLisa = new Pics("MonaLisa", "png");
        monaLisa.printStats("Original");
        monaLisa.resize(33);
        monaLisa.printStats("Scaled");
        monaLisa.convertToAscii();

        
    }
}
Pics.main(null);
Original: 499298 389x413  images/MonaLisa.png
Scaled: 55625 128x136  images/tmp/MonaLisa.png

Explanation of code

First, the monaLisa object is created, which calls the Pics constructor and passes in a name of MonaLisa and an ext (extension) of .png. These are assigned to the attributes, creating an input file (images/MonaLisa.png), an output (resized) file (images/MonaLisa.png), and an output (ASCII) file (images/tmp/MonaLisa.txt).

Next, the setStats() method is called. The path of the input file is assigned to the path object. The number of bytes is also assigned, and then ImageIO reads the input file and obtains its width and height, assigning them to their respective variables.

Now going back to the main method, the monaLisa object calls the printStats() method and passes in the argument of "Original". This basically outputs some information of the input file, such as its size, width, and height. As you can see in the output above, the printStats() method outputs, Original: 499298 389x413 images/MonaLisa.png.

Afterwards, the monaLisa object calls the resize() method with an argument of 33 (resize the image to 33%). An Image object is created. Note: this is really important, the Image object needs to be created out of the try catch block, because if it is created within, the scope of the Image object is within the try catch block and can not be accessed outside. See this for more info. Moving on, the width and height are defined based on the resized scale, and the input file is once again read into img. The resizedImg is obtained by using the getScaledInstance method and assigning it the resized width and height. Next, resizedImg is converted into a buffered image with the name of the resizedFile (images/tmp/MonaLisa.png). The resizedFile is then set as the path of the input file. Once again, the setStats() method is called.

Because of scope of variables, some values of the variables have changed. The path of the input file (inFile) is now assigned to path. The size of the resized file is recorded, and the file is also read in by ImageIO. Additionally, the width and height of the resized file is recorded.

Going back to the main method, the printStats() method is called. Same thing as before, this outputs Scaled: 55625 128x136 images/tmp/MonaLisa.png.

Lastly, the convertToAscii() method is called. Once again, the Image object needs to be set as null outside of the try catch block in order to fulfill the scope of the variable. The first try catch block ensures that if there is already an Ascii file in the output directory, the file would be removed. Next, the PrintWriter and FileWriter object is called to output text (ASCII characters) into the ASCII file (images/tmp/MonaLisa.txt). ImageIO then reads the input file.

Onto the for loop, each pixel of the image is iterated, and a value is calculated based on the RGB value of the pixel. The larger the value (closer to white, or 255), the less space the ASCII character will pick up. As for smaller values (closer to black, or 0), the ASCII character will take up more space. This is called by the asciiChar(double g) method, and it returns the ASCII character.

Grayscale

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.awt.Graphics2D;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;

abstract class Pics {
     
    final String inDir = "images/"; // location of images
    final String outDir = "images/tmp/";  // location of created files
    String inFile;
    String resizedFile;
    String grayscaleFile; 
    String outFile; 
    String ext;   // extension of file
    long bytes;
    int width;
    int height;
    

    // Constructor obtains attributes of picture
     
    public Pics(String name, String ext) {
        this.ext = ext;
        this.inFile = this.inDir + name + "." + ext;
        this.outFile = this.outDir + name + "New." + ext;
    }
   
 
    // convert every pixel to an ascii character (ratio does not seem correct)
    public void changePic() {
        BufferedImage img; 
        
        try {
            File file = new File(this.outFile);
            Files.deleteIfExists(file.toPath()); 
        } catch (IOException e) {
            System.out.println("Delete File error: " + e);
        }

        
      
        test();
      

    }

    protected abstract void test(); 


}
public class Grayscale extends Pics {
     
   public Grayscale(String name, String ext) {
    super(name, ext);
   }

   protected void test() {
    BufferedImage img;
    try {
        img = ImageIO.read(new File(this.inFile));
        for (int i = 0; i < img.getHeight(); i++) {
            for (int j = 0; j < img.getWidth(); j++) {
                Color col = new Color(img.getRGB(j, i));

                int red = (int)(col.getRed() * 0.299);
                int green = (int)(col.getGreen() * 0.587);
                int blue = (int)(col.getBlue() * 0.114); 
                Color rgb = new Color(red + green + blue, red + green + blue, red + green + blue);
   
                img.setRGB(j, i, rgb.getRGB());
             
            }
           
        }
         
        ImageIO.write(img, "png", new File(super.outFile));
    } catch (IOException e) {
    }
   }


    
  
    // tester/driver
    public static void main(String[] args) throws IOException {
        // Pics monaLisa = new Pics("MonaLisa", "png");
        Grayscale monaLisa = new Grayscale("MonaLisa", "png" );
        monaLisa.changePic(); 

        
    }
}
Grayscale.main(null);

Red

public class Redscale extends Pics {
     
    public Redscale(String name, String ext) {
     super(name, ext);
    }
 
    protected void test() {
     BufferedImage img;
     try {
         img = ImageIO.read(new File(this.inFile));
         for (int i = 0; i < img.getHeight(); i++) {
             for (int j = 0; j < img.getWidth(); j++) {
                Color col = new Color(img.getRGB(j, i));
                    
                    int red = (int)(col.getRed());
                    Color rgb = new Color(red, 0, 0);
       
                    img.setRGB(j, i, rgb.getRGB());
              
             }
            
         }
          
         ImageIO.write(img, "png", new File(super.outFile));
     } catch (IOException e) {
     }
    }
 
 
     
   
     // tester/driver
     public static void main(String[] args) throws IOException {
         // Pics monaLisa = new Pics("MonaLisa", "png");
         Redscale monaLisa = new Redscale("MonaLisa", "png" );
         monaLisa.changePic(); 
 
         
     }
 }
 Redscale.main(null);

Blue

public class Bluescale extends Pics {
     
    public Bluescale(String name, String ext) {
     super(name, ext);
    }
 
    protected void test() {
     BufferedImage img;
     try {
         img = ImageIO.read(new File(this.inFile));
         for (int i = 0; i < img.getHeight(); i++) {
             for (int j = 0; j < img.getWidth(); j++) {
                Color col = new Color(img.getRGB(j, i));
                    
                int blue = (int)(col.getBlue());
                Color rgb = new Color(0, 0, blue);
   
                img.setRGB(j, i, rgb.getRGB());
              
             }
            
         }
          
         ImageIO.write(img, "png", new File(super.outFile));
     } catch (IOException e) {
     }
    }
 
 
     
   
     // tester/driver
     public static void main(String[] args) throws IOException {
         // Pics monaLisa = new Pics("MonaLisa", "png");
         Bluescale monaLisa = new Bluescale("MonaLisa", "png" );
         monaLisa.changePic(); 
 
         
     }
 }
 Bluescale.main(null);

Green

public class Greenscale extends Pics {
     
    public Greenscale(String name, String ext) {
     super(name, ext);
    }
 
    protected void test() {
     BufferedImage img;
     try {
         img = ImageIO.read(new File(this.inFile));
         for (int i = 0; i < img.getHeight(); i++) {
             for (int j = 0; j < img.getWidth(); j++) {
                Color col = new Color(img.getRGB(j, i));
                    
                int green = (int)(col.getGreen());
                Color rgb = new Color(0, green, 0);
   
                img.setRGB(j, i, rgb.getRGB());
              
             }
            
         }
          
         ImageIO.write(img, "png", new File(super.outFile));
     } catch (IOException e) {
     }
    }
 
 
     
   
     // tester/driver
     public static void main(String[] args) throws IOException {
         // Pics monaLisa = new Pics("MonaLisa", "png");
         Greenscale monaLisa = new Greenscale("MonaLisa", "png" );
         monaLisa.changePic(); 
 
         
     }
 }
 Greenscale.main(null);