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 Iteration number: "+i+"/"+iterate_count); encode_button(); keep_image(); } } else if (char(keyCode) == 'Y') { if (img != null) { for (int i=0; i[] 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 addToTab(Tab t) { HashMap h = new HashMap(); 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 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 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 toHashMap() { HashMap 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 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 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 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 (curFramemx) 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 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 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 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 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; xx0) 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 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 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 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 s) { try { int idx=0; for (Segment segm : s) { for (int x=0; x 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 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 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 s) throws IOException { for (Segment segm : s) { for (int x=0; x 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 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 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> 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> 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 || 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=0 && ycurrsad) ) { 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>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; xy) 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=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>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 (xxyy) 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 ? 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= 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