手作り画像圧縮ソフト

Processingで作った手作り画像圧縮ソフトです。

PNG、ZIF、JPEG、BMP形式の画像を圧縮することができます。

拡大すると、ドット絵に見えます。
拡大せずに見ると、何も変わっていないように見えますが、中間色で見えるため、目の錯覚で変わっていないように見えるのです。

256色しか使わない画像に変換します。BMPならば、3分の1のサイズになります。

Windows32ビット用、64ビット用、Mac用を作りました。

ダウンロードはこちら

実行後の拡大写真は、こちら↓

これが、拡大前の写真です。⇩

使用画像は、こちら↓

 

 

 

 

ソースコードは、こちら↓

Mac↓

PFont font;
int mode = 0;
PImage ins;
PImage bg;
void Text(String t, float x, float y) {
  fill(0, 3);
  for (float i = -4; i < 5; i += 1) {
    for (float f = -4; f < 5; f += 1) {
      text(t, x+i, y+f);
    }
  }
  fill(255);
  text(t, x, y);
}
String passa;
boolean one;
void setup() {
  ins = loadImage("data/ins.png");
  bg = loadImage("data/bg.png");
  size(800, 480); 
  dragDropFile();
  surface.setTitle("圧縮");
}
int en = 0;
boolean cc;
PImage img;
void draw() {
  if (mode == 1) {
    background(100);
    if (bg != null)image(bg, 0, 0);
    font = createFont("MS PGothic", 32);
    if (font == null) {
      font = createFont("Osaka", 32); 
      println("Osaka");
    }
    if (font != null) {
      textFont (font); 
      textSize(32);
      println("フォントロード成功");
      String noload = "画像がまだロードされていません";
      String noload2 = "このウィンドウにドラック&ドロップしてください。";
      Text(noload, 320-(textWidth(noload)/2), 230);
      Text(noload2, 320-(textWidth(noload2)/2), 270);
    }
    mode = 2;
  }
  if (mode == 0) {
    if (ins != null)image(ins, 0, 0);
    mode = 1;
  }
  ;
  ;
  if (pass != null) {
    background(100);
    if (bg != null)image(bg, 0, 0);
    println("ドロップされました "+pass); 
    en = 0;
    println();
    if (pass.substring(pass.length()-3, pass.length()).equals("kig")) {
      println("自作のやつです"); 
      en = 1;
    }
    if (en == 0) {
      img = loadImage(pass);
    } else {
      img = ucon(loadBytes(pass));
    }
    if (img != null) {
      float xs = img.width;
      float ys = img.height;
      int xss = int(xs);
      int yss = int(ys);
      float w = 1;
      if (xs > ys) {
        w = 640/xs;
      } else {
        w = 480/ys;
      }
      xs *= w;
      ys *= w;
      String str = xss+" x "+yss;
      textSize(32);
      Text(str, (640+80)-(textWidth(str)/2), 30);
      textSize(16);
      str = "予測サイズ"+nf(((float)filesize(img)/1024/1024), 2, 2)+"MB";
      if (en == 0)Text(str, (640+80)-(textWidth(str)/2), 60);
      println("ロードできました!"); 
      println("拡大率は"+nf(w, 2, 2)+"%でした"); 
      image(img, 320-(xs/2), 240-(ys/2), xs, ys);
      textSize(64);
      str = "実行";
      if (en == 1)str = "保存";
      Text(str, (640+80)-(textWidth(str)/2), 460);
    } else {
      println("このファイルは壊れています");
    }
    passa = pass;
    pass = null;
  }
  if (mouseX >= 640) {
    if (mouseY >= 480-80) {
      if (mousePressed && !cc) {
        one = true;
        cc = true;
      } else {
        cc = false;
      }
    }
  }
  if (one) {
    String str = "OK";
    Text(str, (640+80)-(textWidth(str)/2), 460-64);
    if (en == 0) {
      saveBytes(passa+".kig", con(img));
      println(passa+".kig"+" に保存されました");
    }
    if (en == 1) {
      img.save(passa+".png");
      println(passa+".png"+" に保存されました");
    }
    one = false;
  }
}

Windows64bit

import processing.core.*; 
import processing.data.*; 
import processing.event.*; 
import processing.opengl.*; 

import java.awt.datatransfer.*; 
import java.awt.dnd.*; 
import java.io.File; 
import java.io.IOException; 
import java.awt.Component; 
import java.util.List; 

import java.util.HashMap; 
import java.util.ArrayList; 
import java.io.File; 
import java.io.BufferedReader; 
import java.io.PrintWriter; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.IOException; 

public class ASYUKU extends PApplet {

PFont font;
int mode = 0;
PImage ins;
PImage bg;
public void Text(String t, float x, float y) {
  fill(0, 3);
  for (float i = -4; i < 5; i += 1) {
    for (float f = -4; f < 5; f += 1) {
      text(t, x+i, y+f);
    }
  }
  fill(255);
  text(t, x, y);
}
String passa;
boolean one;
public void setup() {
  ins = loadImage("data/ins.png");
  bg = loadImage("data/bg.png");
   
  dragDropFile();
  surface.setTitle("圧縮");
}
int en = 0;
boolean cc;
PImage img;
public void draw() {
  if (mode == 1) {
    background(100);
    if (bg != null)image(bg, 0, 0);
    font = createFont("MS PGothic", 32);
    if (font == null) {
      font = createFont("Osaka", 32); 
      println("Osaka");
    }
    if (font != null) {
      textFont (font); 
      textSize(32);
      println("フォントロード成功");
      String noload = "画像がまだロードされていません";
      String noload2 = "このウィンドウにドラック&ドロップしてください。";
      Text(noload, 320-(textWidth(noload)/2), 230);
      Text(noload2, 320-(textWidth(noload2)/2), 270);
    }
    mode = 2;
  }
  if (mode == 0) {
    if (ins != null)image(ins, 0, 0);
    mode = 1;
  }
  ;
  ;
  if (pass != null) {
    background(100);
    if (bg != null)image(bg, 0, 0);
    println("ドロップされました "+pass); 
    en = 0;
    println();
    if (pass.substring(pass.length()-3, pass.length()).equals("kig")) {
      println("自作のやつです"); 
      en = 1;
    }
    if (en == 0) {
      img = loadImage(pass);
    } else {
      img = ucon(loadBytes(pass));
    }
    if (img != null) {
      float xs = img.width;
      float ys = img.height;
      int xss = PApplet.parseInt(xs);
      int yss = PApplet.parseInt(ys);
      float w = 1;
      if (xs > ys) {
        w = 640/xs;
      } else {
        w = 480/ys;
      }
      xs *= w;
      ys *= w;
      String str = xss+" x "+yss;
      textSize(32);
      Text(str, (640+80)-(textWidth(str)/2), 30);
      textSize(16);
      str = "予測サイズ"+nf(((float)filesize(img)/1024/1024), 2, 2)+"MB";
      if (en == 0)Text(str, (640+80)-(textWidth(str)/2), 60);
      println("ロードできました!"); 
      println("拡大率は"+nf(w, 2, 2)+"%でした"); 
      image(img, 320-(xs/2), 240-(ys/2), xs, ys);
      textSize(64);
      str = "実行";
      if (en == 1)str = "保存";
      Text(str, (640+80)-(textWidth(str)/2), 460);
    } else {
      println("このファイルは壊れています");
    }
    passa = pass;
    pass = null;
  }
  if (mouseX >= 640) {
    if (mouseY >= 480-80) {
      if (mousePressed && !cc) {
        one = true;
        cc = true;
      } else {
        cc = false;
      }
    }
  }
  if (one) {
    String str = "OK";
    Text(str, (640+80)-(textWidth(str)/2), 460-64);
    if (en == 0) {
      saveBytes(passa+".kig", con(img));
      println(passa+".kig"+" に保存されました");
    }
    if (en == 1) {
      img.save(passa+".png");
      println(passa+".png"+" に保存されました");
    }
    one = false;
  }
}

public int filesize(PImage img) {
  int bh = (img.width*img.height)+4;

  return bh;
}
public byte[] con(PImage img) {
  int bh = 0;
  bh = (img.width*img.height)+4;
  byte[] bytes = new byte[bh];
  char xs = PApplet.parseChar(img.width);
  char ys = PApplet.parseChar(img.height);
  println("変換やりまーす");
  println("画像サイズ:"+xs+"x"+ys);
  //上位 8bit を送出
  byte up = PApplet.parseByte(xs >> 8);
  bytes[0] = up;
  byte down = PApplet.parseByte(xs & 255);
  bytes[1] = down;
  ;
  up = PApplet.parseByte(ys >> 8);
  bytes[2] = up;
  down = PApplet.parseByte(ys & 255);
  bytes[3] = down;
  ;
  int f = 0;
  boolean ffA = false;
  for (int y = 0; y < ys; y++) {
    ffA = !ffA;
    boolean ffa = ffA;
    for (int x = 0; x < xs; x++) {
      int F = -8;
      if(ffa)F = 8;
      int R = PApplet.parseInt(( red(img.get(x, y))  +F)/32 );
      int G = PApplet.parseInt(( green(img.get(x, y))+F)/32 );
      int B = PApplet.parseInt(( blue(img.get(x, y) )+F)/64 );
      if(R > 7)R = 7;
      if(G > 7)G = 7;
      if(B > 3)B = 3;
      if(R < 0)R = 0;
      if(G < 0)G = 0;
      if(B < 0)B = 0;
      String r = binary(R , 3);
      String g = binary(G , 3);
      String b = binary(B , 2);
      String rgb = r+g+b;
      byte in = PApplet.parseByte(unbinary(rgb));
      bytes[4+f] = in;
      //println(r,g,b);
      f++;
      ffa = !ffa;
    }
  }
  return bytes;
}
;
public PImage ucon(byte[] img) {
  PImage out = null;
  PGraphics pg = null;
  if (img != null) {
    int mask = 0b10000000;
    for (int i = 0; i < img.length; i++) {
      img[i] ^= mask;
    }
    int xs = ((img[0]+128)*256)+(img[1]+128);
    int ys = ((img[2]+128)*256)+(img[3]+128);
    println(xs, ys);
    pg = createGraphics(xs, ys);
    pg.beginDraw(); 
    pg.loadPixels();
    for (int i = 0; i < pg.pixels.length; i++) {
      String k = binary(PApplet.parseInt(img[i+4]+128), 8);
      String R = k.substring(0, 3);
      String G = k.substring(3, 6);
      String B = k.substring(6, 8);
      float r = unbinary(R)*36.5714285f;
      float g = unbinary(G)*36.5714285f;
      float b = unbinary(B)*85.3333333f;
      //r = 255-r;
      //g = 255-g;
      //b = 255-b;
      //println(r, g, b);
      pg.pixels[i] = color(r, g, b, 256);
    }
    pg.updatePixels();
    pg.endDraw(); 
    //pg.save(pass+".png");
  }
  out = pg.get();
  return out;
}
  
  
  
  



String pass = null;

DropTarget dropTarget;  
Component component;

public void dragDropFile() {
  component = (Component)this.surface.getNative();

  dropTarget = new DropTarget(component, new DropTargetListener() {  
    public void dragEnter(DropTargetDragEvent dtde) {
    }  
    public void dragOver(DropTargetDragEvent dtde) {
    }  
    public void dropActionChanged(DropTargetDragEvent dtde) {
    }  
    public void dragExit(DropTargetEvent dte) {
    }  
    public void drop(DropTargetDropEvent dtde) {  
      dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);  
      Transferable trans = dtde.getTransferable();  
      List<File> fileNameList = null;  
      if (trans.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {  
        try {  
          fileNameList = (List<File>)  
            trans.getTransferData(DataFlavor.javaFileListFlavor);
        } 
        catch (UnsupportedFlavorException ex) {  
          println(ex);
        } 
        catch (IOException ex) {  
          println(ex);
        }
      }  
      if (fileNameList == null) return;  

      for (File f : fileNameList) {
        println(f.getAbsolutePath());
        pass = f.getAbsolutePath();
      }
    }
  }
  );
}
  public void settings() {  size(800, 480); }
  static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "ASYUKU" };
    if (passedArgs != null) {
      PApplet.main(concat(appletArgs, passedArgs));
    } else {
      PApplet.main(appletArgs);
    }
  }
}

 

Windows32bit↓

import processing.core.*; 
import processing.data.*; 
import processing.event.*; 
import processing.opengl.*; 

import java.awt.datatransfer.*; 
import java.awt.dnd.*; 
import java.io.File; 
import java.io.IOException; 
import java.awt.Component; 
import java.util.List; 

import java.util.HashMap; 
import java.util.ArrayList; 
import java.io.File; 
import java.io.BufferedReader; 
import java.io.PrintWriter; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.IOException; 

public class ASYUKU extends PApplet {

PFont font;
int mode = 0;
PImage ins;
PImage bg;
public void Text(String t, float x, float y) {
  fill(0, 3);
  for (float i = -4; i < 5; i += 1) {
    for (float f = -4; f < 5; f += 1) {
      text(t, x+i, y+f);
    }
  }
  fill(255);
  text(t, x, y);
}
String passa;
boolean one;
public void setup() {
  ins = loadImage("data/ins.png");
  bg = loadImage("data/bg.png");
   
  dragDropFile();
  surface.setTitle("圧縮");
}
int en = 0;
boolean cc;
PImage img;
public void draw() {
  if (mode == 1) {
    background(100);
    if (bg != null)image(bg, 0, 0);
    font = createFont("MS PGothic", 32);
    if (font == null) {
      font = createFont("Osaka", 32); 
      println("Osaka");
    }
    if (font != null) {
      textFont (font); 
      textSize(32);
      println("フォントロード成功");
      String noload = "画像がまだロードされていません";
      String noload2 = "このウィンドウにドラック&ドロップしてください。";
      Text(noload, 320-(textWidth(noload)/2), 230);
      Text(noload2, 320-(textWidth(noload2)/2), 270);
    }
    mode = 2;
  }
  if (mode == 0) {
    if (ins != null)image(ins, 0, 0);
    mode = 1;
  }
  ;
  ;
  if (pass != null) {
    background(100);
    if (bg != null)image(bg, 0, 0);
    println("ドロップされました "+pass); 
    en = 0;
    println();
    if (pass.substring(pass.length()-3, pass.length()).equals("kig")) {
      println("自作のやつです"); 
      en = 1;
    }
    if (en == 0) {
      img = loadImage(pass);
    } else {
      img = ucon(loadBytes(pass));
    }
    if (img != null) {
      float xs = img.width;
      float ys = img.height;
      int xss = PApplet.parseInt(xs);
      int yss = PApplet.parseInt(ys);
      float w = 1;
      if (xs > ys) {
        w = 640/xs;
      } else {
        w = 480/ys;
      }
      xs *= w;
      ys *= w;
      String str = xss+" x "+yss;
      textSize(32);
      Text(str, (640+80)-(textWidth(str)/2), 30);
      textSize(16);
      str = "予測サイズ"+nf(((float)filesize(img)/1024/1024), 2, 2)+"MB";
      if (en == 0)Text(str, (640+80)-(textWidth(str)/2), 60);
      println("ロードできました!"); 
      println("拡大率は"+nf(w, 2, 2)+"%でした"); 
      image(img, 320-(xs/2), 240-(ys/2), xs, ys);
      textSize(64);
      str = "実行";
      if (en == 1)str = "保存";
      Text(str, (640+80)-(textWidth(str)/2), 460);
    } else {
      println("このファイルは壊れています");
    }
    passa = pass;
    pass = null;
  }
  if (mouseX >= 640) {
    if (mouseY >= 480-80) {
      if (mousePressed && !cc) {
        one = true;
        cc = true;
      } else {
        cc = false;
      }
    }
  }
  if (one) {
    String str = "OK";
    Text(str, (640+80)-(textWidth(str)/2), 460-64);
    if (en == 0) {
      saveBytes(passa+".kig", con(img));
      println(passa+".kig"+" に保存されました");
    }
    if (en == 1) {
      img.save(passa+".png");
      println(passa+".png"+" に保存されました");
    }
    one = false;
  }
}

public int filesize(PImage img) {
  int bh = (img.width*img.height)+4;

  return bh;
}
public byte[] con(PImage img) {
  int bh = 0;
  bh = (img.width*img.height)+4;
  byte[] bytes = new byte[bh];
  char xs = PApplet.parseChar(img.width);
  char ys = PApplet.parseChar(img.height);
  println("変換やりまーす");
  println("画像サイズ:"+xs+"x"+ys);
  //上位 8bit を送出
  byte up = PApplet.parseByte(xs >> 8);
  bytes[0] = up;
  byte down = PApplet.parseByte(xs & 255);
  bytes[1] = down;
  ;
  up = PApplet.parseByte(ys >> 8);
  bytes[2] = up;
  down = PApplet.parseByte(ys & 255);
  bytes[3] = down;
  ;
  int f = 0;
  boolean ffA = false;
  for (int y = 0; y < ys; y++) {
    ffA = !ffA;
    boolean ffa = ffA;
    for (int x = 0; x < xs; x++) {
      int F = -8;
      if(ffa)F = 8;
      int R = PApplet.parseInt(( red(img.get(x, y))  +F)/32 );
      int G = PApplet.parseInt(( green(img.get(x, y))+F)/32 );
      int B = PApplet.parseInt(( blue(img.get(x, y) )+F)/64 );
      if(R > 7)R = 7;
      if(G > 7)G = 7;
      if(B > 3)B = 3;
      if(R < 0)R = 0;
      if(G < 0)G = 0;
      if(B < 0)B = 0;
      String r = binary(R , 3);
      String g = binary(G , 3);
      String b = binary(B , 2);
      String rgb = r+g+b;
      byte in = PApplet.parseByte(unbinary(rgb));
      bytes[4+f] = in;
      //println(r,g,b);
      f++;
      ffa = !ffa;
    }
  }
  return bytes;
}
;
public PImage ucon(byte[] img) {
  PImage out = null;
  PGraphics pg = null;
  if (img != null) {
    int mask = 0b10000000;
    for (int i = 0; i < img.length; i++) {
      img[i] ^= mask;
    }
    int xs = ((img[0]+128)*256)+(img[1]+128);
    int ys = ((img[2]+128)*256)+(img[3]+128);
    println(xs, ys);
    pg = createGraphics(xs, ys);
    pg.beginDraw(); 
    pg.loadPixels();
    for (int i = 0; i < pg.pixels.length; i++) {
      String k = binary(PApplet.parseInt(img[i+4]+128), 8);
      String R = k.substring(0, 3);
      String G = k.substring(3, 6);
      String B = k.substring(6, 8);
      float r = unbinary(R)*36.5714285f;
      float g = unbinary(G)*36.5714285f;
      float b = unbinary(B)*85.3333333f;
      //r = 255-r;
      //g = 255-g;
      //b = 255-b;
      //println(r, g, b);
      pg.pixels[i] = color(r, g, b, 256);
    }
    pg.updatePixels();
    pg.endDraw(); 
    //pg.save(pass+".png");
  }
  out = pg.get();
  return out;
}
  
  
  
  



String pass = null;

DropTarget dropTarget;  
Component component;

public void dragDropFile() {
  component = (Component)this.surface.getNative();

  dropTarget = new DropTarget(component, new DropTargetListener() {  
    public void dragEnter(DropTargetDragEvent dtde) {
    }  
    public void dragOver(DropTargetDragEvent dtde) {
    }  
    public void dropActionChanged(DropTargetDragEvent dtde) {
    }  
    public void dragExit(DropTargetEvent dte) {
    }  
    public void drop(DropTargetDropEvent dtde) {  
      dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);  
      Transferable trans = dtde.getTransferable();  
      List<File> fileNameList = null;  
      if (trans.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {  
        try {  
          fileNameList = (List<File>)  
            trans.getTransferData(DataFlavor.javaFileListFlavor);
        } 
        catch (UnsupportedFlavorException ex) {  
          println(ex);
        } 
        catch (IOException ex) {  
          println(ex);
        }
      }  
      if (fileNameList == null) return;  

      for (File f : fileNameList) {
        println(f.getAbsolutePath());
        pass = f.getAbsolutePath();
      }
    }
  }
  );
}
  public void settings() {  size(800, 480); }
  static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "ASYUKU" };
    if (passedArgs != null) {
      PApplet.main(concat(appletArgs, passedArgs));
    } else {
      PApplet.main(appletArgs);
    }
  }
}

Follow me!

コメントを残す