// compression parameters int simplification = 4; float switchesInfluence = 50.0f; float clusterImpactOnDetailRemoval = 2.0f; float clusterImpactOnDetailThreshold = 2.0f; float entropyDynamic = 0.7f; float entropyMargin = 0.2f; // decompression parameters int crossLeakSize = 2; float blurPass = 0.5f; int pointAlpha = 0xD0; int pointSize = 2; PImage previousIm; PImage im; boolean recordEntireFile = false; boolean[][][] lastChange; double[][][] changeEntropy; double[][][] changeDirection; boolean[][] lastAnswer; PImage oldSimplifiedImage; int currentFrame=0; ArrayList rleStarts = new ArrayList(); ArrayList finalBits = new ArrayList(); void setup() { frameRate(10); im = loadImage(dataPath("input/"+nf(0, 5)+".png")); size (im.width, im.height); background(0x80); PImage simplifiedImage = createImage(ceil(width/simplification), ceil(height/simplification), RGB); lastChange = new boolean[im.width][im.height][3]; changeEntropy = new double[im.width][im.height][3]; changeDirection = new double[im.width][im.height][3]; lastAnswer = new boolean[simplifiedImage.width][simplifiedImage.height]; for (int x=0; xred(previousIm.get(realX, realY)); if (currentModif==1) thisQuestion = green(simplifiedImage.get(x, y))>green(previousIm.get(realX, realY)); if (currentModif==2) thisQuestion = blue(simplifiedImage.get(x, y))>blue(previousIm.get(realX, realY)); lastAnswer[x][y] = thisQuestion; changeDirection[realX][realY][currentModif] = (changeDirection[realX][realY][currentModif]/2.0f) + (thisQuestion?0.5f:-0.5f); changeEntropy[realX][realY][currentModif] = changeEntropy[realX][realY][currentModif]*entropyDynamic+(1-abs((float)changeDirection[realX][realY][currentModif]))*(1.0f-entropyDynamic); changeEntropy[realX][realY][currentModif] = constrain((float)changeEntropy[realX][realY][currentModif], entropyMargin, 1.0f-entropyMargin); lastChange[realX][realY][currentModif] = thisQuestion; } } PVector[] rlePosition = new PVector[simplifiedImage.width*simplifiedImage.height]; boolean rleDone = false; int rleStack = 0; int rleX=0; int rleY=0; for (int i=0; i=simplifiedImage.width) { rleX=rleX-simplifiedImage.height+1; rleY+=simplifiedImage.height; while (rleX<0||rleY>=simplifiedImage.height) { rleX+=1; rleY-=1; } } } int nbChanges=0; int smallestDetailSize = 0; boolean[] partOfDones = new boolean[rlePosition.length]; for (int i=0; inbStorageBits-3; nbStorageBits++) { boolean lastValue=true; ArrayList values = new ArrayList(); int highestValue = 0; double averageValue = 0; for (int i=0; i(values.size()*nbStorageBits)) { bestFinalByteLength=(values.size()*nbStorageBits); bestNbStorageBits=nbStorageBits; } } println("chosen final bytes length before rle = "+bestFinalByteLength); int maxChanges = floor((float)bestFinalByteLength/clusterImpactOnDetailRemoval); int detailThreshold = floor(bestNbStorageBits/clusterImpactOnDetailThreshold); while (smallestDetailSize=maxChanges*4) rleStarts.remove(0); nbChanges++; } } println("number of details removed : "+nbChanges); for (int x=0; x=0) point(realX-(i+1), realY); if (realY-(i+1)>=0) point(realX, realY-(i+1)); if (realX+(i+1)0.8f) { fill(c); noStroke(); rect(x*simplification, y*simplification, simplification, simplification); }*/ oldSimplifiedImage.set(x, y, c); } } filter(BLUR, blurPass); ArrayList bestValues = new ArrayList(); for (int nbStorageBits = 2; nbStorageBits<=32 && bestNbStorageBits>nbStorageBits-3; nbStorageBits++) { boolean lastValue=true; ArrayList values = new ArrayList(); int highestValue = 0; double averageValue = 0; values.add(nbStorageBits); for (int i=0; i