Advertisement
Guest User

Untitled

a guest
Jul 12th, 2014
227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 3.72 KB | None | 0 0
  1. import java.util.*;
  2. import java.awt.image.*;
  3. import java.io.*;
  4. import javax.imageio.*;
  5.  
  6. public class ChipFont {
  7.  
  8.     static final String FONT_NAME = "chipfontraw.png";
  9.     static final String OUT_NAME  = "compressed.png";
  10.     static final String CHARSET   = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!' ";
  11.     static final String TEXT      = "YOU'RE A    LOOSE CANNON JONES! TURNIN YOUR GUN AND BADGE!";
  12.     static final int CHAR_HEIGHT  = 5;
  13.  
  14.     public static void main(String[] args) throws Exception {
  15.         // load image and split it apart into pixel lists for each character
  16.         BufferedImage font = ImageIO.read(new File(FONT_NAME));
  17.         List<Chunk> chunks = new ArrayList<Chunk>();
  18.         {
  19.             int offset = 0;
  20.             for(char c : CHARSET.toCharArray()) {
  21.                 Chunk chunk = new Chunk();
  22.                 chunks.add(chunk);
  23.                 for(int y = 0; y < CHAR_HEIGHT; y++) {
  24.                     byte row = 0;
  25.                     for(int x = 0; x < 8; x++) {
  26.                         int pixel = font.getRGB(x, y+offset);
  27.                         row = (byte)((row << 1) | (((pixel & 0xFF000000) != 0) ? 1 : 0));
  28.                     }
  29.                     chunk.data.add(row);
  30.                 }
  31.                 chunk.offsets.put(c, 0);
  32.                 offset += CHAR_HEIGHT;
  33.             }
  34.         }
  35.  
  36.         // compress the bitmap
  37.         // by greedily overlapping pairs of chunks
  38.         // until only one chunk remains.
  39.         while(chunks.size() > 1) {
  40.             Chunk bestA = null;
  41.             Chunk bestB = null;
  42.             Chunk bestC = null;
  43.             int bestSize = Integer.MAX_VALUE;
  44.  
  45.             for(Chunk a : chunks) {
  46.                 for(Chunk b : chunks) {
  47.                     if (a == b) { continue; }
  48.                     Chunk c = a.overlap(b);
  49.                     if (c.size() >= bestSize) { continue; }
  50.                     bestA = a;
  51.                     bestB = b;
  52.                     bestC = c;
  53.                     bestSize = c.size();
  54.                 }
  55.             }
  56.  
  57.             chunks.remove(bestA);
  58.             chunks.remove(bestB);
  59.             chunks.add(bestC);
  60.         }
  61.  
  62.         // print out the compressed bitmap in hex
  63.         System.out.format("final bitmap data: (%d bytes)%n", chunks.get(0).size());
  64.         {
  65.             int z = -1;
  66.             for(byte b : chunks.get(0).data) {
  67.                 System.out.format("0x%02X ", b);
  68.                 if (++z % 16 == 15) { System.out.println(); }
  69.             }
  70.         }
  71.         System.out.println();
  72.  
  73.         // print out the converted text
  74.         System.out.format("final text data: (%d bytes)%n", TEXT.length());
  75.         {
  76.             int z = -1;
  77.             for(char c : TEXT.toCharArray()) {
  78.                 System.out.format("0x%02X ", chunks.get(0).offsets.get(c));
  79.                 if (++z % 16 == 15) { System.out.println(); }
  80.             }
  81.         }
  82.         System.out.println();
  83.  
  84.         // write out our final font as a bitmap for visual inspection
  85.         BufferedImage out = new BufferedImage(8, chunks.get(0).size(), BufferedImage.TYPE_BYTE_BINARY);
  86.         {
  87.             int y = 0;
  88.             for(byte b : chunks.get(0).data) {
  89.                 for(int x = 0; x < 8; x++) {
  90.                     out.setRGB(x, y,
  91.                         ((b >> (7-x))&1) != 0 ? 0xFF000000 : 0xFFFFFFFF
  92.                     );
  93.                 }
  94.                 y++;
  95.             }
  96.         }
  97.         ImageIO.write(out, "PNG", new File(OUT_NAME));
  98.  
  99.         System.exit(0);
  100.     }
  101.  
  102. }
  103.  
  104. class Chunk {
  105.     List<Byte> data = new ArrayList<>();
  106.     Map<Character, Integer> offsets = new HashMap<>();
  107.  
  108.     int size() {
  109.         return data.size();
  110.     }
  111.  
  112.     private Chunk overlap(Chunk next, int index) {
  113.         Chunk ret = new Chunk();
  114.         ret.data.addAll(data);
  115.         ret.offsets.putAll(offsets);
  116.  
  117.         for(int z = index; z < next.data.size(); z++) {
  118.             ret.data.add(next.data.get(z));
  119.         }
  120.         for(Map.Entry<Character, Integer> e : next.offsets.entrySet()) {
  121.             ret.offsets.put(e.getKey(), e.getValue() + data.size() - index);
  122.         }
  123.         return ret;
  124.     }
  125.  
  126.     private boolean canOverlap(Chunk next, int index) {
  127.         if (index > size()) { return false; }
  128.         for(int z = 0; z < index; z++) {
  129.             byte a = data.get(data.size() - index + z);
  130.             byte b = next.data.get(z);
  131.             if (a != b) { return false; }
  132.         }
  133.         return true;
  134.     }
  135.  
  136.     Chunk overlap(Chunk next) {
  137.         for(int index = next.size(); index > 0; index--) {
  138.             if (canOverlap(next, index)) {
  139.                 return overlap(next, index);
  140.             }
  141.         }
  142.         return overlap(next, 0);
  143.     }
  144. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement