画像圧縮ソフト改良版

画像の圧縮度合いを選べるようになりました!

 

 

真ん中が、元々の画像、

v1が色数256色の画像、

v2が色数65500色の画像です。

 

 

⇦V1は、256色

この色だけで、犬の写真を表現しています。

 

 

 

 

操作方法は、、、
Processingを起動し、実行。
出てきた画面に好きな画像をドラッグ&ドロップします。
そして、圧縮度合いのボタンを選んでクリックし、実行をクリック。
作られたファイルを再度ドラッグ&ドロップすると、圧縮後の画像が表示されます。
保存ボタンをクリックすれば、圧縮画像の完成です。

(このページの最後に動画が貼ってあります。)

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

ASYUKU

PFont font;
int mode = 0;
PImage ins;
int v;
int d = 2;
boolean x2;
PImage bg;
PImage bgh;
PImage hed;
boolean l = false;
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() {
  noStroke();
  ins = loadImage("data/ins.png");
  bg = loadImage("data/bg.png");
  bgh = loadImage("data/bgh.png");
  hed = loadImage("data/hed.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, 400-(textWidth(noload)/2), 230);
      Text(noload2, 400-(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(bgh, 0, 0);
    println("ドロップされました "+pass); 
    en = 0;
    println();
    if (pass.substring(pass.length()-3, pass.length()).equals("kig")) {
      println("自作のやつです"); 
      en = 1;
    }
    if (pass.substring(pass.length()-4, pass.length()).equals("kig2")) {
      println("v2の自作のやつです"); 
      en = 2;
    }
    if (en == 0) {
      img = loadImage(pass);
    }
    if (en == 1) {
      img = ucon(loadBytes(pass));
    }
    if (en == 2) {
      img = ucon2(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(24);
      Text(str, (640+80)-(textWidth(str)/2), 30);
      textSize(12);
      int fs = 0;
      if(v == 0)fs = filesize(img);
      if(v == 1)fs = filesize2(img);
      str = "予測サイズ"+nf(((float)fs/1024), 0, 2)+"KB ";
      if (en == 0)Text(str, (640+80)-(textWidth(str)/2), 50);
      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);
      l = true;
    } else {
      println("このファイルは壊れています");
    }
    passa = pass;
    pass = null;
  }
  if (mouseX >= 640) {
    if (mouseY >= 480-90) {
      if (mousePressed && !cc) {
        one = true;
        cc = true;
      } else {
        cc = false;
      }
    }
  }
  if (one) {
    textSize(24);
    String str = "OK";
    Text(str, (640+80)-(textWidth(str)/2), 460-64);
    if (en == 0) {
      if(x2)img = _2x(img);
      byte[] out = con(img);
      if(v == 1)out = con2(img);
      String a = ".kig";
      //if(v == 1)a = ".kig2";
      saveBytes(passa+a, out);
      println(passa+a+" に保存されました");
      if(x2)img = _n2x(img);
    }
    if (en >= 1) {
      img.save(passa+".png");
      println(passa+".png"+" に保存されました");
    }
    one = false;
  }
  if(l){
    image(hed,640,0);
    textSize(13);
    Text("バージョン(ベータ)",648,125);
    textSize(14);
    boolean p = false;
    if(bot("V1",644,130,v == 0)){
      v = 0;
      p = true;
    }
    if(bot("V2",644+50,130,v == 1)){
      v = 1;
      p = true;
    }
    Text("ディザリング レベル",648,125+60);
    if(bot(" 無し",644,130+60,d == 0)){
      d = 0;
      p = true;
    }
    if(bot("控えめ",644+50,130+60,d == 1)){
      d = 1;
      p = true;
    }
    if(bot("普通",644+100,130+60,d == 2)){
      d = 2;
      p = true;
    }
    Text("2x",648,125+120);
    if(bot("ON",644,130+120,x2)){
      x2 = true;
      p = true;
    }
    if(bot("OFF",644+50,130+120,!x2)){
      x2 = false;
      p = true;
    }
    //if(bot("V3",644+50,130,v == 2)){
      //v = 2;
      //p = true;
    //}
    if(p)pass = passa;
  }
}

conv1(バージョン1に圧縮256色にするプログラム)

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

  return bh;
}
byte[] con(PImage img) {
  int bh = 0;
  bh = (img.width*img.height)+4;
  byte[] bytes = new byte[bh];
  char xs = char(img.width);
  char ys = char(img.height);
  println("変換やりまーす");
  println("画像サイズ:"+xs+"x"+ys);
  //上位 8bit を送出
  byte up = byte(xs >> 8);
  bytes[0] = up;
  byte down = byte(xs & 255);
  bytes[1] = down;
  ;
  up = byte(ys >> 8);
  bytes[2] = up;
  down = byte(ys & 255);
  bytes[3] = down;
  ;
  int f = 0;
  boolean ffA = false;
  for (int y = 0; y < ys; y++) {
    ffA = !ffA;
    boolean ffa = ffA;
    boolean ffaa = false;
    for (int x = 0; x < xs; x++) {
      int F = 8;
      if (ffa)F = -8;
      if(d == 0)F = 0;
      if(d == 1)F /= 2;
      int R = int(( red(img.get(x, y))  +F)/34.1333333 );
      int G = int(( green(img.get(x, y))+F)/34.1333333 );
      F *= 2;
      int B = int(( blue(img.get(x, y) )+F)/73.1428571 );
      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 = byte(unbinary(rgb));
      byte in = 0;
      in = byte(in | (R<<5));
      in = byte(in | (G<<2));
      in = byte(in | (B<<0));
      bytes[4+f] = in;
      //println(r,g,b);
      //
      f++;
      ffa = !ffa;
    }
  }
  return bytes;
}
;
PImage ucon(byte[] img) {
  boolean unload = false;
  PImage out = null;
  PGraphics pg = null;
  if (img != null) {
    int mask = 0b10000000;
    int umask = 0b01111111;
    if((img[0]&mask) != 0){
      println("新型"); 
      unload = true;
    }
    img[0] = byte(img[0] & umask);
    if (!unload) {
      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++) {
        int in = int(img[i+4]+128);
        //String k = binary(int(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.5714285;
        //float g = unbinary(G)*36.5714285;
        //float b = unbinary(B)*85.3333333;
        //
        int R = 0b11100000;
        int G = 0b00011100;
        int B = 0b00000011;
        float r = (in&R)>>5;
        float g = (in&G)>>2;
        float b = (in&B);
        r *= 34.1333333;
        g *= 34.1333333;
        b *= 73.1428571;
        //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");
    }
  }
  if(pg != null)out = pg.get();
  if(unload)out = ucon2(img);
  return out;
}

conv2(バージョン2、65500色にするプログラム)

int filesize2(PImage img) {
  int bh = (img.width*img.height*2)+4;
  
  return bh;
}
byte[] con2(PImage img) {
  int bh = 0;
  bh = (img.width*img.height*2)+4;
  byte[] bytes = new byte[bh];
  char xs = char(img.width);
  char ys = char(img.height);
  println("変換やりまーす");
  println("画像サイズ:"+xs+"x"+ys);
  //上位 8bit を送出
  byte up = byte(xs >> 8);
  int mask = 0b10000000;
  bytes[0] = byte(up|mask);
  byte down = byte(xs & 255);
  bytes[1] = down;
  ;
  up = byte(ys >> 8);
  bytes[2] = up;
  down = byte(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 = 2;
      if (ffa)F = -2;
      if(d == 0)F = 0;
      if(d == 1)F /= 2;
      int R = int(( red(img.get(x, y))  +F)/8.12698413 );
      int B = int(( blue(img.get(x, y) )+F)/8.12698413 );
      F /= 2;
      int G = int(( green(img.get(x, y))+F)/4.03149606 );
      if (R > 31)R = 31;
      if (G > 63)G = 63;
      if (B > 31)B = 31;
      if (R < 0)R = 0;
      if (G < 0)G = 0;
      if (B < 0)B = 0;
      String r = binary(R, 5);
      String g = binary(G, 6);
      String b = binary(B, 5);
      String rgb = r+g+b;
      //println(rgb);
      //byte in = byte(unbinary(rgb));
      //rrrrrggggggbbbbb
      //
      char rgba = 0;
      rgba = char(rgba | (R<<11));
      rgba = char(rgba | (G<<5));
      rgba = char(rgba | (B<<0));
      ;
      //rgba = char(rgba^mask);
      ;
      byte upa = byte(rgba >> 8);
      byte downa = byte(rgba & 255);
      ;
      bytes[4+(f*2)+0] = upa;
      bytes[4+(f*2)+1] = downa;
      //println(r,g,b);
      f++;
      ffa = !ffa;
    }
  }
  return bytes;
}
;
PImage ucon2(byte[] img) {
  PImage out = null;
  PGraphics pg = null;
  if (img != null) {
    int mask = 0b10000000;
    int umask = 0b01111111;
    img[0] = byte(img[0] & umask);
    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++) {
      int in = int(img[(i*2)+4]+128);
      int ina = int(img[(i*2)+5]+128);
      in = ina+(in*256);
      //String k = binary(int(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.5714285;
      //float g = unbinary(G)*36.5714285;
      //float b = unbinary(B)*85.3333333;
      //
      int R = 0b1111100000000000;
      int G = 0b0000011111100000;
      int B = 0b0000000000011111;
      float r = (in&R)>>11;
      float g = (in&G)>>5;
      float b = (in&B);
      r *= 8.12698413;
      g *= 4.03149606;
      b *= 8.12698413;
      //r = 255-r;
      //g = 255-g;
      //b = 255-b;
      //println(r, g, b);
      pg.pixels[i] = color(r, g, b);
    }
    pg.updatePixels();
    pg.endDraw();
  }
  out = pg.get();
  return out;
}

