creating project.
This commit is contained in:
1 parent
bcf0374319
commit
975e854e50
11 files changed
+20631
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
@@ -0,0 +1,24 @@
|
|||||||
|
pres:
|
||||||
|
env/bin/ipython3 nbconvert cryptographie_visuelle.ipynb --to slides --template output_toggle
|
||||||
|
|
||||||
|
test:
|
||||||
|
env/bin/nosetests
|
||||||
|
|
||||||
|
ipython:
|
||||||
|
env/bin/ipython3 notebook
|
||||||
|
|
||||||
|
serve: reveal.js
|
||||||
|
echo "browse to http://localhost:2000/cryptographie_visuelle.slides.html"
|
||||||
|
env/bin/python -m http.server 2000
|
||||||
|
|
||||||
|
env: reveal.js
|
||||||
|
virtualenv --python=python3 env
|
||||||
|
env/bin/pip install -r requirements.txt
|
||||||
|
|
||||||
|
|
||||||
|
reveal.js:
|
||||||
|
git clone https://github.com/hakimel/reveal.js.git
|
||||||
|
|
||||||
|
clear:
|
||||||
|
rm -rf env
|
||||||
|
rm -rf reveal.js
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
|
||||||
|
{%- extends 'slides_reveal.tpl' -%}
|
||||||
|
|
||||||
|
{% block input_group -%}
|
||||||
|
<div class="input_hidden">
|
||||||
|
{{ super() }}
|
||||||
|
</div>
|
||||||
|
{% endblock input_group %}
|
||||||
|
|
||||||
|
{%- block header -%}
|
||||||
|
{{ super() }}
|
||||||
|
|
||||||
|
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
//div.output_wrapper {
|
||||||
|
// margin-top: 0px;
|
||||||
|
//}
|
||||||
|
.input_hidden {
|
||||||
|
display: none;
|
||||||
|
// margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
$(".output_wrapper").click(function(){
|
||||||
|
$(this).prev('.input_hidden').slideToggle();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{%- endblock header -%}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
Jinja2==2.7.3
|
||||||
|
MarkupSafe==0.23
|
||||||
|
Pillow==2.5.3
|
||||||
|
Pygments==1.6
|
||||||
|
certifi==14.05.14
|
||||||
|
ipython==2.3.1
|
||||||
|
jsonpointer==1.4
|
||||||
|
jsonschema==2.4.0
|
||||||
|
matplotlib==1.4.0
|
||||||
|
mistune==0.4
|
||||||
|
nose==1.3.4
|
||||||
|
numpy==1.9.0
|
||||||
|
pyparsing==2.0.2
|
||||||
|
python-dateutil==2.2
|
||||||
|
pyzmq==14.3.1
|
||||||
|
six==1.8.0
|
||||||
|
tornado==4.0.2
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
from unittest import TestCase
|
||||||
|
from io import BytesIO
|
||||||
|
from base64 import b16decode
|
||||||
|
|
||||||
|
|
||||||
|
from visual_cryptography.visual_cryptography import ImageLayer, produce_image_layer_from_real_image
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestImageLayer(TestCase):
|
||||||
|
test_data = b'000001000100101010000100040028010000160000002800000010000000200000000100040000000000800000000000000000000000100000000000000000000000FF84000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111100000010000000010000001000000001000000000000000000000000000000000000000000000000000000000000000000000011100001110000001110000111000000111000011100000000000000000000000000000000000FFFF0000FFFF0000FFFF0000FFFF0000E0070000EFF70000EFF70000FFFF0000FFFF0000FFFF0000FFFF0000E3C70000E3C70000E3C70000FFFF0000FFFF0000'
|
||||||
|
|
||||||
|
def get_test_image(self):
|
||||||
|
return BytesIO(b16decode(self.test_data))
|
||||||
|
|
||||||
|
|
||||||
|
def test_produce_image_layer_from_real_image(self):
|
||||||
|
img = produce_image_layer_from_real_image(self.get_test_image())
|
||||||
|
self.assertEqual(img.data[2][3], 0)
|
||||||
|
self.assertEqual(img.data[0][0], 1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_empty_data(self):
|
||||||
|
img = ImageLayer(0, 0)
|
||||||
|
m = img.get_empty_data(2, 3)
|
||||||
|
self.assertEqual(len(m), 2)
|
||||||
|
self.assertEqual(len(m[0]), 3)
|
||||||
|
|
||||||
|
def test_produce_empty_shares(self):
|
||||||
|
img = ImageLayer(5, 6)
|
||||||
|
ret = img.produce_empty_shares()
|
||||||
|
|
||||||
|
two_shares = 2
|
||||||
|
self.assertEqual(len(ret), two_shares)
|
||||||
|
|
||||||
|
ten_pixels_width = 10
|
||||||
|
self.assertEqual(len(ret[0]), ten_pixels_width)
|
||||||
|
|
||||||
|
twelve_pixels_height = 12
|
||||||
|
self.assertEqual(len(ret[0][0]), twelve_pixels_height)
|
||||||
|
|
||||||
|
|
||||||
|
def test_place_sub_pixels_in_shares_position(self):
|
||||||
|
img = ImageLayer(2, 3)
|
||||||
|
shares = img.produce_empty_shares()
|
||||||
|
|
||||||
|
c = [[1, 1, 1, 1],[1, 1, 1, 1]]
|
||||||
|
img.place_sub_pixels_in_shares(1,1, shares, c)
|
||||||
|
|
||||||
|
self.assertListEqual(shares[0][0].tolist(), [0,0,0,0,0,0])
|
||||||
|
self.assertListEqual(shares[0][1].tolist(), [0,0,0,0,0,0])
|
||||||
|
self.assertListEqual(shares[0][2].tolist(), [0,0,1,1,0,0])
|
||||||
|
self.assertListEqual(shares[0][3].tolist(), [0,0,1,1,0,0])
|
||||||
|
|
||||||
|
def test_place_sub_pixels_in_shares(self):
|
||||||
|
img = ImageLayer(2, 3)
|
||||||
|
shares = img.produce_empty_shares()
|
||||||
|
|
||||||
|
c = [[1, 0, 0, 1],[0, 1, 0, 1]]
|
||||||
|
img.place_sub_pixels_in_shares(1,1, shares, c)
|
||||||
|
self.assertListEqual(shares[0][0].tolist(), [0,0,0,0,0,0])
|
||||||
|
self.assertListEqual(shares[0][1].tolist(), [0,0,0,0,0,0])
|
||||||
|
self.assertListEqual(shares[0][2].tolist(), [0,0,1,0,0,0])
|
||||||
|
self.assertListEqual(shares[0][3].tolist(), [0,0,0,1,0,0])
|
||||||
|
|
||||||
|
def test_get_pixel_value_in_share(self):
|
||||||
|
img = ImageLayer(10, 10)
|
||||||
|
share = img.produce_empty_shares()[0]
|
||||||
|
|
||||||
|
pixel = [1, 2, 3, 4]
|
||||||
|
img.place_sub_pixels_in_shares(3,1, [share], [pixel])
|
||||||
|
self.assertEqual(pixel, img.get_pixel_value_in_share(3,1, share))
|
||||||
|
|
||||||
|
def test_inverse_pixel(self):
|
||||||
|
img = ImageLayer(2, 3)
|
||||||
|
inv = img.inverse_pixel([0, 1])
|
||||||
|
expt = [1, 0]
|
||||||
|
self.assertEqual(expt, inv)
|
||||||
|
|
||||||
|
def test_produce_cheated_image_from_other_share(self):
|
||||||
|
img = produce_image_layer_from_real_image(self.get_test_image())
|
||||||
|
share = img.produce_two_shares_from_image()[0]
|
||||||
|
|
||||||
|
cheated_share = img.produce_cheated_image_from_other_share(share)
|
||||||
|
self.assertEqual(len(cheated_share), 32)
|
||||||
|
self.assertEqual(len(cheated_share[0]), 32)
|
||||||
|
|
||||||
|
def test_produce_two_shares_from_image(self):
|
||||||
|
img = produce_image_layer_from_real_image(self.get_test_image())
|
||||||
|
shares = img.produce_two_shares_from_image()
|
||||||
|
self.assertEquals(len(shares), 2)
|
||||||
Whitespace-only changes.
@@ -0,0 +1,121 @@
|
|||||||
|
from PIL import Image
|
||||||
|
import numpy as np
|
||||||
|
from json import dumps
|
||||||
|
from random import choice
|
||||||
|
|
||||||
|
|
||||||
|
class ImageLayer(object):
|
||||||
|
c_0 = (
|
||||||
|
[[0,0,1,1], [0,0,1,1]],
|
||||||
|
[[1,1,0,0], [1,1,0,0]],
|
||||||
|
[[1,0,1,0], [1,0,1,0]],
|
||||||
|
[[0,1,0,1], [0,1,0,1]],
|
||||||
|
[[0,1,1,0], [0,1,1,0]],
|
||||||
|
[[1,0,0,1], [1,0,0,1]],
|
||||||
|
)
|
||||||
|
|
||||||
|
c_1 = (
|
||||||
|
[[0,0,1,1], [1,1,0,0]],
|
||||||
|
[[1,1,0,0], [0,0,1,1]],
|
||||||
|
[[1,0,1,0], [0,1,0,1]],
|
||||||
|
[[0,1,0,1], [1,0,1,0]],
|
||||||
|
[[0,1,1,0], [1,0,0,1]],
|
||||||
|
[[1,0,0,1], [0,1,1,0]],
|
||||||
|
)
|
||||||
|
|
||||||
|
pixel_width = 2
|
||||||
|
|
||||||
|
def __init__(self, height, width):
|
||||||
|
self.data = self.get_empty_data(height, width)
|
||||||
|
|
||||||
|
def get_json_string(self):
|
||||||
|
return dumps(self.data)
|
||||||
|
|
||||||
|
def get_empty_data(self, number_of_lines, number_of_columns):
|
||||||
|
data = []
|
||||||
|
for i in range(number_of_lines):
|
||||||
|
data.append(np.array([0]*number_of_columns))
|
||||||
|
return np.array(data)
|
||||||
|
|
||||||
|
def produce_empty_shares(self):
|
||||||
|
sub_pixel_matrix = self.c_0[0]
|
||||||
|
number_of_share_to_produce = len(sub_pixel_matrix)
|
||||||
|
number_of_sub_pixels = len(sub_pixel_matrix[0])
|
||||||
|
|
||||||
|
current_width = len(self.data[0])
|
||||||
|
current_height = len(self.data)
|
||||||
|
|
||||||
|
ret = [self.get_empty_data(current_height * self.pixel_width, current_width * self.pixel_width) for i in range(len(sub_pixel_matrix))]
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def get_single_empty_share(self):
|
||||||
|
return self.produce_empty_shares()[0]
|
||||||
|
|
||||||
|
def place_sub_pixels_in_shares(self, line, col, shares, sub_pixel_matrix):
|
||||||
|
number_of_sub_pixels = len(sub_pixel_matrix[0])
|
||||||
|
for i, share in enumerate(shares):
|
||||||
|
for l in range(line * self.pixel_width, (line + 1) * self.pixel_width ):
|
||||||
|
for c in range(col * self.pixel_width, (col + 1) * self.pixel_width):
|
||||||
|
share[l][c] = sub_pixel_matrix[i][(l % self.pixel_width) * self.pixel_width + (c % self.pixel_width)]
|
||||||
|
|
||||||
|
def get_pixel_value_in_share(self, x, y, share):
|
||||||
|
pixel = [0, 0, 0, 0]
|
||||||
|
pixel[0] = share[2 * x][2 * y]
|
||||||
|
pixel[1] = share[2 * x][2 * y + 1]
|
||||||
|
pixel[2] = share[2 * x + 1][2 * y]
|
||||||
|
pixel[3] = share[2 * x + 1][2 * y + 1]
|
||||||
|
return pixel
|
||||||
|
|
||||||
|
def produce_shares_from_image(self):
|
||||||
|
shares = self.produce_empty_shares()
|
||||||
|
for (x,y), color in np.ndenumerate(self.data):
|
||||||
|
c = self.c_0 if color == 0 else self.c_1
|
||||||
|
self.place_sub_pixels_in_shares(x, y, shares, choice(c))
|
||||||
|
return shares
|
||||||
|
|
||||||
|
def produce_two_shares_from_image(self):
|
||||||
|
return self.produce_shares_from_image()
|
||||||
|
|
||||||
|
def inverse_pixel(self, pixel):
|
||||||
|
return [(e + 1) % 2 for e in pixel]
|
||||||
|
|
||||||
|
def get_cheated_pixel(self, x, y, share, color):
|
||||||
|
pixel = self.get_pixel_value_in_share(x, y, share)
|
||||||
|
if color == 0:
|
||||||
|
return pixel
|
||||||
|
return self.inverse_pixel(pixel)
|
||||||
|
|
||||||
|
def produce_cheated_image_from_other_share(self, share):
|
||||||
|
cheated_share = self.get_single_empty_share()
|
||||||
|
for (x,y), color in np.ndenumerate(self.data):
|
||||||
|
cheated_pixel = self.get_cheated_pixel(x, y, share, color)
|
||||||
|
self.place_sub_pixels_in_shares(x, y, [cheated_share], [cheated_pixel])
|
||||||
|
return cheated_share
|
||||||
|
|
||||||
|
|
||||||
|
def cmyk_to_luminance(r, g, b):
|
||||||
|
"""
|
||||||
|
takes a RGB color and returns it grayscale value. See
|
||||||
|
http://www.johndcook.com/blog/2009/08/24/algorithms-convert-color-grayscale/
|
||||||
|
for more information
|
||||||
|
"""
|
||||||
|
return 0.299 * r + 0.587 * g + 0.114 * b
|
||||||
|
|
||||||
|
|
||||||
|
def cmyk_to_black_and_white(r, g, b):
|
||||||
|
black_threshold = 255 / 3
|
||||||
|
if cmyk_to_luminance(r, g, b) > black_threshold:
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def produce_image_layer_from_real_image(image_path):
|
||||||
|
im = Image.open(image_path).convert('RGB')
|
||||||
|
ret = ImageLayer(*im.size)
|
||||||
|
for i in range(im.size[0]):
|
||||||
|
for j in range(im.size[1]):
|
||||||
|
r, g, b = im.im.getpixel((i,j))
|
||||||
|
ret.data[j][i] = cmyk_to_black_and_white(r, g, b)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
Reference in new issue
Block a user