3

How does such an image conversion algorithm work?

I want to convert a bitmap to ASCII art. Can anyone help me out what sort of algorithm should I use?

                 .   W    ,                
                 W   W    @                
                 W  ,W    W                
              ,  W, :W*  .W  .             
              #  WW @WW  WW  #             
              W  WW.WWW  WW: W             
              W. WW*WWW# WW@ W             
           * :WW.WWWWWWW@WWW@W  #          
          +* #WW#WWWWWWWWWWWWW# W          
          W# @WWWWWWWWWWWWWWWWW W          
          WW WWWWWWWWWWWWWWWWWW W          
          WW WWWWWWWWWWWWWWWWWW@W#         
         ,WW.WWWWWWWWWWWWWWWWWWWWW         
          WW@WWWWWWWWWWWWWWWWWWWWW         
        : WWWWWWWWWWWWWWWWWWWWWWWW :       
        @ WWWWWWWW@WWWWWWW@@WWWWWW.        
        W*WWWWWW::::@WWW:::::#WWWWW        
        WWWWWW@::   :+*:.   ::@WWWW        
        WWWWW@:*:.::     .,.:.:WWWW        
        @WWWW#:.:::.     .:: #:@WWW        
        :WWW@:#. ::     :WWWW:@WWWW        
         WWW#*:W@*@W     .   W:#WWW        
        #WWWW:@      ::   ::  *WWWW        
        W@WW*W  .::,.::::,:+  @@WW#,       
        WWWW## ,,.: .:::.: .  .WWW:,       
        @WWW@:   W..::::: #.  :WWWW        
         WWWW::  *..:.  ::.,. :WWWW        
         WWWW:: :.:.:   :  :: ,@WW@        
         WWWW:  .:,  :  ,,     :WW,        
         .: #         :  ,     : *         
          W +    .,  :::  .,   : @         
          W ::                .: W         
       @,,,W:.  ,, ::*@*:,  . :@W.,,@      
     +.....*: : : .#WWWWW:  : .#:....+,    
    @...:::*:,, : :WWWWWWW, ,  *::::..,#   
  :...::::::W:,   @W::::*W.   :W:::::...#  
 @@@@@@@@@@@W@@@@@W@@@@@@W@@@@@W@@@@@@@@@@:
Community
  • 1
  • 1
Ankita Bansal
  • 335
  • 1
  • 5
  • 11

2 Answers2

2

Convert image to ASCII art

  • Size. Let's assume that one character is on average twice as high as its wide, and in order to maintain the same proportions, we have to scale down the original image. Therefore, it makes sense to use monospaced fonts.

  • Color. We can convert the brightness of a pixel to a character depending on the density of the character. Therefore, it is more accurate to convert grayscale or black and white images with high contrast.

Original picture:

Coding Horror

Scaled ASCII picture:

scH=16, scW=8
scH=8, scW=4
scH=2, scW=1
scH=16, scW=8 scH=8, scW=4 scH=2, scW=1
class ImageToASCIIArt {
  public static void main(String[] args) throws IOException {
    char[][] chars = readImage("/tmp/image.jpg", 16, 8);
    writeToFile("/tmp/image.txt", chars);
  }

  static char[][] readImage(String path, int scH, int scW) throws IOException {
    BufferedImage image = ImageIO.read(new File(path));
    int height = image.getHeight() / scH;
    int width = image.getWidth() / scW;
    char[][] chars = new char[height][width];
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
        // scaling image and accumulating colors
        int colorRGB = 0;
        for (int k = 0; k < scH; k++)
          for (int p = 0; p < scW; p++)
            colorRGB += image.getRGB(j * scW + p, i * scH + k);
        // get the average color
        Color color = new Color(colorRGB / (scH * scW));
        // read the R, G, B values of the color and get the average brightness
        int brightness = (color.getRed()+color.getGreen()+color.getBlue()) / 3;
        // get a character depending on the brightness value
        chars[i][j] = getDensity(brightness);
      }
    }
    return chars;
  }

  static final String DENSITY =
      "@QB#NgWM8RDHdOKq9$6khEPXwmeZaoS2yjufF]}{tx1zv7lciL/\\|?*>r^;:_\"~,'.-`";

  static char getDensity(int value) {
    // Since we don't have 255 characters, we have to use percentages
    int charValue = (int) Math.round(DENSITY.length() / 255.0 * value);
    charValue = Math.max(charValue, 0);
    charValue = Math.min(charValue, DENSITY.length() - 1);
    return DENSITY.charAt(charValue);
  }

  static void writeToFile(String path, char[][] chars) throws IOException {
    FileWriter writer = new FileWriter(path);
    for (char[] row : chars) {
      String str = String.valueOf(row);
      writer.append(str).write("\n");
      System.out.println(str);
    }
    writer.flush();
    writer.close();
  }
}

See also: Restore an image from an ASCII artDraw an ASCII art from an image

1

This can be done easily in Java,

int width = 100;
int height = 30;

//BufferedImage image = ImageIO.read(new File("/logo.jpg"));
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setFont(new Font("SansSerif", Font.BOLD, 24));

Graphics2D graphics = (Graphics2D) g;
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics.drawString("JAVA", 10, 20);

//save this image
//ImageIO.write(image, "png", new File("/ascii-art.png"));

for (int y = 0; y < height; y++) {
    StringBuilder sb = new StringBuilder();
    for (int x = 0; x < width; x++) {
        sb.append(image.getRGB(x, y) == -16777216 ? " " : "$");
    }
    if (sb.toString().trim().isEmpty()) {
        continue;
    }
    System.out.println(sb);
}

Original source:

Generate an ASCII picture from a string

Prokash Sarkar
  • 11,723
  • 1
  • 37
  • 50