dd(ドラッグ&ドロップのためのプログラム)

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

String pass = null;

DropTarget dropTarget;  
Component component;

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();
      }
    }
  }
  );
}

gui(グラフィカルuserインターフェースの略。ボタンのプログラム)

PImage _2x(PImage in) {
  PGraphics pg = createGraphics(in.width*2, in.height*2);
  pg.noSmooth();
  pg.beginDraw();
  pg.noSmooth();
  pg.scale(2);
  pg.image(in, 0, 0);
  pg.endDraw();
  return pg.get();
}
PImage _n2x(PImage in) {
  PGraphics pg = createGraphics(in.width/2, in.height/2);
  pg.noSmooth();
  pg.beginDraw();
  pg.noSmooth();
  pg.scale(0.5);
  pg.image(in, 0, 0);
  pg.endDraw();
  return pg.get();
}
boolean bot(String t, float x, float y, boolean f) {
  int w = 50;
  int h = 40-8;
  //w = int(textWidth(t)+16)-8;
  x += 2;
  y += 2;
  ;
  w -= 2;
  h -= 2;
  x += 2;
  y += 2;
  boolean a = false;
  if (x <= mouseX && x+w >= mouseX) {
    if (y <= mouseY && y+h >= mouseY) {
      a = true;
    }
  }
  w += 2;
  h += 2;
  x -= 2;
  y -= 2;
  int ofx = 0;
  int ofy = -4;
  ;
  w -= 2;
  h -= 2;
  x += 3;
  y += 4;
  ;
  fill(255, 64);
  rect(x, y, w, h);
  if (f)rect(x, y, w, h);
  fill(255);
  text(t, x+(w/2)-(textWidth(t)/2)+ofx, h+2+y-7+ofy);
  if (!mousePressed)a = false;
  return a;
}

データの予測容量を計算して表示できるようにしました!!!

 

 

 

 

zipダウンロードは、こちら

操作動画は、こちら↓

 

 

 

Follow me!

コメントを残す