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 y = 0; y < img.getHeight(); y+=2) {
            for (int x = 0; x < img.getWidth(); x++) {
                Color col = new Color(img.getRGB(x, y));
                double pixVal = (col.getRed() + col.getBlue() + col.getGreen())/3;
                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 >= 230) {
            str = "`";
        } else if (g >= 220) {
            str = ".";
        } else if (g >= 210) {
            str = "'";
        } else if (g >= 200) {
            str = "_";
        } else if (g >= 190) {
            str = "*";
        } else if (g >= 180) {
            str = "v";
        } else if (g >= 170) {
            str = "|";
        } else if (g >= 160) {
            str = "+";
        } else if (g >= 150) {
            str = "=";
        } else if (g >= 140) {
            str = "{";
        } else if (g >= 120) {
            str = "^";
        } else if (g >= 110) {
            str = "&";
        } else if (g >= 100) {
            str = "I";
        } else if (g >= 90) {
            str = "%";
        } else if (g >= 80) {
            str = "$";
        } else if (g >= 60) {
            str = "0";
        } else if (g >= 50) {
            str = "9";
        } else if (g >= 40) {
            str = "8";
        } else if (g >= 30){
            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 pumpkin = new Pics("pumpkin", "png");
        pumpkin.printStats("Original");
        pumpkin.resize(33);
        pumpkin.printStats("Scaled");
        pumpkin.convertToAscii();
    }
}
Pics.main(null);
Original: 499298 389x413  images/MonaLisa.png
Scaled: 55625 128x136  images/tmp/MonaLisa.png
Original: 39392 302x265  images/pumpkin.png
Scaled: 10497 100x87  images/tmp/pumpkin.png

Grayscale

import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Color;

public class Grayscale{
  public static void main(String args[])throws IOException{
    File f = new File("images/MonaLisa.png");
    BufferedImage img = ImageIO.read(f);

    int width = img.getWidth();
    int height = img.getHeight();

    for(int y = 0; y < height; y++){
      for(int x = 0; x < width; x++){
        int p = img.getRGB(x,y);

        int a = (p>>24)&0xff;
        int r = (p>>16)&0xff;
        int g = (p>>8)&0xff;
        int b = p&0xff;

        int avg = (r+g+b)/3;

        p = (avg<<24) | (avg<<16) | (avg<<8) | avg;

        img.setRGB(x, y, p);
      }
    }

    try{
      f = new File("images/grayscale.png");
      ImageIO.write(img, "png", f);
      System.out.println("success!");
    }catch(IOException e){
      System.out.println(e);
    }
  }
}

Grayscale.main(null);
success!

Blue Scale

import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Color;

public class Bluescale{
  public static void main(String args[])throws IOException{
    File f = new File("images/MonaLisa.png");
    BufferedImage img = ImageIO.read(f);

    //get image width and height
    int width = img.getWidth();
    int height = img.getHeight();

    //convert to grayscale
    for(int y = 0; y < height; y++){
      for(int x = 0; x < width; x++){
        int p = img.getRGB(x,y);

        int a = (p>>24)&0xff;
        int r = (p>>16)&0xff;
        int g = (p>>8)&0xff;
        int b = p&0xff;

        //calculate average
        int avg = (r+g+b)/3;

        //replace RGB value with avg
        p = (a<<24) | (0) | (0) | avg;

        img.setRGB(x, y, p);
      }
    }

    //write image
    try{
      f = new File("images/bluescale.png");
      ImageIO.write(img, "png", f);
    }catch(IOException e){
      System.out.println(e);
    }
  }//main() ends here
}//class ends here

Bluescale.main(null);

Redscale

import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Color;

public class Redscale{
  public static void main(String args[])throws IOException{
    File f = new File("images/MonaLisa.png");
    BufferedImage img = ImageIO.read(f);

    //get image width and height
    int width = img.getWidth();
    int height = img.getHeight();

    //convert to grayscale
    for(int y = 0; y < height; y++){
      for(int x = 0; x < width; x++){
        int p = img.getRGB(x,y);

        int a = (p>>24)&0xff;
        int r = (p>>16)&0xff;
        int g = (p>>8)&0xff;
        int b = p&0xff;

        //calculate average
        int avg = (r+g+b)/3;

        //replace RGB value with avg
        p = (a<<24) | avg<<16 | 0 | 0;

        img.setRGB(x, y, p);
      }
    }

    //write image
    try{
      f = new File("images/redscale.png");
      ImageIO.write(img, "png", f);
    }catch(IOException e){
      System.out.println(e);
    }
  }//main() ends here
}//class ends here

Redscale.main(null);

Kind of creepy!

Greenscale

import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Color;

public class Greenscale{
  public static void main(String args[])throws IOException{
    File f = new File("images/MonaLisa.png");
    BufferedImage img = ImageIO.read(f);

    //get image width and height
    int width = img.getWidth();
    int height = img.getHeight();

    //convert to grayscale
    for(int y = 0; y < height; y++){
      for(int x = 0; x < width; x++){
        int p = img.getRGB(x,y);

        int a = (p>>24)&0xff;
        int r = (p>>16)&0xff;
        int g = (p>>8)&0xff;
        int b = p&0xff;

        //calculate average
        int avg = (r+g+b)/3;

        //replace RGB value with avg
        p = (a<<24) | 0 | avg<<8 | 0;

        img.setRGB(x, y, p);
      }
    }

    //write image
    try{
      f = new File("images/greenscale.png");
      ImageIO.write(img, "png", f);
    }catch(IOException e){
      System.out.println(e);
    }
  }//main() ends here
}//class ends here

Greenscale.main(null);