Repository: GlitchCodec/GLIC
Branch: master
Commit: 460e61bf9b01
Files: 159
Total size: 94.8 KB
Directory structure:
gitextract_hbgmkhg3/
├── .gitignore
├── GLIC.pde
├── GUI.pde
├── LICENSE
├── README.md
├── code/
│ ├── JWave.jar
│ └── bit-io-1.3.7.jar
├── codec.pde
├── colorspaces.pde
├── encoding.pde
├── planes.pde
├── predictions.pde
├── presets/
│ ├── 0ddangl3
│ ├── 0rg4n1c-___
│ ├── 0rg4n1c-t1ny4ngl3z
│ ├── 0rg4n1c-tr1angl3
│ ├── 0rg4n1c-tr1f0rc3
│ ├── 0rg4n1c-tr33
│ ├── 0rg4n1c-v1n3z
│ ├── 1211
│ ├── 1422
│ ├── 1amblu
│ ├── 1llu510n
│ ├── 1ns1t3
│ ├── 2211
│ ├── 221122
│ ├── 3255
│ ├── 3ra53r
│ ├── 5pl1tz
│ ├── 5um7h1ng
│ ├── 8-b1tz
│ ├── 8l33dm3
│ ├── abstract_expressionism
│ ├── ayy
│ ├── beautifulwave
│ ├── bi0g4n1c
│ ├── bispham1
│ ├── bl33dyl1n3z
│ ├── bl33dyl1n3z-2
│ ├── black+whiteblockyglitch
│ ├── blasted
│ ├── bleeding_blocks
│ ├── blocks
│ ├── blockssmoll
│ ├── blops
│ ├── blops2
│ ├── brokens7r1p3z
│ ├── burn
│ ├── c0m1c
│ ├── cartoon
│ ├── ch3ss
│ ├── channels
│ ├── chock-a-block
│ ├── colour_boxy_glitch
│ ├── colour_glow
│ ├── colour_mess
│ ├── colour_mess2
│ ├── colour_waves
│ ├── colour_waves_2
│ ├── colour_waves_3
│ ├── colour_waves_sharp
│ ├── colour_waves_sharp2
│ ├── colourful_disturbances
│ ├── confetti
│ ├── constrctivist
│ ├── constrctivist2
│ ├── constrctivist_minimal
│ ├── cr0550v3r
│ ├── cubism
│ ├── cute blocks
│ ├── d1ffu510n
│ ├── d1ffu510nz
│ ├── d3cayy-d
│ ├── d3cayy-e
│ ├── default
│ ├── diagonalcolourbleed
│ ├── diagonalcolourbleed2
│ ├── diagonalmess
│ ├── erase_horizontal
│ ├── erase_vertical
│ ├── g0dh34d-d
│ ├── g0dh34d-e
│ ├── ghost
│ ├── gif1
│ ├── gif2
│ ├── haze
│ ├── haze2
│ ├── high_compression
│ ├── idk
│ ├── jpegls1
│ ├── lightblur
│ ├── lightblur2
│ ├── lines
│ ├── liquiblock
│ ├── lmao
│ ├── m1n1m3l0l
│ ├── minimaldiag
│ ├── mthr
│ ├── n07h1ng2c
│ ├── n07h1ng2c-2
│ ├── neato
│ ├── ordered_destruction
│ ├── ordered_destruction_2
│ ├── p1xx1
│ ├── pcool
│ ├── pls
│ ├── preset 38
│ ├── progressive
│ ├── scanlined
│ ├── shinybright
│ ├── sk0011rgb
│ ├── sk001xyz
│ ├── sk0021xyz
│ ├── sk00244xyz
│ ├── sk00244xyz2
│ ├── sk1211
│ ├── sk1723
│ ├── sk221122
│ ├── sk3255
│ ├── squareglitchfromthebottom
│ ├── thousandsofblocks
│ ├── ts01
│ ├── uncubizm
│ ├── vv01
│ ├── vv02
│ ├── vv03
│ ├── vv04
│ ├── vv05
│ ├── vv06
│ ├── vv07
│ ├── vv08
│ ├── vv09
│ ├── vv10
│ ├── vv11
│ ├── vv12
│ ├── vv13
│ ├── vv14
│ ├── vv15
│ ├── vv16
│ ├── vv17
│ ├── vv18
│ ├── vv19
│ ├── vv20
│ ├── vv21
│ ├── vv22
│ ├── vv23
│ ├── vv24
│ ├── vv25
│ ├── wat
│ ├── wavydown
│ ├── wavydownbigger
│ ├── web_p_like
│ ├── webp
│ ├── wot
│ ├── wtf
│ └── wtf2
├── quantization.pde
├── segmentation.pde
└── transformation.pde
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.DS_Store
applet
application.linux32
application.linux64
application.windows32
application.windows64
application.macosx
*.glic
*.bak
*.*~
*.jpg
*.jpeg
*.png
================================================
FILE: GLIC.pde
================================================
// GLIC - GLitch Image Codec, ready for databending
//////////////////// Config
// Hidden stuff (not in GUI)
// Press CTRL-Y to encode image with all presets
// Press CTRL-I to iterate [encoding -> keep image...] `iterate_count` times.
int iterate_count = 5;
// batch stuff
import java.util.ArrayList.*;
import java.io.*;
import java.io.File;
int curFrame=0;
boolean isBatch = false;
String filenames[];
java.io.FilenameFilter extfilter = new java.io.FilenameFilter() {
boolean accept(File dir, String name) {
if (name.toLowerCase().endsWith("png") || name.toLowerCase().endsWith("jpeg")
|| name.toLowerCase().endsWith("jpg") || name.toLowerCase().endsWith("bmp")) return true;
else return false;
}
};
java.io.FilenameFilter glicfilter = new java.io.FilenameFilter() {
boolean accept(File dir, String name) {
if (name.toLowerCase().endsWith("glic")) return true;
else return false;
}
};
String filename;
String fileext;
String foldername = "."+File.separator;
String session_id;
////// size of windows
final static int max_display_size = 750;
//////
PImage img, result, isegm, ipred;
String origname;
PImage current;
int neww, newh, posx=0, posy=0;
PGraphics buffer;
void setup() {
size(750, 750);
smooth(8);
frameRate(20);
// img = loadImage("face.jpg");
//
// buffer=createGraphics(img.width,img.height);
// neww=img.width;
// newh=img.height;
// result = encode(img,"faa.glic");
// current = result;
gui();
println();
println("Press TAB to hide/show GUI");
println("Press CTRL-L to load image");
println("Press CTRL-E to encode image");
println("Press CTRL-D to decode image");
println("Press CTRL-S to save image");
println("Press CTRL-Y to apply all presets");
println();
println("Presets provided by: Myrto, Saturn Kat, Letsglitchit, Vivi, NoNoNoNoNo, Pandy Chan, GenerateMe, Jay Di, José Irion Neto.");
println();
}
void draw() {
background(0);
if (buffer != null && !resetting_buffer) {
image(buffer, posx, posy, neww, newh);
}
}
boolean isCtrlPressed = false;
void keyPressed() {
if (keyCode == TAB) {
if (cp5.isVisible()) {
cp5.hide();
} else {
cp5.show();
}
} else if (keyCode == CONTROL && isCtrlPressed == false)
isCtrlPressed = true;
else if (isCtrlPressed) {
if (char(keyCode) == 'S') {
save_button();
} else if (char(keyCode) == 'L') {
load_button();
} else if (char(keyCode) == 'D') {
decode_button();
} else if (char(keyCode) == 'E') {
encode_button();
} else if (char(keyCode) == 'I') {
println("***** ITERATING ENCODING " + iterate_count + " times!");
println("be patient");
for (int i=0; i<iterate_count; i++) {
println("----------> Iteration number: "+i+"/"+iterate_count);
encode_button();
keep_image();
}
} else if (char(keyCode) == 'Y') {
if (img != null) {
for (int i=0; i<presets_count; i++) {
presets(i);
if(isBatch) {
readValues();
encode_batch(true);
} else {
encode_button();
save_buffer(current_preset);
}
}
}
}
}
}
void keyReleased() {
if (keyCode == CONTROL) isCtrlPressed = false;
}
================================================
FILE: GUI.pde
================================================
import controlP5.*;
import java.text.SimpleDateFormat;
import java.util.Date;
ControlP5 cp5;
CheckBox separate_channels;
CheckBox batch, skip_header, skip_session;
Tab ch1, ch2, ch3;
Controller ch1mn, ch1mx, ch2mn, ch2mx, ch3mn, ch3mx;
Slider co_r, co_g, co_b;
ScrollableList sl_cs, presets_list;
Button lbutton, ebutton, dbutton;
ButtonBar bbar;
Textfield save_filename, glic_filename, preset_name;
String[] bbar_names = new String[] {
"Image", "Segm", "Pred", "Result"
};
HashMap<String, ControllerInterface>[] chmap = new HashMap[3];
boolean separate_channels_toggle = false;
boolean do_skip_session = false;
int presets_count = 0;
String current_preset = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
void gui() {
cp5 = new ControlP5(this);
Tab global = cp5.getTab("default").setLabel("Global config");
ch1 = cp5.addTab("Channel 1").setLabel("All channels");
ch2 = cp5.addTab("Channel 2").setVisible(false);
ch3 = cp5.addTab("Channel 3").setVisible(false);
cp5.addLabel("color_outside_label")
.setText("Color outside")
.setPosition(10, 150)
.moveTo(global);
co_r = cp5.addSlider("R")
.setPosition(10, 160)
.setWidth(170)
.setRange(0, 255)
.setValue(128)
.setScrollSensitivity(0.02)
.moveTo(global);
co_g = cp5.addSlider("G")
.setPosition(10, 170)
.setWidth(170)
.setRange(0, 255)
.setValue(128)
.setScrollSensitivity(0.02)
.moveTo(global);
co_b = cp5.addSlider("B")
.setPosition(10, 180)
.setWidth(170)
.setRange(0, 255)
.setValue(128)
.setScrollSensitivity(0.02)
.moveTo(global);
separate_channels = cp5.addCheckBox("separate_channels")
.setPosition(10, 200)
.addItem("Separate channels", 1)
.deactivate(0)
.moveTo(global);
batch = cp5.addCheckBox("batch")
.setPosition(110, 200)
.addItem("Batch run", 1)
.deactivate(0)
.moveTo(global);
sl_cs = cp5.addScrollableList("Color space")
.setType(ScrollableList.LIST)
.setPosition(10, 20)
.setSize(180, 120)
.moveTo(global);
for (int i=0; i<COLORSPACES; i++) {
sl_cs.addItem(getColorspaceName(i), i);
}
sl_cs.getItem(1).put("state", true);
sl_cs.setValue(1);
lbutton = cp5.addButton("load_button")
.setPosition(10, 220)
.setSize(120, 20)
.setLabel("LOAD IMAGE (ctrl-l)")
.moveTo(global);
cp5.addButton("reload_image")
.setPosition(140, 220)
.setSize(50, 20)
.setLabel("RELOAD")
.moveTo(global);
ebutton = cp5.addButton("encode_button")
.setPosition(10, 250)
.setSize(180, 20)
.setLabel("ENCODE (ctrl-e)")
.moveTo(global);
skip_header = cp5.addCheckBox("skip_header")
.setPosition(10, 280)
.addItem("Use config during decoding (skip header)", 1)
.deactivate(0)
.moveTo(global);
dbutton = cp5.addButton("decode_button")
.setPosition(10, 290)
.setSize(180, 20)
.setLabel("DECODE (ctrl-d)")
.moveTo(global);
cp5.addButton("save_button")
.setPosition(10, 320)
.setSize(180, 20)
.setLabel("SAVE RESULT (ctrl-s)")
.moveTo(global);
save_filename = cp5.addTextfield("Save filename")
.setPosition(10, 350)
.setWidth(180)
.setAutoClear(false)
.moveTo(global);
glic_filename = cp5.addTextfield("GLIC filename")
.setPosition(10, 390)
.setWidth(180)
.setAutoClear(false)
.moveTo(global);
skip_session = cp5.addCheckBox("skip_session")
.setPosition(10, 430)
.addItem("Skip generating session id", 1)
.deactivate(0)
.moveTo(global);
bbar = cp5.addButtonBar("image_switch")
.setPosition(10, 450)
.setWidth(180)
.addItems(bbar_names)
.moveTo(global);
cp5.addButton("keep_image")
.setPosition(10, 470)
.setWidth(180)
.setLabel("KEEP IMAGE")
.moveTo(global);
cp5.addLabel("presets_label")
.setText("Presets")
.setPosition(10, 500)
.moveTo(global);
presets_list = cp5.addScrollableList("presets")
.setType(ScrollableList.LIST)
.setPosition(10, 510)
.setSize(180, 120)
.moveTo(global);
updatePresets();
preset_name = cp5.addTextfield("Preset name")
.setPosition(10, 650)
.setWidth(180)
.setAutoClear(false)
.moveTo(global);
cp5.addButton("save_preset")
.setPosition(10, 690)
.setSize(180, 20)
.setLabel("SAVE PRESET")
.moveTo(global);
chmap[0] = addToTab(ch1);
chmap[1] = addToTab(ch2);
chmap[2] = addToTab(ch3);
ch1mn = cp5.getController(ch1.getName() + "min");
ch1mx = cp5.getController(ch1.getName() + "max");
ch2mn = cp5.getController(ch2.getName() + "min");
ch2mx = cp5.getController(ch2.getName() + "max");
ch3mn = cp5.getController(ch3.getName() + "min");
ch3mx = cp5.getController(ch3.getName() + "max");
}
HashMap<String, ControllerInterface> addToTab(Tab t) {
HashMap<String, ControllerInterface> h = new HashMap<String, ControllerInterface>();
cp5.addLabel(t.getName() + "segmentation_label")
.setText("Segmentation, min/max are powers of 2")
.setPosition(10, 20)
.moveTo(t);
Slider mn_blocksize = cp5.addSlider(t.getName() + "min")
.setLabel("MIN")
.setPosition(10, 30)
.setWidth(160)
.setRange(1, 9)
.setNumberOfTickMarks(9)
.showTickMarks(false)
.setValue(2)
.moveTo(t);
h.put("min", mn_blocksize);
Slider mx_blocksize = cp5.addSlider(t.getName() + "max")
.setLabel("MAX")
.setPosition(10, 40)
.setWidth(160)
.setRange(1, 9)
.setNumberOfTickMarks(9)
.showTickMarks(false)
.setValue(8)
.moveTo(t);
h.put("max", mx_blocksize);
Slider thr_block = cp5.addSlider(t.getName() + "thr")
.setLabel("THR")
.setPosition(10, 50)
.setWidth(160)
.setRange(5, 250)
.setValue(15)
.setScrollSensitivity(0.02)
.moveTo(t);
h.put("thr", thr_block);
ScrollableList pred = cp5.addScrollableList(t.getName() + "pred")
.setLabel("Predictions")
.setType(ScrollableList.LIST)
.setPosition(10, 70)
.setSize(180, 120)
.moveTo(t);
h.put("pred", pred);
for (int i=0; i<MAX_PRED; i++) {
pred.addItem(predict_name(i), i);
}
pred.addItem(predict_name(-1), -1);
pred.addItem(predict_name(-2), -2);
pred.addItem(predict_name(-3), -3);
pred.getItem(7).put("state", true);
pred.setValue(7);
cp5.addLabel(t.getName()+"quantization_label")
.setText("Quantization value")
.setPosition(10, 200)
.moveTo(t);
Slider quant = cp5.addSlider(t.getName() + "quant")
.setLabel("")
.setPosition(10, 210)
.setWidth(180)
.setRange(0, 255)
.setValue(0)
.setScrollSensitivity(0.02)
.moveTo(t);
h.put("quant", quant);
RadioButton clamp = cp5.addRadioButton(t.getName() + "clamp")
.setPosition(10, 230)
.addItem(t.getName() + "CLAMP_NONE", CLAMP_NONE)
.addItem(t.getName() + "CLAMP_MOD256", CLAMP_MOD256)
.activate(0)
.moveTo(t);
clamp.getItem(0).setLabel("CLAMP_NONE");
clamp.getItem(1).setLabel("CLAMP_MOD256");
h.put("clamp", clamp);
ScrollableList trans = cp5.addScrollableList(t.getName() + "trans")
.setLabel("Wavelet")
.setType(ScrollableList.LIST)
.setPosition(10, 260)
.setSize(180, 120)
.moveTo(t);
h.put("trans", trans);
trans.addItem("NONE", 0);
for (int i=1; i<WAVELETNO; i++) {
trans.addItem(getWavelet(i).getName(), i);
}
trans.addItem("RANDOM", -1);
trans.getItem(0).put("state", true);
trans.setValue(0);
cp5.addLabel(t.getName() + "compression_label")
.setText("Compression")
.setPosition(10, 390)
.moveTo(t);
Slider compress = cp5.addSlider(t.getName() + "compress")
.setLabel("")
.setPosition(10, 400)
.setWidth(180)
.setRange(0, 255)
.setValue(0)
.setScrollSensitivity(0.02)
.moveTo(t);
h.put("compress", compress);
cp5.addLabel(t.getName() + "scaler_label")
.setText("Scale transformation (2^x)")
.setPosition(10, 420)
.moveTo(t);
Slider scaler = cp5.addSlider(t.getName() + "scale")
.setLabel("")
.setPosition(10, 430)
.setWidth(180)
.setRange(2, 24)
.setValue(20)
.setScrollSensitivity(0.02)
.moveTo(t);
h.put("scale", scaler);
RadioButton ttype = cp5.addRadioButton(t.getName() + "ttype")
.setPosition(10, 450)
.addItem(t.getName()+"TRANSTYPE_FWT", TRANSTYPE_FWT)
.addItem(t.getName()+"TRANSTYPE_WPT", TRANSTYPE_WPT)
.addItem(t.getName()+"TRANSTYPE_RANDOM", -1)
.activate(0)
.moveTo(t);
ttype.getItem(0).setLabel("TRANSTYPE_FWT");
ttype.getItem(1).setLabel("TRANSTYPE_WPT");
ttype.getItem(2).setLabel("TRANSTYPE_RANDOM");
h.put("transtype", ttype);
ScrollableList encoding = cp5.addScrollableList(t.getName() + "encoding")
.setLabel("Final encoding")
.setType(ScrollableList.LIST)
.setPosition(10, 490)
.setSize(180, 100)
.moveTo(t);
h.put("encoding", encoding);
for (int i=0; i<ENCODINGNO; i++) {
encoding.addItem(encoding_name(i), i);
}
encoding.getItem(1).put("state", true);
encoding.setValue(1);
return h;
}
void image_switch(int v) {
switch(v) {
case 0:
current = img;
break;
case 1:
current = isegm;
break;
case 2:
current = ipred;
break;
case 3:
current = result;
break;
}
reset_buffer();
}
void presets(int i) {
current_preset = (String)presets_list.getItem(i).get("text");
try {
println("Loading preset: " + current_preset);
ObjectInputStream ois = new ObjectInputStream(createInput("presets"+File.separator+current_preset));
HashMap<String, Object> map = (HashMap)ois.readObject();
fromHashMap(map);
ois.close();
}
catch (IOException e) {
println("Failed to load preset: " + current_preset);
current_preset = null;
}
catch (ClassNotFoundException e) {
println("Failed to load preset: " + current_preset);
current_preset = null;
}
}
void save_preset() {
String s = preset_name.getText();
if (s != null && !s.trim().isEmpty()) {
try {
println("Saving preset: " + s);
ObjectOutputStream oos = new ObjectOutputStream(createOutput("presets"+File.separator+s.toLowerCase()));
oos.writeObject(toHashMap());
oos.close();
}
catch (IOException e) {
println("Failed to save preset: " + s);
}
}
updatePresets();
}
void updatePresets() {
String[] filenames;
println("Loading presets");
java.io.File folder = new java.io.File(sketchPath("presets"));
filenames = folder.list();
if (filenames != null) {
presets_list.clear();
for (String s : sort (filenames)) {
presets_list.addItem(s, s);
}
}
presets_count = filenames.length;
}
void readValues() {
ccfg.colorspace = (int)sl_cs.getValue();
ccfg.color_outside = color(co_r.getValue(), co_g.getValue(), co_b.getValue());
for (int p=0; p<3; p++) {
HashMap<String, ControllerInterface> map = separate_channels_toggle ? chmap[p] : chmap[0];
ccfg.min_block_size[p] = 1<<(int)map.get("min").getValue();
ccfg.max_block_size[p] = 1<<(int)map.get("max").getValue();
ccfg.segmentation_precision[p] = map.get("thr").getValue();
ccfg.prediction_method[p] = (Integer)((ScrollableList)map.get("pred")).getItem((int)map.get("pred").getValue()).get("value");
ccfg.quantization_value[p] = (int)map.get("quant").getValue();
ccfg.clamp_method[p] = (int)map.get("clamp").getValue();
ccfg.transform_type[p] = (int)map.get("transtype").getValue();
ccfg.transform_method[p] = (Integer)((ScrollableList)map.get("trans")).getItem((int)map.get("trans").getValue()).get("value");
ccfg.transform_compress[p] = map.get("compress").getValue();
ccfg.transform_scale[p] = (int)pow(2.0, map.get("scale").getValue());
ccfg.encoding_method[p] = (Integer)((ScrollableList)map.get("encoding")).getItem((int)map.get("encoding").getValue()).get("value");
}
}
HashMap<String, Object> toHashMap() {
HashMap<String, Object> m = new HashMap();
m.put("colorspace", sl_cs.getValue());
m.put("color_outside_r", co_r.getValue());
m.put("color_outside_g", co_g.getValue());
m.put("color_outside_b", co_b.getValue());
m.put("separate_channels", separate_channels.getArrayValue());
for (int p=0; p<3; p++) {
HashMap<String, ControllerInterface> map = chmap[p];
String ch = "ch"+p;
for (String k : map.keySet ()) {
if (map.get(k) instanceof RadioButton) {
m.put(ch+k, map.get(k).getArrayValue());
} else {
m.put(ch+k, map.get(k).getValue());
}
}
}
return m;
}
void fromHashMap(HashMap<String, Object> m) {
sl_cs.setValue((Float)m.get("colorspace"));
co_r.setValue((Float)m.get("color_outside_r"));
co_g.setValue((Float)m.get("color_outside_g"));
co_b.setValue((Float)m.get("color_outside_b"));
if (m.get("separate_channels") != null)
separate_channels.setArrayValue((float[])m.get("separate_channels"));
else
separate_channels.deactivate(0);
for (int p=0; p<3; p++) {
HashMap<String, ControllerInterface> map = chmap[p];
String ch = "ch"+p;
for (String k : map.keySet ()) {
if (map.get(k) instanceof RadioButton) {
map.get(k).setArrayValue((float[])m.get(ch+k));
} else {
map.get(k).setValue((Float)m.get(ch+k));
}
}
}
toggle_sep_chan();
}
void reload_image() {
println("Reload image done");
load_image(origname, false);
ipred = isegm = null;
reset_buffer();
}
void keep_image() {
img = current;
}
String session_prefix() {
if (do_skip_session)
return "";
else
return "_" + session_id;
}
void encode_batch(boolean dopresets) {
println("batch: "+foldername);
java.io.File folder = new java.io.File(dataPath(foldername)); // set up a File object for the directory
filenames = folder.list(extfilter); // fill the fileNames string array with the filter result
curFrame = 0;
String preset_dir = dopresets ? File.separator + current_preset : "";
while (curFrame<filenames.length) {
String curr_name = foldername+File.separator+"batch"+session_prefix()+preset_dir+File.separator+filenames[curFrame];
println("Encoding: " + curr_name);
img = loadImage(foldername+File.separator+filenames[curFrame]);
result = encode(img, curr_name.replace(".png", "").replace(".jpg", "").replace(".jpeg", "").replace(".bmp", "")+".glic"); // todo: make filename without extension
result.save(curr_name);
current = result;
reset_buffer();
curFrame++;
}
}
void encode_button() {
readValues();
if (!isBatch) {
println("Encoding: " + foldername+File.separator+filename+session_prefix()+File.separator+glic_filename.getText());
result = encode(img, foldername+File.separator+filename+session_prefix()+File.separator+glic_filename.getText());
current = result;
reset_buffer();
} else {
encode_batch(false);
}
bbar_reset("Result");
}
void decode_button() {
if (!isBatch) {
println("Decoding: " + foldername+File.separator+filename+session_prefix()+File.separator+glic_filename.getText());
result = decode(foldername+File.separator+filename+session_prefix()+File.separator+glic_filename.getText());
current = result;
reset_buffer();
} else {
println("Batch: "+foldername);
java.io.File folder = new java.io.File(dataPath(foldername)+File.separator + "batch" + session_prefix()); // set up a File object for the directory
filenames = folder.list(glicfilter); // fill the fileNames string array with the filter result
curFrame = 0;
while (curFrame<filenames.length) {
String curr_name = foldername+File.separator+"batch"+session_prefix()+File.separator+filenames[curFrame];
println("Decoding: " + curr_name);
result = decode(curr_name);
result.save(curr_name.replace(".glic", "")+".png");
current = result;
reset_buffer();
curFrame++;
}
}
bbar_reset("Result");
}
void save_buffer(String pref) {
if (buffer != null) {
String ppref = "".equals(pref) ? "" : (pref + "_");
String fn = foldername+File.separator+filename+session_prefix()+File.separator+ppref+save_filename.getText();
println("Saving: " + fn);
buffer.save(fn);
save_filename.setText(get_next_filename());
println("Saved");
}
}
void save_button() {
save_buffer("");
}
int filename_cnt = 0;
String get_next_filename() {
return filename+"_"+nf(filename_cnt++, 6)+".png";
}
void bbar_reset(String h) {
for (String s : bbar_names) {
if (h.equals(s)) {
bbar.changeItem(s, "selected", true);
} else {
bbar.changeItem(s, "selected", false);
}
}
}
void new_session() {
if (!do_skip_session) {
session_id = hex(sdf.format(new Date()).hashCode());
println("Session name: " + session_id);
} else {
session_id = "";
}
filename_cnt = 0;
save_filename.setText(get_next_filename());
glic_filename.setText(filename+".glic");
}
void load_image(String fname, boolean reset_session) {
println("Loading file: " + fname);
if ("jpg".equals(fileext)
|| "jpeg".equals(fileext)
|| "gif".equals(fileext)
|| "png".equals(fileext)
|| "bmp".equals(fileext)) {
img = loadImage(fname);
bbar_reset("Image");
} else {
result = img = decode(fname);
bbar_reset("Result");
}
if (reset_session) new_session();
current = img;
reset_buffer();
}
void fileSelected(File selection) {
if (selection != null) {
current = null;
String fn = selection.getName();
int i = fn.lastIndexOf('.');
fileext = fn.substring(i+1).toLowerCase();
filename = fn.substring(0, i);
foldername = selection.getParent();
origname = selection.getAbsolutePath();
load_image(origname, true);
}
}
boolean resetting_buffer = false;
void reset_buffer() {
resetting_buffer = true;
if (current != null) {
float ratio = (float)current.width/(float)current.height;
neww = ratio < 1.0 ? (int)(max_display_size * ratio) : max_display_size;
newh = ratio < 1.0 ? max_display_size : (int)(max_display_size / ratio);
posx = ratio < 1.0 ? (max_display_size-neww) / 2 : 0;
posy = ratio < 1.0 ? 0 : (max_display_size-newh) / 2;
buffer = createGraphics(current.width, current.height);
buffer.beginDraw();
buffer.image(current, 0, 0);
buffer.endDraw();
}
resetting_buffer = false;
}
void load_button() {
selectInput("Select a file to process:", "fileSelected");
}
void toggle_sep_chan() {
if (separate_channels.getArrayValue()[0]==1) {
ch1.setLabel("Channel 1");
ch2.setVisible(true);
ch3.setVisible(true);
separate_channels_toggle = true;
} else {
ch1.setLabel("All channels");
ch2.setVisible(false);
ch3.setVisible(false);
separate_channels_toggle = false;
}
}
void controlEvent(ControlEvent e) {
if (e.isFrom(separate_channels)) {
toggle_sep_chan();
}
if (e.isFrom(batch)) {
isBatch = !isBatch;
}
if (e.isFrom(skip_header)) {
do_skip_header = !do_skip_header;
}
if (e.isFrom(skip_session)) {
do_skip_session = !do_skip_session;
new_session();
}
if (e.isFrom(ch1mn)) {
float mn = ch1mn.getValue();
float mx = ch1mx.getValue();
if (mn>mx) ch1mx.setValue(mn);
}
if (e.isFrom(ch2mn)) {
float mn = ch2mn.getValue();
float mx = ch2mx.getValue();
if (mn>mx) ch2mx.setValue(mn);
}
if (e.isFrom(ch3mn)) {
float mn = ch3mn.getValue();
float mx = ch3mx.getValue();
if (mn>mx) ch3mx.setValue(mn);
}
if (e.isFrom(ch1mx)) {
float mn = ch1mn.getValue();
float mx = ch1mx.getValue();
if (mx<mn) ch1mn.setValue(mx);
}
if (e.isFrom(ch2mx)) {
float mn = ch2mn.getValue();
float mx = ch2mx.getValue();
if (mx<mn) ch2mn.setValue(mx);
}
if (e.isFrom(ch3mx)) {
float mn = ch3mn.getValue();
float mx = ch3mx.getValue();
if (mx<mn) ch3mn.setValue(mx);
}
}
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2017 GlitchCodec
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# GLIC
Glitch Image Codec
Documentation: https://docs.google.com/document/d/1cdJvEmSKNAkzkU0dFUa-kb_QJB2ISQg-QfCqpHLFlck/edit?usp=sharing
================================================
FILE: codec.pde
================================================
import com.github.jinahya.bit.io.*;
import java.io.*;
boolean do_skip_header = false;
class CodecConfig {
// Color space to operate
int colorspace = HWB;
// color outside image, always RGB
color color_outside = color(128, 128, 128);
// Segmentation configuration.
// Minimum/maximum block size for each channel
int[] min_block_size = {
2, 2, 2
};
int[] max_block_size = {
256, 256, 256
};
// Precision (lower better), values between 5 and 50+
float[] segmentation_precision = {
15, 15, 15
};
// Final encoding configuration
int[] encoding_method = {
0, 0, 0
};
// Global prediction method
int[] prediction_method = {
9, 9, 9
};
// prediction quantization 0-255
int[] quantization_value = {
110, 110, 110
};
int[] clamp_method = {
0, 0, 0
};
// type of transformation
int[] transform_type = {
0, 0, 0
};
// Transform method
int[] transform_method = {
29, 29, 29
};
// transform compression 0-255
float[] transform_compress = {
0, 0, 0
};
int[] transform_scale = {
20, 20, 20
};
public CodecConfig() {
super();
}
}
CodecConfig ccfg = new CodecConfig();
float trans_compression_value(float v) {
return 50*sq(v/255.0);
}
float quant_value(int v) {
return v/2.0;
}
PImage encode(PImage img, String fname) {
System.gc();
img.loadPixels();
try {
println("Encoding started");
GlicCodecWriter gcw = new GlicCodecWriter(fname, img.width, img.height);
println("Write first header");
// fourcc, width, height, colorspace, border color
gcw.writeFirstHeader();
println("Color space: "+getColorspaceName(ccfg.colorspace));
// prepare transform method and type, skip TRANS_NONE (0)
for (int p=0; p<3; p++) {
ccfg.transform_method[p] = ccfg.transform_method[p]==WAVELET_RANDOM ? (int)random(1, WAVELETNO) : ccfg.transform_method[p];
ccfg.transform_type[p] = ccfg.transform_type[p]==TRANSTYPE_RANDOM ? (int)random(TRANSTYPENO) : ccfg.transform_type[p];
}
println("Write second header");
// prediction method, quantization and clamping, transformations and final encoding per channel
gcw.writeSecondHeader();
// img -> planes structure
Planes planes = new Planes(img.pixels, img.width, img.height, ccfg.colorspace);
// Segmentation is stored as quad tree encoded binary (1 - go deeper, 0 - leaf)
// where to store all segments
ArrayList<Segment> segments[] = new ArrayList[3];
gcw.writeSegmentationMark();
for (int p=0; p<3; p++) {
println("Channel "+p+" segmentation. Structure.");
gcw.writeChannelMark(p);
ByteArrayOutputStream segm_arr_out = new ByteArrayOutputStream();
DefaultBitOutput segm_out = new DefaultBitOutput(new StreamByteOutput(segm_arr_out));
segments[p] = makeSegmentation(segm_out, planes, p, ccfg.min_block_size[p], ccfg.max_block_size[p], ccfg.segmentation_precision[p]);
println("Created " + segments[p].size() + " segments.");
// allign to byte
segm_out.align(1);
// store size to update later
gcw.segmentation_sizes[p]=segm_arr_out.size();
gcw.writeArray(segm_arr_out.toByteArray(), segm_arr_out.size());
}
println("Store segmentation visualization");
isegm = visualize_segmentation(segments, planes);
// set separator, 512 bytes of 0xff
gcw.writeSeparator(512, (byte)0xff);
// process of encoding involves decoding, we have to store somewhere only encoded data
Planes result = planes.clone();
Planes planes_pred = planes.clone();
println("Data encoding: predictions and transformations");
for (int p=0; p<3; p++) {
Wavelet wavelet = ccfg.transform_method[p] == WAVELET_NONE ? null : createWavelet(ccfg.transform_method[p]);
WaveletTransform trans = wavelet == null ? null : createTransform(ccfg.transform_type[p], wavelet);
Compressor comp = ccfg.transform_compress[p] > 0 ? new CompressorMagnitude(trans_compression_value(ccfg.transform_compress[p])) : null;
println("Wavelet for plane " + p + " -> " + (wavelet==null?"NONE":wavelet.getName()));
println("Transformation for plane " + p + " -> " + (trans==null?"NONE":trans.getName()));
println("Prediction for plane " + p + " -> " + predict_name(ccfg.prediction_method[p]));
// gather SAD/BSAD statistics
pred_sad_stats = new int[MAX_PRED];
float pq = quant_value(ccfg.quantization_value[p]);
for (Segment s : segments[p]) {
// predict
int[][] pred = predict(ccfg.prediction_method[p], planes, p, s);
// calculate residuals and clamp
planes.subtract(p, s, pred, ccfg.clamp_method[p]);
// quantize result
if (pq > 0) quantize(planes, p, s, pq, true);
// if transformation applied transform and compress
// maximum value after transformation is s.size * max_value
try {
if (trans != null) {
double[][] tr = planes.get(p, s);
tr = trans.forward(tr);
if (comp != null) {
tr = comp.compress(tr);
}
// store result as ints
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
planes.set(p, s.x+x, s.y+y, round((float)((tr[x][y]*ccfg.transform_scale[p])/(float)s.size)));
}
}
}
}
catch (JWaveException e) {
// ignore
}
// store encoding value in result planes to save later
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
result.set(p, s.x+x, s.y+y, planes.get(p, s.x+x, s.y+y));
}
}
// decompress now
// wavelets
try {
if (trans != null) {
double[][] tr = new double[s.size][s.size];
for (int xx=0; xx<tr.length; xx++) {
for (int yy=0; yy<tr.length; yy++) {
tr[xx][yy] = (s.size*planes.get(p, s.x+xx, s.y+yy))/(float)ccfg.transform_scale[p];
}
}
tr = trans.reverse(tr);
planes.set(p, s, tr, ccfg.clamp_method[p]);
}
}
catch (JWaveException e) {
// ignore
}
// reverse quantization
if (pq > 0) quantize(planes, p, s, pq, false);
// add back residuals and clamp
pred = predict(s.pred_type, planes, p, s);
planes.add(p, s, pred, ccfg.clamp_method[p]);
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
planes_pred.set(p, s.x+x, s.y+y, pred[x][y]);
}
}
}
}
ipred = planes_pred.toImage();
planes_pred=null;
gcw.writePredictDataMark();
// store another config, prediction additional info
for (int p=0; p<3; p++) {
println("Channel "+p+" segmentation. Configuration.");
gcw.writeChannelMark(p);
gcw.writeSegmentsData(p, segments[p]);
}
gcw.writeSeparator(512, (byte)0xff);
gcw.writeDataMark();
println("Encoding data");
for (int p=0; p<3; p++) {
gcw.writeChannelMark(p);
gcw.data_sizes[p] = gcw.writeData(ccfg.encoding_method[p], result, p, segments[p]);
}
println(gcw.data_sizes);
gcw.close();
result = null;
PImage rrr = planes.toImage();
println("FINISHED");
println("");
return rrr;
}
catch (Exception e) {
println("Encoding failed");
e.printStackTrace();
}
return null;
}
PImage decode(String fname) {
System.gc();
if (do_skip_header) readValues();
println("Decoding started");
try {
GlicCodecReader gcr = new GlicCodecReader(fname);
println("Read first header");
gcr.readFirstHeader();
println("Color space: "+getColorspaceName(gcr.colorspace));
println("Read second header");
gcr.readSecondHeader();
println("Reading segmentation structure");
Planes planes = new Planes(gcr.w, gcr.h, gcr.colorspace, new RefColor(gcr.color_outside[0], gcr.color_outside[1], gcr.color_outside[2], gcr.colorspace));
ArrayList<Segment> segments[] = new ArrayList[4];
gcr.skip(13); // segmentation mark
for (int p=0; p<3; p++) {
println("Channel "+p+" segmentation");
gcr.skip(4);
byte[] segmentation_info = gcr.readArray(gcr.segmentation_sizes[p]);
ArrayByteInput segm_arr_in = new ArrayByteInput(segmentation_info, 0, segmentation_info.length);
DefaultBitInput segm_in = new DefaultBitInput(segm_arr_in);
segments[p] = readSegmentation(segm_in, planes);
}
gcr.skip(512);
println("Reading segmentation data");
gcr.skip(12); // predict data mark
for (int p=0; p<3; p++) {
gcr.skip(4);
gcr.readSegmentsData(p, segments[p]);
}
gcr.skip(512);
gcr.skip(10); // image data mark
println("Decoding data");
for (int p=0; p<3; p++) {
gcr.skip(4);
gcr.readData(gcr.encoding_method[p], planes, p, segments[p]);
}
Planes planes_pred = planes.clone();
for (int p=0; p<3; p++) {
Wavelet wavelet = gcr.transform_method[p] == WAVELET_NONE ? null : createWavelet(gcr.transform_method[p]);
WaveletTransform trans = wavelet == null ? null : createTransform(gcr.transform_type[p], wavelet);
println("Wavelet for plane " + p + " -> " + (wavelet==null?"NONE":wavelet.getName()));
println("Transformation for plane " + p + " -> " + (trans==null?"NONE":trans.getName()));
println("Prediction for plane " + p + " -> " + predict_name(gcr.prediction_method[p]));
float pq = quant_value(gcr.quant_value[p]);
for (Segment s : segments[p]) {
try {
if (trans != null) {
double[][] tr = new double[s.size][s.size];
for (int xx=0; xx<tr.length; xx++) {
for (int yy=0; yy<tr.length; yy++) {
tr[xx][yy] = (s.size*planes.get(p, s.x+xx, s.y+yy))/(float)gcr.transform_scale[p];
}
}
tr = trans.reverse(tr);
planes.set(p, s, tr, gcr.clamp_method[p]);
}
}
catch (JWaveException e) {
// ignore
}
if (pq>0) quantize(planes, p, s, pq, false);
int[][] pred = predict(s.pred_type, planes, p, s);
planes.add(p, s, pred, gcr.clamp_method[p]);
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
planes_pred.set(p, s.x+x, s.y+y, pred[x][y]);
}
}
}
}
gcr.close();
println("Store segmentation visualization");
isegm = visualize_segmentation(segments, planes);
ipred = planes_pred.toImage();
println("FINISHED");
println("");
return planes.toImage();
}
catch (Exception e) {
println("Decoding failed");
e.printStackTrace();
}
return null;
}
PImage visualize_segmentation(ArrayList<Segment> segments[], Planes source) {
Planes res = source.clone();
for (int p=0; p<3; p++) {
for (Segment ss : segments[p]) {
int v = source.get(p, ss.x+(ss.size>>1), ss.y+(ss.size>>1));
for (int x=0; x<ss.size; x++) {
for (int y=0; y<ss.size; y++) {
res.set(p, ss.x+x, ss.y+y, v);
}
}
}
}
return res.toImage();
}
class GlicCodecReader {
DataInputStream o;
String filename;
int w, h;
int colorspace;
int[] color_outside = {
0, 0, 0
};
int[] segmentation_sizes = {
0, 0, 0, 0
};
int[] data_sizes = {
0, 0, 0, 0
};
int[] segmdata_sizes = {
0, 0, 0, 0
};
// Final encoding configuration
int[] encoding_method = {
0, 0, 0
};
// Global prediction method
int[] prediction_method = {
0, 0, 0
};
int[] clamp_method = {
0, 0, 0
};
// prediction quantization 0-255
int[] quant_value = {
0, 0, 0
};
// Transform method
int[] transform_method = {
0, 0, 0
};
// type of transformation
int[] transform_type = {
0, 0, 0
};
int[] transform_scale = {
0, 0, 0
};
public GlicCodecReader(String filename) {
this.filename = filename;
o = new DataInputStream(new BufferedInputStream(createInput(filename)));
}
byte[] readArray(int size) throws IOException {
byte[] res = new byte[size];
try {
o.readFully(res, 0, size);
}
catch (java.io.EOFException e) {
// ignore
}
return res;
}
void readSegmentsData(int p, ArrayList<Segment> segments) throws IOException {
DataInputStream in = new DataInputStream(new ByteArrayInputStream(readArray(segmdata_sizes[p])));
try {
for (Segment s : segments) {
s.pred_type = in.readUnsignedByte();
s.pred_type = s.pred_type == PRED_NONE ? prediction_method[p] : s.pred_type;
s.refx = in.readShort();
s.refy = in.readShort();
s.refa = in.readUnsignedByte() % 3;
s.angle = (float)in.readShort()/0x7000;
}
}
catch (EOFException e) {
// ignore
}
finally {
in.close();
}
}
void readData(int method, Planes p, int pno, ArrayList<Segment> s) {
switch (method) {
case ENCODING_PACKED:
decode_packed(p, pno, s);
break;
case ENCODING_RLE:
decode_rle(p, pno, s);
break;
default:
decode_raw(p, pno, s);
}
}
void decode_raw(Planes p, int pno, ArrayList<Segment> s) {
try {
int idx=0;
for (Segment segm : s) {
for (int x=0; x<segm.size; x++) {
for (int y=0; y<segm.size; y++) {
if (idx < data_sizes[pno]) {
p.set(pno, segm.x+x, segm.y+y, o.readInt());
idx+=4;
}
}
}
}
}
catch (IOException e) {
println("decode raw failed");
// ignore
}
}
void decode_packed(Planes p, int pno, ArrayList<Segment> s) {
try {
byte[] d = readArray(data_sizes[pno]);
DefaultBitInput in = new DefaultBitInput(new ArrayByteInput(d, 0, d.length));
int bits = (int)ceil(log(transform_scale[pno])/log(2.0));
for (Segment segm : s) {
for (int x=0; x<segm.size; x++) {
for (int y=0; y<segm.size; y++) {
p.set(pno, segm.x+x, segm.y+y, decodePackedBits(in, pno, bits));
}
}
}
}
catch(EOFException e) {
println("decode packed failed (EOF)");
// ignore
}
catch(IOException e) {
println("decode packed failed (IO)");
// ignore
}
catch(IllegalStateException e) {
println("decode packed failed");
// ignore
}
}
void decode_rle(Planes p, int pno, ArrayList<Segment> s) {
try {
byte[] d = readArray(data_sizes[pno]);
DefaultBitInput in = new DefaultBitInput(new ArrayByteInput(d, 0, d.length));
int bits = (int)ceil(log(transform_scale[pno])/log(2.0));
int currentval = 0;
boolean do_read_type = true;
int currentcnt = 0;
for (Segment segm : s) {
for (int x=0; x<segm.size; x++) {
for (int y=0; y<segm.size; y++) {
if (do_read_type) {
if (in.readBoolean()) { // size
currentcnt = in.readInt(true, 7)+2;
do_read_type = false;
}
currentval = decodePackedBits(in, pno, bits);
}
p.set(pno, segm.x+x, segm.y+y, currentval);
currentcnt--;
if (currentcnt <= 0) {
do_read_type = true;
}
}
}
}
}
catch(EOFException e) {
println("decode rle failed (EOF)");
// ignore
}
catch(IOException e) {
println("decode rle failed (IO)");
// ignore
}
catch(IllegalStateException e) {
println("decode rle failed");
// ignore
}
}
int decodePackedBits(DefaultBitInput in, int pno, int bits) throws IOException {
if (transform_method[pno] == WAVELET_NONE) {
if (clamp_method[pno] == CLAMP_NONE) {
return in.readInt(false, 9);
} else if (clamp_method[pno] == CLAMP_MOD256) {
return in.readInt(true, 8);
}
} else {
return in.readInt(false, bits+1);
}
return 0;
}
void skip(int bytes) {
try {
for (int i=0; i<bytes; i++) o.readByte();
}
catch (IOException e) {
println("skip failed");
// ignore
}
}
void readFirstHeader() throws IOException {
// GLIC
skip(4);
// width, height
w = max(64,abs(o.readInt())%8192); // 4
h = max(64,abs(o.readInt())%8192); // 4
// colorspace
colorspace = o.readUnsignedByte(); // 1
if (do_skip_header) colorspace = ccfg.colorspace;
// color outside image
color_outside[0] = o.readUnsignedByte();
color_outside[1] = o.readUnsignedByte();
color_outside[2] = o.readUnsignedByte();
if (do_skip_header) {
color_outside[0] = getR(ccfg.color_outside);
color_outside[1] = getG(ccfg.color_outside);
color_outside[2] = getB(ccfg.color_outside);
}
segmentation_sizes[0] = o.readInt()&0x7ffff;
segmentation_sizes[1] = o.readInt()&0x7ffff;
segmentation_sizes[2] = o.readInt()&0x7ffff;
segmentation_sizes[3] = o.readInt()&0x7ffff;
segmdata_sizes[0] = o.readInt()&0xffffff;
segmdata_sizes[1] = o.readInt()&0xffffff;
segmdata_sizes[2] = o.readInt()&0xffffff;
segmdata_sizes[3] = o.readInt()&0xffffff;
data_sizes[0] = o.readInt()&0x3ffffff;
data_sizes[1] = o.readInt()&0x3ffffff;
data_sizes[2] = o.readInt()&0x3ffffff;
data_sizes[3] = o.readInt()&0x3ffffff;
println("Segmentation sizes");
println(segmentation_sizes);
println("Segmentation data sizes");
println(segmdata_sizes);
println("Data sizes");
println(data_sizes);
skip(128-16-16-16-16);
}
void readSecondHeader() throws IOException {
for (int p=0; p<3; p++) {
skip(4);
prediction_method[p] = o.readUnsignedByte();
quant_value[p] = o.readUnsignedByte();
clamp_method[p] = o.readUnsignedByte();
transform_method[p] = o.readUnsignedByte();
transform_type[p] = o.readUnsignedByte();
transform_scale[p] = o.readInt();
encoding_method[p] = o.readUnsignedByte();
if (do_skip_header) {
println(separate_channels_toggle);
int pp = separate_channels_toggle ? p : 0;
prediction_method[p] = max(0,ccfg.prediction_method[pp]);
quant_value[p] = ccfg.quantization_value[pp];
clamp_method[p] = ccfg.clamp_method[pp];
transform_method[p] = ccfg.transform_method[pp];
transform_type[p] = ccfg.transform_type[p];
transform_scale[p] = ccfg.transform_scale[pp];
encoding_method[p] = ccfg.encoding_method[pp];
}
skip(32-4-6-4);
}
}
void close() throws IOException {
o.close();
}
}
class GlicCodecWriter {
DataOutputStream o;
String filename;
int w, h;
int current_written;
int[] segmentation_sizes = {
0, 0, 0, 0
};
int[] data_sizes = {
0, 0, 0, 0
};
int[] segmdata_sizes = {
0, 0, 0, 0
};
public GlicCodecWriter(String filename, int w, int h) {
this.w = w;
this.h = h;
this.filename = filename;
o = new DataOutputStream(new BufferedOutputStream(createOutput(filename)));
current_written = o.size();
}
int writeData(int method, Planes p, int pno, ArrayList<Segment> s) throws IOException {
int current = o.size();
switch (method) {
case ENCODING_PACKED:
encode_packed(p, pno, s);
break;
case ENCODING_RLE:
encode_rle(p, pno, s);
break;
default:
encode_raw(p, pno, s);
}
return (o.size() - current);
}
void encode_raw(Planes p, int pno, ArrayList<Segment> s) throws IOException {
for (Segment segm : s) {
for (int x=0; x<segm.size; x++) {
for (int y=0; y<segm.size; y++) {
o.writeInt(p.get(pno, segm.x+x, segm.y+y));
}
}
}
}
void encode_packed(Planes p, int pno, ArrayList<Segment> s) throws IOException {
DefaultBitOutput out = new DefaultBitOutput(new StreamByteOutput(o));
int bits = (int)ceil(log(ccfg.transform_scale[pno])/log(2.0));
for (Segment segm : s) {
for (int x=0; x<segm.size; x++) {
for (int y=0; y<segm.size; y++) {
emitPackedBits(out, pno, bits, p.get(pno, segm.x+x, segm.y+y));
}
}
}
out.align(1);
}
void encode_rle(Planes p, int pno, ArrayList<Segment> s) throws IOException {
DefaultBitOutput out = new DefaultBitOutput(new StreamByteOutput(o));
int bits = (int)ceil(log(ccfg.transform_scale[pno])/log(2.0));
int currentval = 0;
boolean firstval = true;
int currentcnt = 0;
for (Segment segm : s) {
for (int x=0; x<segm.size; x++) {
for (int y=0; y<segm.size; y++) {
int val = p.get(pno, segm.x+x, segm.y+y);
if (firstval) {
currentval = val;
currentcnt = 1;
firstval = false;
} else {
if (currentval != val || currentcnt == 129) {
if (currentcnt == 1) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeInt(true, 7, currentcnt-2);
}
emitPackedBits(out, pno, bits, currentval);
currentval = val;
currentcnt = 1;
} else {
currentcnt++;
}
}
}
}
}
if (currentval == 1) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeInt(true, 7, currentcnt-2);
}
emitPackedBits(out, pno, bits, currentval);
out.align(1);
}
void emitPackedBits(DefaultBitOutput out, int pno, int bits, int val) throws IOException {
if (ccfg.transform_method[pno] == WAVELET_NONE) {
if (ccfg.clamp_method[pno] == CLAMP_NONE) {
out.writeInt(false, 9, val);
} else if (ccfg.clamp_method[pno] == CLAMP_MOD256) {
out.writeInt(true, 8, val);
}
} else {
out.writeInt(false, bits+1, val);
}
}
void writeSegmentsData(int pno, ArrayList<Segment> segments) throws IOException {
ByteArrayOutputStream baus = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(baus);
for (Segment s : segments) {
int pred_type = ccfg.prediction_method[pno] < 0 ? s.pred_type : PRED_NONE; // if prediction is different than NONE, store it, other cases are NONE
out.writeByte(pred_type);
out.writeShort(s.refx);
out.writeShort(s.refy);
out.writeByte(s.refa);
out.writeShort((int)(0x7000 * s.angle) );
}
out.flush();
out.close();
segmdata_sizes[pno] = baus.size();
writeArray(baus.toByteArray(), baus.size());
}
void align(int bytes) throws IOException {
int to_write = bytes - (o.size()-current_written);
writeSeparator(to_write, 0);
current_written = o.size();
}
void writeArray(byte[] a, int size) throws IOException {
o.write(a, 0, size);
}
void writeSeparator(int size, int val) throws IOException {
for (int i=0; i<size; i++) {
o.writeByte(val);
}
}
void writeChannelMark(int ch) throws IOException {
o.writeByte(0x43);
o.writeByte(0x48);
o.writeByte(0x30);
o.writeByte(0x31+ch);
}
void writeSegmentationMark() throws IOException { //12
o.writeByte(0x53);
o.writeByte(0x45);
o.writeByte(0x47);
o.writeByte(0x4D);
o.writeByte(0x45);
o.writeByte(0x4E);
o.writeByte(0x54);
o.writeByte(0x41);
o.writeByte(0x54);
o.writeByte(0x49);
o.writeByte(0x4F);
o.writeByte(0x4E);
o.writeByte(0x20);
}
void writePredictDataMark() throws IOException { //11
o.writeByte(0x50);
o.writeByte(0x52);
o.writeByte(0x45);
o.writeByte(0x44);
o.writeByte(0x49);
o.writeByte(0x43);
o.writeByte(0x54);
o.writeByte(0x44);
o.writeByte(0x41);
o.writeByte(0x54);
o.writeByte(0x41);
o.writeByte(0x20);
}
void writeDataMark() throws IOException { //9
o.writeByte(0x49);
o.writeByte(0x4D);
o.writeByte(0x41);
o.writeByte(0x47);
o.writeByte(0x45);
o.writeByte(0x44);
o.writeByte(0x41);
o.writeByte(0x54);
o.writeByte(0x41);
o.writeByte(0x20);
}
void writeFirstHeader() throws IOException {
// GLIC
o.writeByte(0x47);
o.writeByte(0x4C);
o.writeByte(0x49);
o.writeByte(0x43);
// width, height
o.writeInt(w); // 4
o.writeInt(h); // 4
// colorspace
o.writeByte(ccfg.colorspace); // 1
// color outside image
o.writeByte(getR(ccfg.color_outside)); // 1
o.writeByte(getG(ccfg.color_outside)); // 1
o.writeByte(getB(ccfg.color_outside)); // 1
align(128);
}
void writeSecondHeader() throws IOException {
for (int p=0; p<3; p++) {
writeChannelMark(p);
int pred = ccfg.prediction_method[p];
// write PRED_NONE if random or sad/bsad, specific prediction method will be stored separately
if (pred<0) pred = PRED_NONE;
o.writeByte(pred); // what prediction
o.writeByte(ccfg.quantization_value[p]); // quantization value
o.writeByte(ccfg.clamp_method[p]); // how to clamp / encode residuals
o.writeByte(ccfg.transform_method[p]); // which wavelet
o.writeByte(ccfg.transform_type[p]); // which transform
o.writeInt(ccfg.transform_scale[p]);
o.writeByte(ccfg.encoding_method[p]); // final encoding / compression
align(32);
}
}
void size() throws IOException {
o.size();
}
void close() throws IOException {
o.flush();
o.close();
RandomAccessFile raf = new RandomAccessFile(sketchPath(filename), "rw");
raf.seek(16);
raf.writeInt(segmentation_sizes[0]);
raf.writeInt(segmentation_sizes[1]);
raf.writeInt(segmentation_sizes[2]);
raf.writeInt(segmentation_sizes[3]);
raf.writeInt(segmdata_sizes[0]);
raf.writeInt(segmdata_sizes[1]);
raf.writeInt(segmdata_sizes[2]);
raf.writeInt(segmdata_sizes[3]);
raf.writeInt(data_sizes[0]);
raf.writeInt(data_sizes[1]);
raf.writeInt(data_sizes[2]);
raf.writeInt(data_sizes[3]);
raf.close();
println("Segmentation sizes");
println(segmentation_sizes);
println("Segmentation data sizes");
println(segmdata_sizes);
println("Data sizes");
println(data_sizes);
}
}
================================================
FILE: colorspaces.pde
================================================
final static int COLORSPACES = 16;
final static int OHTA = 0;
// RGB == 1; defined in processing
final static int CMY = 2;
// HSB == 3; defined in processing
final static int XYZ = 4;
final static int YXY = 5;
final static int HCL = 6;
final static int LUV = 7;
final static int LAB = 8;
final static int HWB = 9;
final static int RGGBG = 10;
final static int YPbPr = 11;
final static int YCbCr = 12;
final static int YDbDr = 13;
final static int GS = 14;
final static int YUV = 15;
// name
String getColorspaceName(int cs) {
switch(cs) {
case OHTA:
return "OHTA";
case CMY:
return "CMY";
case XYZ:
return "XYZ";
case YXY:
return "YXY";
case HCL:
return "HCL";
case LUV:
return "LUV";
case LAB:
return "LAB";
case HWB:
return "HWB";
case HSB:
return "HSB";
case RGGBG:
return "R-GGB-G";
case YPbPr:
return "YPbPr";
case YCbCr:
return "YCbCr";
case YDbDr:
return "YDbDr";
case GS:
return "Greyscale";
case YUV:
return "YUV";
default:
return "RGB";
}
}
// colorspace converters
color fromColorspace(color c, int cs) {
switch(cs) {
case OHTA:
return fromOHTA(c);
case CMY:
return fromCMY(c);
case XYZ:
return fromXYZ(c);
case YXY:
return fromYXY(c);
case HCL:
return fromHCL(c);
case LUV:
return fromLUV(c);
case LAB:
return fromLAB(c);
case HWB:
return fromHWB(c);
case HSB:
return fromHSB(c);
case RGGBG:
return fromRGGBG(c);
case YPbPr:
return fromYPbPr(c);
case YCbCr:
return fromYCbCr(c);
case YDbDr:
return fromYDbDr(c);
case GS:
return tofromGS(c);
case YUV:
return fromYUV(c);
default:
return c;
}
}
color toColorspace(color c, int cs) {
switch(cs) {
case OHTA:
return toOHTA(c);
case CMY:
return toCMY(c);
case XYZ:
return toXYZ(c);
case YXY:
return toYXY(c);
case HCL:
return toHCL(c);
case LUV:
return toLUV(c);
case LAB:
return toLAB(c);
case HWB:
return toHWB(c);
case HSB:
return toHSB(c);
case RGGBG:
return toRGGBG(c);
case YPbPr:
return toYPbPr(c);
case YCbCr:
return toYCbCr(c);
case YDbDr:
return toYDbDr(c);
case YUV:
return toYUV(c);
case GS:
return tofromGS(c);
default:
return c;
}
}
// Colorspace converters
final int getA(color c) {
return (c & 0xff000000) >> 24;
}
final int getR(color c) {
return (c & 0xff0000) >> 16;
}
final int getG(color c) {
return (c & 0xff00) >> 8;
}
final int getB(color c) {
return c & 0xff;
}
final int getLuma(color c) {
return constrain((int)(0.2126*getR(c)+0.7152*getG(c)+0.0722*getB(c)), 0, 255);
}
int getChannel(color c, int ch) {
switch(ch) {
case 0 :
return getR(c);
case 1 :
return getG(c);
case 2 :
return getB(c);
case 3 :
return getA(c);
default:
return 0;
}
}
// normalized versions
final float getNR(color c) {
return r255[(c & 0xff0000) >> 16];
}
final float getNG(color c) {
return r255[(c & 0xff00) >> 8];
}
final float getNB(color c) {
return r255[c & 0xff];
}
final float getNLuma(color c) {
return r255[getLuma(c)];
}
color blendRGB(color c, int r, int g, int b) {
return (c & 0xff000000) | (constrain(r, 0, 255) << 16) | (constrain(g, 0, 255) << 8 ) | constrain(b, 0, 255);
}
color blendRGB(color c, float r, float g, float b) {
return blendRGB(c, (int)(r*255), (int)(g*255), (int)(b*255));
}
/**************
* Greyscale
**************/
color tofromGS(color c) {
int l = getLuma(c);
return blendRGB(c, l, l, l);
}
/**************
* YUV
**************/
final static float Umax = 0.436 * 255.0;
final static float Vmax = 0.615 * 255.0;
color toYUV(color c) {
int R = getR(c);
int G = getG(c);
int B = getB(c);
int Y = (int)( 0.299*R+0.587*G+0.114*B);
int U = (int)map(-0.14713*R-0.28886*G+0.436*B,-Umax,Umax,0,255);
int V = (int)map(0.615*R-0.51499*G-0.10001*B,-Vmax,Vmax,0,255);
return blendRGB(c, Y, U, V);
}
color fromYUV(color c) {
int Y = getR(c);
float U = map(getG(c),0,255,-Umax,Umax);
float V = map(getB(c),0,255,-Vmax,Vmax);
int R = (int)(Y + 1.13983*V);
int G = (int)(Y - 0.39465*U - 0.58060*V);
int B = (int)(Y + 2.03211*U);
return blendRGB(c, R, G, B);
}
/**************
* YDbDr
**************/
color toYDbDr(color c) {
int R = getR(c);
int G = getG(c);
int B = getB(c);
int Y = (int)( 0.299*R+0.587*G+0.114*B);
int Db = (int)(127.5+(-0.450*R-0.883*G+1.333*B)/2.666);
int Dr = (int)(127.5+(-1.333*R+1.116*G+0.217*B)/2.666);
return blendRGB(c, Y, Db, Dr);
}
color fromYDbDr(color c) {
int Y = getR(c);
float Db = (getG(c)-127.5)*2.666;
float Dr = (getB(c)-127.5)*2.666;
int R = (int)(Y + 9.2303716147657e-05*Db-0.52591263066186533*Dr);
int G = (int)(Y - 0.12913289889050927*Db+0.26789932820759876*Dr);
int B = (int)(Y + 0.66467905997895482*Db-7.9202543533108e-05*Dr);
return blendRGB(c, R, G, B);
}
/**************
* YCbCr
**************/
color toYCbCr(color c) {
int R = getR(c);
int G = getG(c);
int B = getB(c);
int Y = (int)( 0.2988390*R+0.5868110*G+0.1143500*B);
int Cb = (int)(-0.168736*R-0.3312640*G+0.5000000*B+127.5);
int Cr = (int)( 0.5000000*R-0.4186880*G-0.0813120*B+127.5);
return blendRGB(c, Y, Cb, Cr);
}
color fromYCbCr(color c) {
int Y = getR(c);
float Cb = getG(c) - 127.5;
float Cr = getB(c) - 127.5;
int R = (int)(Y + 1.402*Cr)+1; // some fix
int G = (int)(Y-0.344136*Cb-0.714136*Cr);
int B = (int)(Y+1.772000*Cb)+1; // some fix
return blendRGB(c, R, G, B);
}
/**************
* YPbPr
**************/
color toYPbPr(color c) {
int R = getR(c);
int B = getB(c);
int Y = getLuma(c);
int Pb = B - Y;
int Pr = R - Y;
if(Pb<0) Pb+=256;
if(Pr<0) Pr+=256;
return blendRGB(c, Y, Pb, Pr);
}
color fromYPbPr(color c) {
int Y = getR(c);
int B = getG(c) + Y;
int R = getB(c) + Y;
if(R>255) R-=256;
if(B>255) B-=256;
int G = (int)((Y-0.2126*R-0.0722*B)/0.7152);
return blendRGB(c, R, G, B);
}
/**************
* R-G,G,B-G
**************/
color toRGGBG(color c) {
int G = getG(c);
int R = getR(c)-G;
int B = getB(c)-G;
if(R<0) R+=256;
if(B<0) B+=256;
return blendRGB(c, R, G, B);
}
color fromRGGBG(color c) {
int G = getG(c);
int R = getR(c)+G;
int B = getB(c)+G;
if(R>255) R-=256;
if(B>255) B-=256;
return blendRGB(c, R, G, B);
}
/**************
* HWB
**************/
color toHSB(color c) {
int R = getR(c);
int G = getG(c);
int B = getB(c);
int _min = min(R, G, B);
int _max = max(R, G, B);
float delta = _max-_min;
float saturation = delta/_max;
float brightness = r255[_max];
if (delta == 0.0) return blendRGB(c, 0.0, saturation, brightness);
float hue = 0;
if (R == _max) hue = (G-B)/delta;
else if (G == _max) hue = 2.0 + (B-R)/delta;
else hue = 4.0 + (R-G)/delta;
hue /= 6.0;
if (hue < 0.0) hue += 1.0;
return blendRGB(c, hue, saturation, brightness);
}
color fromHSB(color c) {
float S = getNG(c);
float B = getNB(c);
if (S == 0.0) return blendRGB(c, B, B, B);
float h = 6.0 * getNR(c);
float f = h-floor(h);
float p = B*(1.0-S);
float q = B*(1.0-S*f);
float t = B*(1.0-(S*(1.0-f)));
float r, g, b;
switch((int)h) {
case 1:
r=q;
g=B;
b=p;
break;
case 2:
r=p;
g=B;
b=t;
break;
case 3:
r=p;
g=q;
b=B;
break;
case 4:
r=t;
g=p;
b=B;
break;
case 5:
r=B;
g=p;
b=q;
break;
default:
r=B;
g=t;
b=p;
break;
}
return blendRGB(c, r, g, b);
}
/**************
* HWB
**************/
color toHWB(color c) {
int R = getR(c);
int G = getG(c);
int B = getB(c);
int w = min(R, G, B);
int v = max(R, G, B);
int hue;
if (v == w) hue = 255;
else {
float f = ((R == w) ? G-B : ((G == w) ? B-R : R-G));
float p = (R == w) ? 3.0 : ((G == w) ? 5.0 : 1.0);
hue = (int)map((p-f/(v-w))/6.0, 0, 1, 0, 254);
}
return blendRGB(c, hue, w, 255-v);
}
color fromHWB(color c) {
int H = getR(c);
int B = 255-getB(c);
if (H == 255) return blendRGB(c, B, B, B);
else {
float hue = map(H, 0, 254, 0, 6);
float v = r255[B];
float whiteness = getNG(c);
int i = (int)floor(hue);
float f = hue-i;
if ((i&0x01)!= 0) f=1.0-f;
float n = whiteness+f*(v-whiteness);
float r, g, b;
switch(i) {
case 1:
r=n;
g=v;
b=whiteness;
break;
case 2:
r=whiteness;
g=v;
b=n;
break;
case 3:
r=whiteness;
g=n;
b=v;
break;
case 4:
r=n;
g=whiteness;
b=v;
break;
case 5:
r=v;
g=whiteness;
b=n;
break;
default:
r=v;
g=n;
b=whiteness;
break;
}
return blendRGB(c, r, g, b);
}
}
/**************
* Lab
**************/
final static float D65X=0.950456;
final static float D65Y=1.0;
final static float D65Z=1.088754;
final static float CIEEpsilon=(216.0/24389.0);
final static float CIEK=(24389.0/27.0);
final static float CIEK2epsilon = CIEK * CIEEpsilon;
final static float D65FX_4 = 4.0*D65X/(D65X+15.0*D65Y+3.0*D65Z);
final static float D65FY_9 = 9.0*D65Y/(D65X+15.0*D65Y+3.0*D65Z);
final static float RANGE_X = 100.0 * (0.4124+0.3576+0.1805);
final static float RANGE_Y = 100.0;
final static float RANGE_Z = 100.0 * (0.0193+0.1192+0.9505);
final static float mepsilon = 1.0e-10;
final static float corrratio = 1.0/2.4;
final static float One_Third = 1.0/3.0;
final static float one_hsixteen = 1.0/116.0;
color toLAB(color c) {
PVector xyz = _toXYZ(getNR(c), getNG(c), getNB(c));
xyz.div(100.0);
xyz.x /= D65X;
xyz.y /= D65Y;
xyz.z /= D65Z;
float x, y, z;
if (xyz.x > CIEEpsilon) {
x = pow(xyz.x, One_Third);
} else {
x= (CIEK*xyz.x+16.0)*one_hsixteen;
}
if (xyz.y > CIEEpsilon) {
y = pow(xyz.y, One_Third);
} else {
y = (CIEK*xyz.y+16.0)*one_hsixteen;
}
if (xyz.z > CIEEpsilon) {
z = pow(xyz.z, One_Third);
} else {
z = (CIEK*xyz.z+16.0)*one_hsixteen;
}
float L = 255.0*(((116.0*y)-16.0)*0.01);
float a = 255.0*(0.5*(x-y)+0.5);
float b = 255.0*(0.5*(y-z)+0.5);
return blendRGB(c, round(L), round(a), round(b));
}
color fromLAB(color c) {
float L = 100*getNR(c);
float a = getNG(c)-0.5;
float b = getNB(c)-0.5;
float y = (L+16.0)*one_hsixteen;
float x = y+a;
float z = y-b;
float xxx=x*x*x;
if (xxx>CIEEpsilon) {
x = xxx;
} else {
x = (116.0*x-16.0)/CIEK;
}
float yyy=y*y*y;
if (yyy>CIEEpsilon) {
y = yyy;
} else {
y = L/CIEK;
}
float zzz=z*z*z;
if (zzz>CIEEpsilon) {
z = zzz;
} else {
z = (116.0*z-16.0)/CIEK;
}
return _fromXYZ(c, RANGE_X*x, RANGE_Y*y, RANGE_Z*z);
}
/**************
* Luv
**************/
final float PerceptibleReciprocal(float x) {
float sgn = x < 0.0 ? -1.0 : 1.0;
if ((sgn * x) >= mepsilon) return (1.0 / x);
return (sgn/mepsilon);
}
color toLUV(color c) {
PVector xyz = _toXYZ(getNR(c), getNG(c), getNB(c));
xyz.div(100.0);
float d = xyz.y; // / D65Y;
float L;
if (d > CIEEpsilon) L = 116.0*pow(d, One_Third)-16.0;
else L = CIEK * d;
float alpha = PerceptibleReciprocal(xyz.x + 15.0 * xyz.y + 3.0 * xyz.z);
float L13 = 13.0 * L;
float u = L13 * ((4.0 * alpha * xyz.x)-D65FX_4);
float v = L13 * ((9.0 * alpha * xyz.y)-D65FY_9);
L /= 100.0;
u=(u+134.0)/354.0;
v=(v+140.0)/262.0;
return blendRGB(c, round(L*255), round(u*255), round(v*255));
}
color fromLUV(color c) {
float L = 100.0*getNR(c);
float u = 354.0*getNG(c)-134.0;
float v = 262.0*getNB(c)-140.0;
float X, Y, Z;
if (L > CIEK2epsilon) Y = pow((L+16.0)*one_hsixteen, 3.0);
else Y = L/CIEK;
float L13 = 13.0*L;
float L52 = 52.0*L;
float Y5 = 5.0*Y;
float L13u = L52/(u+L13*D65FX_4);
X=((Y*((39.0*L/(v+L13*D65FY_9))-5.0))+Y5)/((((L13u)-1.0)/3.0)+One_Third);
Z=(X*(((L13u)-1.0)/3.0))-Y5;
return _fromXYZ(c, 100*X, 100*Y, 100*Z);
}
/**************
* HCL
**************/
color toHCL(color c) {
float r = getNR(c);
float g = getNG(c);
float b = getNB(c);
float max = max(r, max(g, b));
float chr = max - min(r, min(g, b));
float h = 0.0;
if ( chr != 0) {
if (r == max) {
h = ((g-b)/chr+6.0) % 6.0;
} else if (g == max) {
h = (b-r)/chr + 2.0;
} else {
h = (r-g)/chr + 4.0;
}
}
return blendRGB(c, round((h/6.0)*255), round(chr*255), round(255*(0.298839*r+0.586811*g+0.114350*b)));
}
color fromHCL(color c) {
float h = 6.0*getNR(c);
float chr = getNG(c);
float l = getNB(c);
float x = chr*(1.0-abs((h%2.0)-1.0));
float r = 0.0;
float g = 0.0;
float b = 0.0;
if ((0.0 <= h) && (h < 1.0)) {
r=chr;
g=x;
} else if ((1.0 <= h) && (h < 2.0)) {
r=x;
g=chr;
} else if ((2.0 <= h) && (h < 3.0)) {
g=chr;
b=x;
} else if ((3.0 <= h) && (h < 4.0)) {
g=x;
b=chr;
} else if ((4.0 <= h) && (h < 5.0)) {
r=x;
b=chr;
} else {//if ((5.0 <= h) && (h < 6.0)) {
r=chr;
b=x;
}
float m = l - (0.298839*r+0.586811*g+0.114350*b);
return blendRGB(c, round(255*(r+m)), round(255*(g+m)), round(255*(b+m)));
}
/**************
* Yxy
**************/
color toYXY(color c) {
PVector xyz = _toXYZ(getNR(c), getNG(c), getNB(c));
float sum = xyz.x + xyz.y + xyz.z;
float x = xyz.x > 0 ? xyz.x / sum : 0.0;
float y = xyz.y > 0 ? xyz.y / sum : 0.0;
return blendRGB(c,
(int)map(xyz.y, 0, RANGE_Y, 0, 255),
(int)map(x, 0.0, 1.0, 0, 255),
(int)map(y, 0.0, 1.0, 0, 255));
}
color fromYXY(color c) {
float Y = map(getR(c), 0, 255, 0, RANGE_Y);
float x = map(getG(c), 0, 255, 0, 1.0);
float y = map(getB(c), 0, 255, 0, 1.0);
float divy = Y / (y>0 ? y : 1.0e-6);
return _fromXYZ(c, x * divy, Y, (1-x-y)*divy);
}
/**************
* XYZ
**************/
// FIXME: range from 0 to 1
float correctionxyz(float n) {
return (n > 0.04045 ? pow((n + 0.055) / 1.055, 2.4) : n / 12.92) * 100.0;
}
PVector _toXYZ(float rr, float gg, float bb) {
float r = correctionxyz(rr);
float g = correctionxyz(gg);
float b = correctionxyz(bb);
return new PVector(r * 0.4124 + g * 0.3576 + b * 0.1805,
r * 0.2126 + g * 0.7152 + b * 0.0722,
r * 0.0193 + g * 0.1192 + b * 0.9505);
}
color toXYZ(color c) {
PVector xyz = _toXYZ(getNR(c), getNG(c), getNB(c));
return blendRGB(c,
(int)map(xyz.x, 0, RANGE_X, 0, 255),
(int)map(xyz.y, 0, RANGE_Y, 0, 255),
(int)map(xyz.z, 0, RANGE_Z, 0, 255));
}
float recorrectionxyz(float n) {
return n > 0.0031308 ? 1.055 * pow(n, corrratio) - 0.055 : 12.92 * n;
}
// FIXME: range from 0 to 1
color _fromXYZ(color c, float xx, float yy, float zz) {
float x = xx/100.0;
float y = yy/100.0;
float z = zz/100.0;
int r = round(255.0*recorrectionxyz(x * 3.2406 + y * -1.5372 + z * -0.4986));
int g = round(255.0*recorrectionxyz(x * -0.9689 + y * 1.8758 + z * 0.0415));
int b = round(255.0*recorrectionxyz(x * 0.0557 + y * -0.2040 + z * 1.0570));
return blendRGB(c, r, g, b);
}
color fromXYZ(color c) {
float x = map(getR(c), 0, 255, 0, RANGE_X);
float y = map(getG(c), 0, 255, 0, RANGE_Y);
float z = map(getB(c), 0, 255, 0, RANGE_Z);
return _fromXYZ(c, x, y, z);
}
/**************
* CMY
**************/
color toCMY(color c) {
return blendRGB(c, 255-getR(c), 255-getG(c), 255-getB(c));
}
color fromCMY(color c) {
return toCMY(c);
}
/**************
* OHTA
**************/
color fromOHTA(color c) {
int I1 = getR(c);
float I2 = map(getG(c), 0, 255, -127.5, 127.5);
float I3 = map(getB(c), 0, 255, -127.5, 127.5);
int R = (int)(I1+1.00000*I2-0.66668*I3);
int G = (int)(I1+1.33333*I3);
int B = (int)(I1-1.00000*I2-0.66668*I3);
return blendRGB(c, R, G, B);
}
color toOHTA(color c) {
int R = getR(c);
int G = getG(c);
int B = getB(c);
int I1 = (int)(0.33333*R+0.33334*G+0.33333*B);
int I2 = (int)map(0.5*(R-B), -127.5, 127.5, 0, 255);
int I3 = (int)map(-0.25000*R+0.50000*G-0.25000*B, -127.5, 127.5, 0, 255);
return blendRGB(c, I1, I2, I3);
}
////
// 1/n table for n=0..255 - to speed up color conversions things
final static float[] r255 = {
0.0, 0.003921569, 0.007843138, 0.011764706, 0.015686275, 0.019607844, 0.023529412, 0.02745098, 0.03137255, 0.03529412, 0.039215688,
0.043137256, 0.047058824, 0.050980393, 0.05490196, 0.05882353, 0.0627451, 0.06666667, 0.07058824, 0.07450981, 0.078431375, 0.08235294,
0.08627451, 0.09019608, 0.09411765, 0.09803922, 0.101960786, 0.105882354, 0.10980392, 0.11372549, 0.11764706, 0.12156863, 0.1254902,
0.12941177, 0.13333334, 0.13725491, 0.14117648, 0.14509805, 0.14901961, 0.15294118, 0.15686275, 0.16078432, 0.16470589, 0.16862746,
0.17254902, 0.1764706, 0.18039216, 0.18431373, 0.1882353, 0.19215687, 0.19607843, 0.2, 0.20392157, 0.20784314, 0.21176471, 0.21568628,
0.21960784, 0.22352941, 0.22745098, 0.23137255, 0.23529412, 0.23921569, 0.24313726, 0.24705882, 0.2509804, 0.25490198, 0.25882354,
0.2627451, 0.26666668, 0.27058825, 0.27450982, 0.2784314, 0.28235295, 0.28627452, 0.2901961, 0.29411766, 0.29803923, 0.3019608, 0.30588236,
0.30980393, 0.3137255, 0.31764707, 0.32156864, 0.3254902, 0.32941177, 0.33333334, 0.3372549, 0.34117648, 0.34509805, 0.34901962, 0.3529412,
0.35686275, 0.36078432, 0.3647059, 0.36862746, 0.37254903, 0.3764706, 0.38039216, 0.38431373, 0.3882353, 0.39215687, 0.39607844, 0.4,
0.40392157, 0.40784314, 0.4117647, 0.41568628, 0.41960785, 0.42352942, 0.42745098, 0.43137255, 0.43529412, 0.4392157, 0.44313726,
0.44705883, 0.4509804, 0.45490196, 0.45882353, 0.4627451, 0.46666667, 0.47058824, 0.4745098, 0.47843137, 0.48235294, 0.4862745, 0.49019608,
0.49411765, 0.49803922, 0.5019608, 0.5058824, 0.50980395, 0.5137255, 0.5176471, 0.52156866, 0.5254902, 0.5294118, 0.53333336, 0.5372549,
0.5411765, 0.54509807, 0.54901963, 0.5529412, 0.5568628, 0.56078434, 0.5647059, 0.5686275, 0.57254905, 0.5764706, 0.5803922, 0.58431375,
0.5882353, 0.5921569, 0.59607846, 0.6, 0.6039216, 0.60784316, 0.6117647, 0.6156863, 0.61960787, 0.62352943, 0.627451, 0.6313726, 0.63529414,
0.6392157, 0.6431373, 0.64705884, 0.6509804, 0.654902, 0.65882355, 0.6627451, 0.6666667, 0.67058825, 0.6745098, 0.6784314, 0.68235296,
0.6862745, 0.6901961, 0.69411767, 0.69803923, 0.7019608, 0.7058824, 0.70980394, 0.7137255, 0.7176471, 0.72156864, 0.7254902, 0.7294118,
0.73333335, 0.7372549, 0.7411765, 0.74509805, 0.7490196, 0.7529412, 0.75686276, 0.7607843, 0.7647059, 0.76862746, 0.77254903, 0.7764706,
0.78039217, 0.78431374, 0.7882353, 0.7921569, 0.79607844, 0.8, 0.8039216, 0.80784315, 0.8117647, 0.8156863, 0.81960785, 0.8235294, 0.827451,
0.83137256, 0.8352941, 0.8392157, 0.84313726, 0.84705883, 0.8509804, 0.85490197, 0.85882354, 0.8627451, 0.8666667, 0.87058824, 0.8745098,
0.8784314, 0.88235295, 0.8862745, 0.8901961, 0.89411765, 0.8980392, 0.9019608, 0.90588236, 0.9098039, 0.9137255, 0.91764706, 0.92156863,
0.9254902, 0.92941177, 0.93333334, 0.9372549, 0.9411765, 0.94509804, 0.9490196, 0.9529412, 0.95686275, 0.9607843, 0.9647059, 0.96862745,
0.972549, 0.9764706, 0.98039216, 0.9843137, 0.9882353, 0.99215686, 0.99607843, 1.0
};
================================================
FILE: encoding.pde
================================================
// final encoding
final static int ENCODING_RAW = 0;
final static int ENCODING_PACKED = 1;
final static int ENCODING_RLE = 2;
final static int ENCODINGNO = 3;
String encoding_name(int v) {
switch(v) {
case ENCODING_RAW: return "ENCODING RAW";
case ENCODING_PACKED: return "ENCODING PACKED";
case ENCODING_RLE: return "ENCODING RLE";
}
return null;
}
================================================
FILE: planes.pde
================================================
final static float LOG2 = log(2.0);
final static int CLAMP_NONE = 0;
final static int CLAMP_MOD256 = 1;
int clamp_in(int method, int x) {
switch(method) {
case CLAMP_MOD256:
return x<0?x+256:x>255?x-256:x;
default:
return x;
}
}
int clamp_out(int method, int x) {
switch(method) {
case CLAMP_MOD256:
return x<0?x+256:x>255?x-256:x;
default:
return constrain(x, 0, 255);
}
}
int clamp(int method, int x) {
switch(method) {
case CLAMP_MOD256:
return constrain(x, 0, 255);
default:
return constrain(x, -255, 255);
}
}
class RefColor {
int[] c;
public RefColor() {
c = new int[] {
128, 128, 128, 255
};
}
public RefColor(int r, int g, int b) {
this(color(r, g, b));
}
public RefColor(int r, int g, int b, int cs) {
this(color(r, g, b), cs);
}
public RefColor(color cc) {
c = new int[4];
c[2] = cc & 0xff;
c[1] = (cc >> 8) & 0xff;
c[0] = (cc >> 16) & 0xff;
c[3] = (cc >> 24) & 0xff;
}
public RefColor(color cc, int cs) {
this(toColorspace(cc, cs));
}
}
class Planes {
int ww, hh;
int w, h, cs;
int[][][] channels;
RefColor ref;
public Planes(int[] pxls, int w, int h, int cs, RefColor ref) {
this(w, h, cs, ref);
extractPlanes(pxls);
}
public Planes(int w, int h, int cs) {
this(w, h, cs, new RefColor(ccfg.color_outside, cs));
}
public Planes(int w, int h, int cs, RefColor ref) {
this.w = w;
this.h = h;
this.cs = cs;
ww = 1<<(int)ceil(log(w)/LOG2);
hh = 1<<(int)ceil(log(h)/LOG2);
//channels = new int[4][w][h];
channels = new int[3][w][h];
for (int x=0; x<w; x++) {
for (int y=0; y<h; y++) {
channels[0][x][y] = ref.c[0];
channels[1][x][y] = ref.c[1];
channels[2][x][y] = ref.c[2];
// channels[3][x][y] = ref.c[3];
}
}
this.ref = ref;
}
public Planes(int[] pxls, int w, int h, int cs) {
this(pxls, w, h, cs, new RefColor(ccfg.color_outside, cs));
}
public Planes clone() {
return new Planes(w,h,cs,ref);
}
private void extractPlanes(int[] pxls) {
for (int x=0; x<w; x++) {
for (int y=0; y<h; y++) {
color c = toColorspace(pxls[y*w+x], cs);
channels[2][x][y] = c & 0xff;
channels[1][x][y] = (c >> 8) & 0xff;
channels[0][x][y] = (c >> 16) & 0xff;
// channels[3][x][y] = (c >> 24) & 0xff;
}
}
}
public int[] toPixels() {
int[] pxls = new int[w*h];
for (int x=0; x<w; x++) {
for (int y=0; y<h; y++) {
int off = y*w+x;
int alpha = img == null ? 0xff000000 : (img.pixels[off]&0xff000000);
pxls[off] = fromColorspace(
(channels[2][x][y] ) |
((channels[1][x][y] ) << 8) |
((channels[0][x][y] ) << 16) |
alpha
// ((channels[3][x][y] ) << 24)
, cs);
}
}
return pxls;
}
public PImage toImage() {
PImage i = createImage(w, h, ARGB);
i.loadPixels();
i.pixels = toPixels();
i.updatePixels();
return i;
}
public int get(int pno, int x, int y) {
if (x<0 || x>=w || y<0 || y>=h) {
return ref.c[pno];
} else {
return channels[pno][x][y];
}
}
void set(int pno, int x, int y, int val) {
if (x>=0 && x<w && y>=0 && y<h) {
channels[pno][x][y] = val;
}
}
double[][] get(int pno, Segment s) {
double[][] res = new double[s.size][s.size];
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
res[x][y] = get(pno, x+s.x, y+s.y)/255.0;
}
}
return res;
}
void set(int pno, Segment s, double[][] values, int method) {
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
// set(pno, x+s.x, y+s.y, clamp(method,round((float)values[x][y])));
set(pno, x+s.x, y+s.y, clamp(method,round((float)(values[x][y]*255.0))));
}
}
}
void subtract(int pno, Segment s, int[][] values, int clamp_method) {
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
int v = get(pno, x+s.x, y+s.y) - values[x][y];
set(pno, x+s.x, y+s.y, clamp_in(clamp_method, v));
}
}
}
void add(int pno, Segment s, int[][] values, int clamp_method) {
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
int v = get(pno, x+s.x, y+s.y) + values[x][y];
set(pno, x+s.x, y+s.y, clamp_out(clamp_method, v));
}
}
}
}
================================================
FILE: predictions.pde
================================================
static final int PRED_SAD = -1;
static final int PRED_BSAD = -2;
static final int PRED_RANDOM = -3;
static final int PRED_NONE = 0;
static final int PRED_CORNER = 1;
static final int PRED_H = 2;
static final int PRED_V = 3;
static final int PRED_DC = 4;
static final int PRED_DCMEDIAN = 5;
static final int PRED_MEDIAN = 6;
static final int PRED_AVG = 7;
static final int PRED_TRUEMOTION = 8;
static final int PRED_PAETH = 9;
static final int PRED_LDIAG = 10;
static final int PRED_HV = 11;
static final int PRED_JPEGLS = 12;
static final int PRED_DIFF = 13;
static final int PRED_REF = 14;
static final int PRED_ANGLE = 15;
static final int MAX_PRED = 16;
int[][] predict(int prediction, Planes p, int pno, Segment s) {
switch(prediction) {
case PRED_CORNER:
return pred_gen(p, pno, s, 0);
case PRED_H:
return pred_gen(p, pno, s, 1);
case PRED_V:
return pred_gen(p, pno, s, 2);
case PRED_DC:
return pred_dc(p, pno, s);
case PRED_DCMEDIAN:
return pred_dcmedian(p, pno, s);
case PRED_MEDIAN:
return pred_median(p, pno, s);
case PRED_AVG:
return pred_avg(p, pno, s);
case PRED_TRUEMOTION:
return pred_truemotion(p, pno, s);
case PRED_PAETH:
return pred_paeth(p, pno, s);
case PRED_LDIAG:
return pred_ldiag(p, pno, s);
case PRED_HV:
return pred_hv(p, pno, s);
case PRED_JPEGLS:
return pred_jpegls(p, pno, s);
case PRED_DIFF:
return pred_diff(p, pno, s);
case PRED_REF:
return pred_ref(p, pno, s);
case PRED_ANGLE:
return pred_angle(p, pno, s);
case PRED_RANDOM:
return predict((int)random(MAX_PRED), p, pno, s);
case PRED_SAD:
return pred_sad(p, pno, s, true);
case PRED_BSAD:
return pred_sad(p, pno, s, false);
default:
return new int[s.size][s.size];
}
}
String predict_name(int prediction) {
switch(prediction) {
case PRED_CORNER:
return "PRED_CORNER";
case PRED_H:
return "PRED_H";
case PRED_V:
return "PRED_V";
case PRED_DC:
return "PRED_DC";
case PRED_DCMEDIAN:
return "PRED_DCMEDIAN";
case PRED_MEDIAN:
return "PRED_MEDIAN";
case PRED_AVG:
return "PRED_AVG";
case PRED_TRUEMOTION:
return "PRED_TRUEMOTION";
case PRED_PAETH:
return "PRED_PAETH";
case PRED_LDIAG:
return "PRED_LDIAG";
case PRED_HV:
return "PRED_HV";
case PRED_JPEGLS:
return "PRED_JPEGLS";
case PRED_DIFF:
return "PRED_DIFF";
case PRED_REF:
return "PRED_REF";
case PRED_ANGLE:
return "PRED_ANGLE";
case PRED_RANDOM:
return "PRED_RANDOM";
case PRED_SAD:
return "PRED_SAD";
case PRED_BSAD:
return "PRED_BSAD";
default:
return "PRED_NONE";
}
}
int getSAD(int[][] pred, Planes p, int pno, Segment s) {
int sum = 0;
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
sum+=abs(p.get(pno, s.x+x, s.y+y)-pred[x][y]);
}
}
return sum;
}
int[] pred_sad_stats = new int[MAX_PRED];
int[][] pred_sad(Planes p, int pno, Segment s, boolean do_sad) {
int[][] currres = null;
int currsad = do_sad ? MAX_INT : MIN_INT;
int currtype = -1;
for (int i=0; i<MAX_PRED; i++) {
int[][] res = predict(i, p, pno, s);
int sad = getSAD(res, p, pno, s);
if ( (do_sad && sad<currsad) || (!do_sad && sad>currsad) ) {
currsad = sad;
currtype = s.pred_type;
currres = res;
}
}
s.pred_type = currtype;
pred_sad_stats[currtype]++;
return currres;
}
int[][] pred_gen(Planes p, int pno, Segment s, int type) {
int[][] res = new int[s.size][s.size];
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
switch(type) {
case 0:
res[x][y] = p.get(pno, s.x-1, s.y-1);
break;
case 1:
res[x][y] = p.get(pno, s.x-1, s.y+y);
break;
case 2:
res[x][y] = p.get(pno, s.x+x, s.y-1);
break;
}
}
}
switch(type) {
case 0:
s.pred_type = PRED_CORNER;
break;
case 1:
s.pred_type = PRED_H;
break;
case 2:
s.pred_type = PRED_V;
break;
}
return res;
}
int getDC(Planes p, int pno, Segment s) {
int v = 0;
for (int i=0; i<s.size; i++) {
v += p.get(pno, s.x-1, s.y+i);
v += p.get(pno, s.x+i, s.y-1);
}
v += p.get(pno, s.x-1, s.y-1);
v /= (s.size+s.size+1);
return v;
}
int getMedian(int a, int b, int c) {
return max(min(a, b), min(max(a, b), c));
}
int[][] pred_dc(Planes p, int pno, Segment s) {
int[][] res = new int[s.size][s.size];
int c = getDC(p, pno, s);
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
res[x][y] = c;
}
}
s.pred_type = PRED_DC;
return res;
}
int[][] pred_dcmedian(Planes p, int pno, Segment s) {
int[][] res = new int[s.size][s.size];
int c = getDC(p, pno, s);
for (int x=0; x<s.size; x++) {
int v1 = p.get(pno, s.x+x, s.y-1);
for (int y=0; y<s.size; y++) {
int v2 = p.get(pno, s.x-1, s.y+y);
res[x][y] = getMedian(c, v1, v2);
}
}
s.pred_type = PRED_DCMEDIAN;
return res;
}
int[][] pred_median(Planes p, int pno, Segment s) {
int[][] res = new int[s.size][s.size];
int c = p.get(pno, s.x-1, s.y-1);
for (int x=0; x<s.size; x++) {
int v1 = p.get(pno, s.x+x, s.y-1);
for (int y=0; y<s.size; y++) {
int v2 = p.get(pno, s.x-1, s.y+y);
res[x][y] = getMedian(c, v1, v2);
}
}
s.pred_type = PRED_MEDIAN;
return res;
}
int[][] pred_truemotion(Planes p, int pno, Segment s) {
int[][] res = new int[s.size][s.size];
int c = p.get(pno, s.x-1, s.y-1);
for (int x=0; x<s.size; x++) {
int v1 = p.get(pno, s.x+x, s.y-1);
for (int y=0; y<s.size; y++) {
int v2 = p.get(pno, s.x-1, s.y+y);
res[x][y] = constrain(v1+v2-c, 0, 255);
}
}
s.pred_type = PRED_TRUEMOTION;
return res;
}
int[][] pred_paeth(Planes p, int pno, Segment s) {
int[][] res = new int[s.size][s.size];
int c = p.get(pno, s.x-1, s.y-1);
for (int x=0; x<s.size; x++) {
int v1 = p.get(pno, s.x+x, s.y-1);
for (int y=0; y<s.size; y++) {
int v2 = p.get(pno, s.x-1, s.y+y);
int pp = v1+v2-c;
int pa = abs(pp-v2);
int pb = abs(pp-v1);
int pc = abs(pp-c);
int v = ((pa<=pb) && (pa<=pc))?v2:(pb<=pc?v1:c);
res[x][y] = constrain(v, 0, 255);
}
}
s.pred_type = PRED_PAETH;
return res;
}
int[][] pred_avg(Planes p, int pno, Segment s) {
int[][] res = new int[s.size][s.size];
for (int x=0; x<s.size; x++) {
int v1 = p.get(pno, s.x+x, s.y-1);
for (int y=0; y<s.size; y++) {
int v2 = p.get(pno, s.x-1, s.y+y);
res[x][y] = (v1+v2)>>1;
}
}
s.pred_type = PRED_AVG;
return res;
}
int[][] pred_ldiag(Planes p, int pno, Segment s) {
int[][] res = new int[s.size][s.size];
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
int ss = x+y;
int xx = p.get(pno, s.x+(ss+1<s.size?ss+1:s.size-1), s.y-1);
int yy = p.get(pno, s.x-1, s.y+(ss<s.size?ss:s.size-1));
int c = ((x+1)*xx+(y+1)*yy)/(x+y+2);
res[x][y] = c;
}
}
s.pred_type = PRED_LDIAG;
return res;
}
int[][] pred_hv(Planes p, int pno, Segment s) {
int[][] res = new int[s.size][s.size];
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
int c;
if (x>y) c = p.get(pno, s.x+x, s.y-1);
else if (y>x) c = p.get(pno, s.x-1, s.y+y);
else c = (p.get(pno, s.x+x, s.y-1) + p.get(pno, s.x-1, s.y+y)) >> 1;
res[x][y] = c;
}
}
s.pred_type = PRED_HV;
return res;
}
int[][] pred_jpegls(Planes p, int pno, Segment s) {
int[][] res = new int[s.size][s.size];
for (int x=0; x<s.size; x++) {
int c = p.get(pno, s.x+x-1, s.y-1);
int a = p.get(pno, s.x+x, s.y-1);
for (int y=0; y<s.size; y++) {
int b = p.get(pno, s.x-1, s.y+y);
int v;
if (c>=max(a, b)) v = min(a, b);
else if (c<=min(a, b)) v=max(a, b);
else v = a+b-c;
res[x][y] = v;
}
}
s.pred_type = PRED_JPEGLS;
return res;
}
int[][] pred_diff(Planes p, int pno, Segment s) {
int[][] res = new int[s.size][s.size];
for (int x=0; x<s.size; x++) {
int x1 = p.get(pno, s.x+x, s.y-1);
int x2 = p.get(pno, s.x+x, s.y-2);
for (int y=0; y<s.size; y++) {
int y1 = p.get(pno, s.x-1, s.y+y);
int y2 = p.get(pno, s.x-2, s.y+y);
int v = constrain((y2+y2-y1+x2+x2-x1)>>1, 0, 255);
res[x][y] = v;
}
}
s.pred_type = PRED_DIFF;
return res;
}
int[][] findBestRef(Planes p, int pno, Segment s) {
int currsad = MAX_INT;
int[][] currres = null;
for (int i=0; i<45; i++) {
int[][] res = new int[s.size][s.size];
int xx = (int)random(-s.size, s.x);
int yy;
if (xx<s.x-s.size) {
yy = (int)random(-s.size, s.y);
} else {
yy = (int)random(-s.size, s.y-s.size);
}
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
res[x][y] = p.get(pno, xx+x, yy+y);
}
}
int sad = getSAD(res, p, pno, s);
if (sad<currsad) {
currres = res;
currsad = sad;
s.refx = xx;
s.refy = yy;
}
}
return currres;
}
int[][] pred_ref(Planes p, int pno, Segment s) {
s.pred_type = PRED_REF;
if (s.refx == Short.MAX_VALUE || s.refy == Short.MAX_VALUE) {
return findBestRef(p, pno, s);
} else {
int[][] res = new int[s.size][s.size];
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
res[x][y] = p.get(pno, s.refx+x, s.refy+y);
}
}
return res;
}
}
PVector getAngleRef(int i, int x, int y, float a, int w) {
float xx=-1;
float yy=-1;
switch(i%3) {
case 0:
{
float v = (w-y-1)+x*a;
xx = (v-w)/a;
yy = (w-1-a-v);
break;
}
case 1:
{
float v = (w-x-1)+y*a;
yy = (v-w)/a;
xx = (w-1-a-v);
break;
}
case 2:
{
float v = x+y*a;
yy = -1.0;
xx = v + a;
break;
}
}
if (xx>yy)
return new PVector(round(xx), -1);
else
return new PVector(-1, round(yy));
}
int[][] findBestAngle(Planes p, int pno, Segment s) {
float stepa = 1.0/min(16, s.size);
int[][] currres = null;
int currsad = MAX_INT;
for (int i=0; i<3; i++) {
for (float a=0; a<1.0; a+=stepa) {
float aa = ((int)(a*0x8000))/(float)0x8000;
int[][] res = new int[s.size][s.size];
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
PVector angref = getAngleRef(i, x, y, aa, s.size);
int xx = angref.x >= s.size ? s.size-1 : (int)angref.x;
res[x][y] = p.get(pno, xx+s.x, (int)angref.y+s.y);
}
}
int sad = getSAD(res, p, pno, s);
if (sad<currsad) {
currres = res;
currsad = sad;
s.angle = a;
s.refa = i;
}
}
}
return currres;
}
int[][] pred_angle(Planes p, int pno, Segment s) {
s.pred_type = PRED_ANGLE;
if (s.angle<0 || s.refa<0) {
return findBestAngle(p, pno, s);
} else {
int[][] res = new int[s.size][s.size];
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
PVector angref = getAngleRef(s.refa, x, y, s.angle, s.size);
int xx = angref.x >= s.size ? s.size-1 : (int)angref.x;
res[x][y] = p.get(pno, xx+s.x, (int)angref.y+s.y);
}
}
return res;
}
}
================================================
FILE: quantization.pde
================================================
void quantize(Planes planes, int p, Segment s, float val, boolean forward) {
if (val > 1) {
for (int x=0; x<s.size; x++) {
for (int y=0; y<s.size; y++) {
float col = planes.get(p, x+s.x, y+s.y);
if (forward)
col = col / val;
else
col = col * val;
planes.set(p, x+s.x, y+s.y, (int)round(col));
}
}
}
}
================================================
FILE: segmentation.pde
================================================
class Segment {
int x,y,size;
// needed for prediction
int pred_type = PRED_NONE;
float angle = -1;
int refa = -1;
int refx = Short.MAX_VALUE; /// set to -1 if you want grid effect
int refy = Short.MAX_VALUE; /// set to -1 if you want grid effect
public String toString() {
return "x="+x+", y="+y+ ", size=" + size;
}
}
ArrayList<Segment> makeSegmentation(DefaultBitOutput segm_out, Planes p, int pno, int min_size, int max_size, float thr) throws IOException {
ArrayList<Segment> s = new ArrayList<Segment>();
segment(segm_out, s, p, pno, 0, 0, max(p.ww,p.hh), max(1,min_size), min(512,max_size), thr);
return s;
}
void segment(DefaultBitOutput segm_out, ArrayList<Segment> s, Planes p, int pno, int x, int y, int size, int min_size, int max_size, float thr) throws IOException {
if(x>=p.w || y>=p.h) return;
float currStdDev = calcStdDev(p, pno, x, y, size);
if(size>max_size || (size>min_size && currStdDev>thr)) {
segm_out.writeBoolean(true);
int mid = size/2;
segment(segm_out,s,p,pno,x,y,mid,min_size,max_size,thr);
segment(segm_out,s,p,pno,x+mid,y,mid,min_size,max_size,thr);
segment(segm_out,s,p,pno,x,y+mid,mid,min_size,max_size,thr);
segment(segm_out,s,p,pno,x+mid,y+mid,mid,min_size,max_size,thr);
} else {
segm_out.writeBoolean(false);
Segment segm = new Segment();
segm.x = x;
segm.y = y;
segm.size = size;
s.add(segm);
}
}
ArrayList<Segment> readSegmentation(DefaultBitInput segm_in, Planes p) {
ArrayList<Segment> s = new ArrayList<Segment>();
segment(segm_in, s, p, 0, 0, max(p.ww,p.hh));
return s;
}
void segment(DefaultBitInput segm_in, ArrayList<Segment> s, Planes p, int x, int y, int size) {
if(x>=p.w || y>=p.h) return;
boolean decision;
try {
decision = segm_in.readBoolean();
} catch (Exception e) {
decision = false;
}
if(decision && size > 2) {
int mid = size/2;
segment(segm_in,s,p,x,y,mid);
segment(segm_in,s,p,x+mid,y,mid);
segment(segm_in,s,p,x,y+mid,mid);
segment(segm_in,s,p,x+mid,y+mid,mid);
} else {
Segment segm = new Segment();
segm.x = x;
segm.y = y;
segm.size = size;
s.add(segm);
}
}
float calcStdDev(Planes planes, int pno, int x, int y, int size) {
int limit = (int)(max(0.1*sq(size),4));
float A = 0;
float Q = 0;
for(int k=1;k<=limit;k++) {
int posx = (int)random(size);
int posy = (int)random(size);
int xk = planes.get(pno,x+posx,y+posy);
float oldA = A;
A+=(xk-A)/k;
Q+=(xk-oldA)*(xk-A);
}
return sqrt(Q/(limit-1));
}
================================================
FILE: transformation.pde
================================================
import jwave.transforms.*;
import jwave.transforms.wavelets.Wavelet;
import jwave.transforms.wavelets.WaveletBuilder;
import jwave.Transform;
import jwave.TransformBuilder;
import jwave.compressions.Compressor;
import jwave.compressions.CompressorMagnitude;
import jwave.compressions.CompressorPeaksAverage;
import jwave.exceptions.JWaveException;
final static int TRANSTYPE_RANDOM = -1;
final static int TRANSTYPE_FWT = 0;
final static int TRANSTYPE_WPT = 1;
//final static int TRANSTYPE_SWT = 2;
final static int TRANSTYPENO = 2;
WaveletTransform createTransform(int transtype, Wavelet wavelet) {
switch (transtype) {
case TRANSTYPE_FWT:
return new FastWaveletTransform(wavelet);
case TRANSTYPE_WPT:
return new WaveletPacketTransform(wavelet);
// case TRANSTYPE_SWT:
// return new ShiftingWaveletTransform(wavelet);
default:
return createTransform((int)random(TRANSTYPENO), wavelet);
}
}
final static int WAVELETNO = 68;
final static int WAVELET_RANDOM = -1;
final static int WAVELET_NONE = 0;
final static int HAARORTHOGONAL = 1;
final static int BIORTHOGONAL11 = 2;
final static int BIORTHOGONAL13 = 3;
final static int BIORTHOGONAL15 = 4;
final static int BIORTHOGONAL22 = 5;
final static int BIORTHOGONAL24 = 6;
final static int BIORTHOGONAL26 = 7;
final static int BIORTHOGONAL28 = 8;
final static int BIORTHOGONAL31 = 9;
final static int BIORTHOGONAL33 = 10;
final static int BIORTHOGONAL35 = 11;
final static int BIORTHOGONAL37 = 12;
final static int BIORTHOGONAL39 = 13;
final static int BIORTHOGONAL44 = 14;
final static int BIORTHOGONAL55 = 15;
final static int BIORTHOGONAL68 = 16;
final static int COIFLET1 = 17;
final static int COIFLET2 = 18;
final static int COIFLET3 = 19;
final static int COIFLET4 = 20;
final static int COIFLET5 = 21;
final static int SYMLET2 = 22;
final static int SYMLET3 = 23;
final static int SYMLET4 = 24;
final static int SYMLET5 = 25;
final static int SYMLET6 = 26;
final static int SYMLET7 = 27;
final static int SYMLET8 = 28;
final static int SYMLET9 = 29;
final static int SYMLET10 = 30;
final static int SYMLET11 = 31;
final static int SYMLET12 = 32;
final static int SYMLET13 = 33;
final static int SYMLET14 = 34;
final static int SYMLET15 = 35;
final static int SYMLET16 = 36;
final static int SYMLET17 = 37;
final static int SYMLET18 = 38;
final static int SYMLET19 = 39;
final static int SYMLET20 = 40;
final static int LEGENDRE1 = 41;
final static int LEGENDRE2 = 42;
final static int LEGENDRE3 = 43;
final static int DAUBECHIES2 = 44;
final static int DAUBECHIES3 = 45;
final static int DAUBECHIES4 = 46;
final static int DAUBECHIES5 = 47;
final static int DAUBECHIES6 = 48;
final static int DAUBECHIES7 = 49;
final static int DAUBECHIES8 = 50;
final static int DAUBECHIES9 = 51;
final static int DAUBECHIES10 = 52;
final static int DAUBECHIES11 = 53;
final static int DAUBECHIES12 = 54;
final static int DAUBECHIES13 = 55;
final static int DAUBECHIES14 = 56;
final static int DAUBECHIES15 = 57;
final static int DAUBECHIES16 = 58;
final static int DAUBECHIES17 = 59;
final static int DAUBECHIES18 = 60;
final static int DAUBECHIES19 = 61;
final static int DAUBECHIES20 = 62;
final static int BATTLE23 = 63;
final static int CDF53 = 64;
final static int CDF97 = 65;
final static int DISCRETEMAYER = 66;
final static int HAAR = 67;
Wavelet createWavelet(int wavelettype) {
switch(wavelettype) {
case HAAR:
return new Haar1();
case HAARORTHOGONAL:
return new Haar1Orthogonal();
case DAUBECHIES2:
return new Daubechies2();
case DAUBECHIES3:
return new Daubechies3();
case DAUBECHIES4:
return new Daubechies4();
case DAUBECHIES5:
return new Daubechies5();
case DAUBECHIES6:
return new Daubechies6();
case DAUBECHIES7:
return new Daubechies7();
case DAUBECHIES8:
return new Daubechies8();
case DAUBECHIES9:
return new Daubechies9();
case DAUBECHIES10:
return new Daubechies10();
case DAUBECHIES11:
return new Daubechies11();
case DAUBECHIES12:
return new Daubechies12();
case DAUBECHIES13:
return new Daubechies13();
case DAUBECHIES14:
return new Daubechies14();
case DAUBECHIES15:
return new Daubechies15();
case DAUBECHIES16:
return new Daubechies16();
case DAUBECHIES17:
return new Daubechies17();
case DAUBECHIES18:
return new Daubechies18();
case DAUBECHIES19:
return new Daubechies19();
case DAUBECHIES20:
return new Daubechies20();
case COIFLET1:
return new Coiflet1();
case COIFLET2:
return new Coiflet2();
case COIFLET3:
return new Coiflet3();
case COIFLET4:
return new Coiflet4();
case COIFLET5:
return new Coiflet5();
case LEGENDRE1:
return new Legendre1();
case LEGENDRE2:
return new Legendre2();
case LEGENDRE3:
return new Legendre3();
case SYMLET2:
return new Symlet2();
case SYMLET3:
return new Symlet3();
case SYMLET4:
return new Symlet4();
case SYMLET5:
return new Symlet5();
case SYMLET6:
return new Symlet6();
case SYMLET7:
return new Symlet7();
case SYMLET8:
return new Symlet8();
case SYMLET9:
return new Symlet9();
case SYMLET10:
return new Symlet10();
case SYMLET11:
return new Symlet11();
case SYMLET12:
return new Symlet12();
case SYMLET13:
return new Symlet13();
case SYMLET14:
return new Symlet14();
case SYMLET15:
return new Symlet15();
case SYMLET16:
return new Symlet16();
case SYMLET17:
return new Symlet17();
case SYMLET18:
return new Symlet18();
case SYMLET19:
return new Symlet19();
case SYMLET20:
return new Symlet20();
case BIORTHOGONAL11:
return new BiOrthogonal11();
case BIORTHOGONAL13:
return new BiOrthogonal13();
case BIORTHOGONAL15:
return new BiOrthogonal15();
case BIORTHOGONAL22:
return new BiOrthogonal22();
case BIORTHOGONAL24:
return new BiOrthogonal24();
case BIORTHOGONAL26:
return new BiOrthogonal26();
case BIORTHOGONAL28:
return new BiOrthogonal28();
case BIORTHOGONAL31:
return new BiOrthogonal31();
case BIORTHOGONAL33:
return new BiOrthogonal33();
case BIORTHOGONAL35:
return new BiOrthogonal35();
case BIORTHOGONAL37:
return new BiOrthogonal37();
case BIORTHOGONAL39:
return new BiOrthogonal39();
case BIORTHOGONAL44:
return new BiOrthogonal44();
case BIORTHOGONAL55:
return new BiOrthogonal55();
case BIORTHOGONAL68:
return new BiOrthogonal68();
case DISCRETEMAYER:
return new DiscreteMayer();
case BATTLE23:
return new Battle23();
case CDF53:
return new CDF53();
case CDF97:
return new CDF97();
default:
return createWavelet((int)random(1, WAVELETNO));
}
}
Wavelet[] waveletTab = new Wavelet[WAVELETNO];
Wavelet getWavelet(int wavelettype) {
if (wavelettype>=0 && wavelettype<WAVELETNO) {
Wavelet w = waveletTab[wavelettype];
if (w == null) {
w = createWavelet(wavelettype);
waveletTab[wavelettype] = w;
}
return w;
} else {
return createWavelet(-1);
}
}
gitextract_hbgmkhg3/ ├── .gitignore ├── GLIC.pde ├── GUI.pde ├── LICENSE ├── README.md ├── code/ │ ├── JWave.jar │ └── bit-io-1.3.7.jar ├── codec.pde ├── colorspaces.pde ├── encoding.pde ├── planes.pde ├── predictions.pde ├── presets/ │ ├── 0ddangl3 │ ├── 0rg4n1c-___ │ ├── 0rg4n1c-t1ny4ngl3z │ ├── 0rg4n1c-tr1angl3 │ ├── 0rg4n1c-tr1f0rc3 │ ├── 0rg4n1c-tr33 │ ├── 0rg4n1c-v1n3z │ ├── 1211 │ ├── 1422 │ ├── 1amblu │ ├── 1llu510n │ ├── 1ns1t3 │ ├── 2211 │ ├── 221122 │ ├── 3255 │ ├── 3ra53r │ ├── 5pl1tz │ ├── 5um7h1ng │ ├── 8-b1tz │ ├── 8l33dm3 │ ├── abstract_expressionism │ ├── ayy │ ├── beautifulwave │ ├── bi0g4n1c │ ├── bispham1 │ ├── bl33dyl1n3z │ ├── bl33dyl1n3z-2 │ ├── black+whiteblockyglitch │ ├── blasted │ ├── bleeding_blocks │ ├── blocks │ ├── blockssmoll │ ├── blops │ ├── blops2 │ ├── brokens7r1p3z │ ├── burn │ ├── c0m1c │ ├── cartoon │ ├── ch3ss │ ├── channels │ ├── chock-a-block │ ├── colour_boxy_glitch │ ├── colour_glow │ ├── colour_mess │ ├── colour_mess2 │ ├── colour_waves │ ├── colour_waves_2 │ ├── colour_waves_3 │ ├── colour_waves_sharp │ ├── colour_waves_sharp2 │ ├── colourful_disturbances │ ├── confetti │ ├── constrctivist │ ├── constrctivist2 │ ├── constrctivist_minimal │ ├── cr0550v3r │ ├── cubism │ ├── cute blocks │ ├── d1ffu510n │ ├── d1ffu510nz │ ├── d3cayy-d │ ├── d3cayy-e │ ├── default │ ├── diagonalcolourbleed │ ├── diagonalcolourbleed2 │ ├── diagonalmess │ ├── erase_horizontal │ ├── erase_vertical │ ├── g0dh34d-d │ ├── g0dh34d-e │ ├── ghost │ ├── gif1 │ ├── gif2 │ ├── haze │ ├── haze2 │ ├── high_compression │ ├── idk │ ├── jpegls1 │ ├── lightblur │ ├── lightblur2 │ ├── lines │ ├── liquiblock │ ├── lmao │ ├── m1n1m3l0l │ ├── minimaldiag │ ├── mthr │ ├── n07h1ng2c │ ├── n07h1ng2c-2 │ ├── neato │ ├── ordered_destruction │ ├── ordered_destruction_2 │ ├── p1xx1 │ ├── pcool │ ├── pls │ ├── preset 38 │ ├── progressive │ ├── scanlined │ ├── shinybright │ ├── sk0011rgb │ ├── sk001xyz │ ├── sk0021xyz │ ├── sk00244xyz │ ├── sk00244xyz2 │ ├── sk1211 │ ├── sk1723 │ ├── sk221122 │ ├── sk3255 │ ├── squareglitchfromthebottom │ ├── thousandsofblocks │ ├── ts01 │ ├── uncubizm │ ├── vv01 │ ├── vv02 │ ├── vv03 │ ├── vv04 │ ├── vv05 │ ├── vv06 │ ├── vv07 │ ├── vv08 │ ├── vv09 │ ├── vv10 │ ├── vv11 │ ├── vv12 │ ├── vv13 │ ├── vv14 │ ├── vv15 │ ├── vv16 │ ├── vv17 │ ├── vv18 │ ├── vv19 │ ├── vv20 │ ├── vv21 │ ├── vv22 │ ├── vv23 │ ├── vv24 │ ├── vv25 │ ├── wat │ ├── wavydown │ ├── wavydownbigger │ ├── web_p_like │ ├── webp │ ├── wot │ ├── wtf │ └── wtf2 ├── quantization.pde ├── segmentation.pde └── transformation.pde
Condensed preview — 159 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (102K chars).
[
{
"path": ".gitignore",
"chars": 158,
"preview": ".DS_Store\napplet\napplication.linux32\napplication.linux64\napplication.windows32\napplication.windows64\napplication.macosx\n"
},
{
"path": "GLIC.pde",
"chars": 3287,
"preview": "// GLIC - GLitch Image Codec, ready for databending\n\n//////////////////// Config\n\n// Hidden stuff (not in GUI)\n\n// Press"
},
{
"path": "GUI.pde",
"chars": 20519,
"preview": "import controlP5.*;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\nControlP5 cp5;\n\nCheckBox separate_channel"
},
{
"path": "LICENSE",
"chars": 1068,
"preview": "MIT License\n\nCopyright (c) 2017 GlitchCodec\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
},
{
"path": "README.md",
"chars": 139,
"preview": "# GLIC\nGlitch Image Codec\n\nDocumentation: https://docs.google.com/document/d/1cdJvEmSKNAkzkU0dFUa-kb_QJB2ISQg-QfCqpHLFlc"
},
{
"path": "codec.pde",
"chars": 26427,
"preview": "import com.github.jinahya.bit.io.*;\nimport java.io.*;\n\nboolean do_skip_header = false;\n\nclass CodecConfig {\n // Color s"
},
{
"path": "colorspaces.pde",
"chars": 19221,
"preview": "final static int COLORSPACES = 16;\n\nfinal static int OHTA = 0;\n// RGB == 1; defined in processing\nfinal static int CMY ="
},
{
"path": "encoding.pde",
"chars": 372,
"preview": "// final encoding\n\nfinal static int ENCODING_RAW = 0;\nfinal static int ENCODING_PACKED = 1;\nfinal static int ENCODING_RL"
},
{
"path": "planes.pde",
"chars": 4449,
"preview": "final static float LOG2 = log(2.0);\n\nfinal static int CLAMP_NONE = 0;\nfinal static int CLAMP_MOD256 = 1;\n\nint clamp_in(i"
},
{
"path": "predictions.pde",
"chars": 11277,
"preview": "static final int PRED_SAD = -1;\nstatic final int PRED_BSAD = -2;\nstatic final int PRED_RANDOM = -3;\n\nstatic final int PR"
},
{
"path": "quantization.pde",
"chars": 394,
"preview": "void quantize(Planes planes, int p, Segment s, float val, boolean forward) {\r\n if (val > 1) {\r\n for (int x=0; x<s.si"
},
{
"path": "segmentation.pde",
"chars": 2597,
"preview": "class Segment {\n int x,y,size;\n \n // needed for prediction\n int pred_type = PRED_NONE;\n float angle = -1;\n int ref"
},
{
"path": "transformation.pde",
"chars": 7119,
"preview": "import jwave.transforms.*;\nimport jwave.transforms.wavelets.Wavelet;\nimport jwave.transforms.wavelets.WaveletBuilder;\nim"
}
]
// ... and 146 more files (download for full content)
About this extraction
This page contains the full source code of the GlitchCodec/GLIC GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 159 files (94.8 KB), approximately 34.3k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.