@ -0,0 +1,97 @@ |
|||
pragma circom 2.0.0; |
|||
|
|||
include "utils/row_hasher.circom"; |
|||
include "utils/pixels.circom"; |
|||
include "node_modules/circomlib/circuits/bitify.circom"; |
|||
|
|||
|
|||
template GrayscaleChecker(n) { |
|||
signal input orig[n][3]; |
|||
signal input gray[n]; |
|||
|
|||
signal output n_check; |
|||
|
|||
component lt[n][2]; |
|||
|
|||
for (var i = 0; i < n; i++) { |
|||
var inter = 299 * orig[i][0] + 587 * orig[i][1] + 114 * orig[i][2]; |
|||
|
|||
lt[i][0] = LessEqThan(18); |
|||
lt[i][1] = LessEqThan(18); |
|||
|
|||
lt[i][0].in[1] <== 1000; |
|||
lt[i][0].in[0] <== inter - 1000 * gray[i]; |
|||
lt[i][0].out === 1; |
|||
|
|||
lt[i][1].in[1] <== 1000; |
|||
lt[i][1].in[0] <== 1000 * gray[i] - inter; |
|||
lt[i][1].out === 1; |
|||
} |
|||
n_check <== n; |
|||
} |
|||
|
|||
template GrayScale(width){ |
|||
|
|||
signal input original[width]; |
|||
signal input transformed[width]; |
|||
|
|||
component decompressor[width]; |
|||
component decompressor_grey[width]; |
|||
component greychecker[width]; |
|||
|
|||
for (var j=0; j<width; j++) { |
|||
decompressor[j] = Decompressor(); |
|||
decompressor[j].in <== original[j]; |
|||
|
|||
decompressor_grey[j] = DecompressorGrey(); |
|||
decompressor_grey[j].in <== transformed[j]; |
|||
|
|||
greychecker[j] = GrayscaleChecker(10); |
|||
greychecker[j].orig <== decompressor[j].out; |
|||
greychecker[j].gray <== decompressor_grey[j].out; |
|||
} |
|||
|
|||
} |
|||
|
|||
template GrayScaleHash(width){ |
|||
signal input ivc_input[2]; |
|||
// signal input prev_orig_hash; |
|||
// signal input prev_gray_hash; |
|||
signal output ivc_output[2]; |
|||
// signal output next_orig_hash; |
|||
// signal output next_gray_hash; |
|||
|
|||
// Private inputs |
|||
signal input external_inputs [2 * width]; |
|||
|
|||
signal row_orig [width]; |
|||
signal row_tran [width]; |
|||
|
|||
for (var i = 0; i < width; i++) { |
|||
row_orig[i] <== external_inputs[i]; |
|||
row_tran[i] <== external_inputs[i + width]; |
|||
} |
|||
|
|||
component orig_row_hasher = RowHasher(width); |
|||
component gray_row_hasher = RowHasher(width); |
|||
component orig_hasher = Hasher(2); |
|||
component gray_hasher = Hasher(2); |
|||
|
|||
orig_row_hasher.img <== row_orig; |
|||
orig_hasher.values[0] <== ivc_input[0]; // prev_orig_hash |
|||
orig_hasher.values[1] <== orig_row_hasher.hash; |
|||
ivc_output[0] <== orig_hasher.hash; // next_orig_hash |
|||
|
|||
gray_row_hasher.img <== row_tran; |
|||
gray_hasher.values[0] <== ivc_input[1]; // prev_gray_hash |
|||
gray_hasher.values[1] <== gray_row_hasher.hash; |
|||
ivc_output[1] <== gray_hasher.hash; // next_grey_hash |
|||
|
|||
// grayscale code here ... |
|||
component checker = GrayScale(width); |
|||
checker.original <== row_orig; |
|||
checker.transformed <== row_tran; |
|||
|
|||
} |
|||
|
|||
component main { public [ivc_input] } = GrayScaleHash(128); |
@ -0,0 +1,9 @@ |
|||
{ |
|||
"name": "circom", |
|||
"version": "1.0.0", |
|||
"main": "index.js", |
|||
"license": "MIT", |
|||
"dependencies": { |
|||
"circomlib": "^2.0.5" |
|||
} |
|||
} |
@ -0,0 +1,153 @@ |
|||
pragma circom 2.0.0; |
|||
include "../node_modules/circomlib/circuits/bitify.circom"; |
|||
include "../node_modules/circomlib/circuits/mux1.circom"; |
|||
include "../node_modules/circomlib/circuits/comparators.circom"; |
|||
|
|||
template Decompressor(){ |
|||
signal input in; |
|||
signal output out[10][3]; |
|||
|
|||
component toBits = Num2Bits(240); |
|||
component toNum[10][3]; |
|||
|
|||
toBits.in <== in; |
|||
|
|||
for (var i=0; i<10; i++) { |
|||
for (var j=0; j<3; j++) { |
|||
toNum[i][j] = Bits2Num(8); |
|||
toNum[i][j].in[0] <== toBits.out[i*24+j*8]; |
|||
toNum[i][j].in[1] <== toBits.out[i*24+j*8+1]; |
|||
toNum[i][j].in[2] <== toBits.out[i*24+j*8+2]; |
|||
toNum[i][j].in[3] <== toBits.out[i*24+j*8+3]; |
|||
toNum[i][j].in[4] <== toBits.out[i*24+j*8+4]; |
|||
toNum[i][j].in[5] <== toBits.out[i*24+j*8+5]; |
|||
toNum[i][j].in[6] <== toBits.out[i*24+j*8+6]; |
|||
toNum[i][j].in[7] <== toBits.out[i*24+j*8+7]; |
|||
out[i][j] <== toNum[i][j].out; |
|||
} |
|||
} |
|||
} |
|||
|
|||
template DecompressorKernel(kernel_size){ |
|||
signal input in; |
|||
signal output out[kernel_size][kernel_size]; |
|||
|
|||
component toBits = Num2Bits(kernel_size*kernel_size*9); // 8-bit value, 1-bit sign |
|||
component toNum[kernel_size][kernel_size]; |
|||
component selector[kernel_size][kernel_size]; |
|||
|
|||
toBits.in <== in; |
|||
|
|||
for (var i=0; i<kernel_size; i++) { |
|||
for (var j=0; j<kernel_size; j++) { |
|||
toNum[i][j] = Bits2Num(8); |
|||
toNum[i][j].in[0] <== toBits.out[i*kernel_size*9+j*9]; |
|||
toNum[i][j].in[1] <== toBits.out[i*kernel_size*9+j*9+1]; |
|||
toNum[i][j].in[2] <== toBits.out[i*kernel_size*9+j*9+2]; |
|||
toNum[i][j].in[3] <== toBits.out[i*kernel_size*9+j*9+3]; |
|||
toNum[i][j].in[4] <== toBits.out[i*kernel_size*9+j*9+4]; |
|||
toNum[i][j].in[5] <== toBits.out[i*kernel_size*9+j*9+5]; |
|||
toNum[i][j].in[6] <== toBits.out[i*kernel_size*9+j*9+6]; |
|||
toNum[i][j].in[7] <== toBits.out[i*kernel_size*9+j*9+7]; |
|||
|
|||
var value = toNum[i][j].out; // value |
|||
var sign = toBits.out[i*kernel_size*9+j*9+8]; // sign |
|||
|
|||
selector[i][j] = Mux1(); |
|||
selector[i][j].c[0] <== value; |
|||
selector[i][j].c[1] <== 0 - value; |
|||
selector[i][j].s <== sign; |
|||
|
|||
out[i][j] <== selector[i][j].out; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
template DecompressorGrey(){ |
|||
signal input in; |
|||
signal output out[10]; |
|||
|
|||
component toBits = Num2Bits(240); |
|||
component toNum[10]; |
|||
|
|||
toBits.in <== in; |
|||
|
|||
for (var i=0; i<10; i++) { |
|||
var j=0; |
|||
toNum[i] = Bits2Num(8); |
|||
toNum[i].in[0] <== toBits.out[i*24]; |
|||
toNum[i].in[1] <== toBits.out[i*24+1]; |
|||
toNum[i].in[2] <== toBits.out[i*24+2]; |
|||
toNum[i].in[3] <== toBits.out[i*24+3]; |
|||
toNum[i].in[4] <== toBits.out[i*24+4]; |
|||
toNum[i].in[5] <== toBits.out[i*24+5]; |
|||
toNum[i].in[6] <== toBits.out[i*24+6]; |
|||
toNum[i].in[7] <== toBits.out[i*24+7]; |
|||
out[i] <== toNum[i].out; |
|||
} |
|||
} |
|||
|
|||
|
|||
template CompressorCrop(){ |
|||
signal input in[10]; |
|||
signal output out; |
|||
|
|||
component toNum = Bits2Num(240); |
|||
component toBits[10]; |
|||
|
|||
for (var i=0; i<10; i++) { |
|||
toBits[i] = Num2Bits(24); |
|||
toBits[i].in <== in[i]; |
|||
for (var j=0; j<24; j++) { |
|||
toNum.in[i*24+j] <== toBits[i].out[j]; |
|||
} |
|||
} |
|||
out <== toNum.out; |
|||
} |
|||
|
|||
template DecompressorCrop(){ |
|||
signal input in; |
|||
signal output out[10]; |
|||
|
|||
component decomp = DecompressorGrey(); |
|||
|
|||
decomp.in <== in; |
|||
out <== decomp.out; |
|||
} |
|||
|
|||
template CropInfoDecompressor(){ |
|||
|
|||
signal input in; |
|||
signal output row_index; |
|||
signal output x; |
|||
signal output y; |
|||
|
|||
component toBits = Num2Bits(36); |
|||
component toNumX = Bits2Num(12); |
|||
component toNumY = Bits2Num(12); |
|||
component toNumIndex = Bits2Num(12); |
|||
|
|||
toBits.in <== in; |
|||
for (var i=0; i<12; i++) { |
|||
toNumX.in[i] <== toBits.out[i]; |
|||
toNumY.in[i] <== toBits.out[i+12]; |
|||
toNumIndex.in[i] <== toBits.out[i+24]; |
|||
} |
|||
|
|||
x <== toNumX.out; |
|||
y <== toNumY.out; |
|||
row_index <== toNumIndex.out; |
|||
} |
|||
|
|||
|
|||
template Test () { |
|||
signal input sig1; |
|||
signal input sig2; |
|||
|
|||
component decom = Decompressor(); |
|||
decom.in <== sig1; |
|||
sig2 === decom.out[2][2]; |
|||
} |
|||
|
|||
// component main = Test(); |
@ -0,0 +1,30 @@ |
|||
pragma circom 2.0.0; |
|||
include "../node_modules/circomlib/circuits/poseidon.circom"; |
|||
|
|||
template Hasher(inputSize) { |
|||
signal input values[inputSize]; |
|||
signal output hash; |
|||
|
|||
component hasher = Poseidon(inputSize); |
|||
for (var i = 0; i < inputSize; i++) { |
|||
hasher.inputs[i] <== values[i]; |
|||
} |
|||
hash <== hasher.out; |
|||
} |
|||
|
|||
|
|||
template RowHasher (width) { |
|||
signal input img[width]; |
|||
signal output hash; |
|||
|
|||
component hasher[width-1]; |
|||
|
|||
for(var i=0; i < width-1; i++) { |
|||
hasher[i] = Hasher(2); |
|||
hasher[i].values[0] <== i == 0 ? img[0] : hasher[i-1].hash; |
|||
hasher[i].values[1] <== img[i+1]; |
|||
} |
|||
|
|||
hash <== hasher[width-2].hash; |
|||
|
|||
} |