Extended Visual Cryptography Schemes 
by Daniel Stoleru


Listing One

#dithering mask four-point star type
_starMask = ((40,  80, 140, 120,  20),
             (60, 170, 210, 190, 100),
             (150, 240, 250, 230, 160),
             (90, 200, 220, 180,  50),
             (10, 110, 130,  70,  30))
#dithering mask box type
_boxMask = ((138, 230,   5, 219, 107),
            (87,  46, 179,  67, 148),
            (189,  26, 250,  15, 199),
            (158,  77, 168,  56,  97),
            (128, 209,  36, 240, 117))


Listing Two

def encrypt(self, mask = _boxMask):
""" Perform the actual dithering algorithm. For any pixel in the 
    original image the function fills a square with black and white 
    pixels in resulting image. If the grey level of the pixel in 
    original image is greater than the one specified in the mask, the 
    corresponding subpixel in resulting image will be black. 
    Otherwise, the subpixel in the resulting image remains white.
    Precondition: the image must have a specified size."""

     maxX = self.__xmax
     maxY = self.__ymax

     length = len(mask)
     result = bitmap((length*maxX, length*maxY))

     for x in range(maxX):
        for y in range(maxY):
            level = self.__img.getpixel((x,y))
            transparency = 0
            for i in range(length):
                for j in range(length):
                    if level >= mask[i][j]:
                        #print a black pixel
                        result.set(i + x*length,j + y*length,0)
                    else:
                        #print a white pixel
                        result.set(i + x*length,j + y*length)
                        transparency = transparency + 1
             self.__data[(x, y)] = transparency
      return result

Listing Three

def fillokzone(self, x, y):
    st = self.__secret.transparency(x, y)
    s1 = self.__share1.transparency(x, y)
    s2 = self.__share2.transparency(x, y)
    m = self.__secret.expansion() #the total number of columns
    """st must be in the range [max(0, s1 + s2 -1), min(s1, s2)].
    """
    Lbound = max(s1, s2)
    tmp = s1 + s2
    Ubound = min(25, tmp)
    if st >= Lbound and st <= Ubound:
        self.__okzone.append([s1, s2, st])

Listing Four
def findmindist(self, x, y, z):
    dist = 0
    distmap = {}
    if len(self.__okzone) <= 0:
        raise "The images cannot be encrypted. okzone empty!"
    x0, y0, z0 = self.__okzone[0]
    min = sqrt((x - x0)*(x - x0) + (y - y0)*(y - y0) + (z - z0)*(z - z0))
    for i in range(len(self.__okzone)):
        xp, yp, zp = self.__okzone[i]
        dist = sqrt((x - xp)*(x - xp) + (y - yp)*(y - yp) + (z - zp)*(z - zp))
        distmap[dist] = [xp, yp, zp]
        if dist < min:
            min = dist
    return distmap[min]

Listing Five

def numberofcolumns(self, x, y):
    """ For every pixel we need to determine an encoding matrix.
    The function will return a tuple containing the number of 11,
    10, 01 and 00 columns. The values are determined based on the
    transparencies of the corresponding 3 pixels."""
    #set the transparency factors
    stp = self.__secret.transparency(x, y)
    s1p = self.__share1.transparency(x, y)
    s2p = self.__share2.transparency(x, y)
    m = self.__secret.expansion() #the total number of columns
    """st must be in the range [max(0, s1 + s2 -1), min(s1, s2)].
    If the condition doesn't hold, we'll try to adjust the
    transparency of the target - st."""
    Lbound = max(s1p, s2p)
    tmp = s1p + s2p
    Ubound = min(25, tmp)
    
    if stp < Lbound or stp > Ubound:
        s1, s2, st = self.findmindist(s1p, s2p, stp)
    else:
        s1, s2, st = s1p, s2p ,stp
        
    p00 = m*m - st
    p01 = st - s1 
    p10 = st - s2 
    p11 = s1 + s2 - st
            
    assert m*m == p11 + p10 + p01 + p00
    
    return p11, p10, p01, p00


Listing Six

def buildbasematrix(self, p11, p10, p01, p00):
    exp = self.__expansion
    matrix = zeros((2, exp*exp))
    stop = p11
    for i in range(stop):
        matrix[0, i] = 1
        matrix[1, i] = 1
    stop = p11 + p10
    for j in range(p11, stop):
        matrix[0, j] = 1
        matrix[1, j] = 0
    stop = p11 + p10 + p01
    for k in range(p11 + p10, stop):
        matrix[0, k] = 0
        matrix[1, k] = 1
    stop = p11 + p10 + p01 + p00
    for l in range(p11 + p10 + p01, stop):
        matrix[0, l] = 0
        matrix[1, l] = 0
    return matrix

Listing Seven

def randompermutation(self, matrix):
    new_matrix = []
    for x in range(len(matrix)):
        new_matrix.append([])

    numcols = range(len(matrix[0]))
    for y in range(len(matrix[0])):
        choice = random.choice(numcols)
        for x in range(len(new_matrix)):
            new_matrix[x].append(matrix[x][choice])
        numcols.remove(choice)  
    
    return new_matrix

Listing Eight

def encodeimages(root, file1, file2, file3):
    pm = pixelmatrix(file1, file2, file3)
    maxX, maxY = pm.size()
    expandorder = pm.expansion()

    share1 = dithering1.bitmap((expandorder*maxX, expandorder*maxY))
    share2 = dithering1.bitmap((expandorder*maxX, expandorder*maxY))

    for x in range(maxX):
        for y in range(maxY):
            pm.fillokzone(x, y)
    for x in range(maxX):
        for y in range(maxY):
            p11, p10, p01, p00 = pm.numberofcolumns(x, y)
            basismatrix = pm.buildbasematrix(p11, p10, p01, p00)
            permutedmatrix = pm.randompermutation(basismatrix)
            ps1 = pm.pixelonshare(permutedmatrix[0])
            length = len(ps1)
            for i in range(length):
                for j in range(length):
                    if ps1[i][j] == 0:
                        #write a white pixel on share1
                        share1.set(i + x*length,j + y*length,0)
                    else:
                        #write a black pixel on share1
                        share1.set(i + x*length,j + y*length)
            ps2 = pm.pixelonshare(permutedmatrix[1])
            length = len(ps2)
            for i in range(length):
                for j in range(length):
                    if ps2[i][j] == 0:
                        #print a white pixel on share2
                        share2.set(i + x*length,j + y*length,0)
                    else:
                        #print a black pixel on share2
                        share2.set(i + x*length,j + y*length)
    v1 = share1.view(root, "First Share")
    v1.psprint("FirstShare.ps")
    v2 = share2.view(root, "Second Share")
    v2.psprint("SecondShare.ps")
    decryptedImage = dithering1.decrypt(share1, share2)
    v3 = decryptedImage.view(root, "Decrypted Image")
    v3.psprint("DecryptedImage.ps")
    if showAllImages != 0:
        v4, v5, v6 = pm.showimages(root)
        v4.psprint("FirstImgDithered.ps")
        v5.psprint("SecondImgDithered.ps")
        v6.psprint("TargetImgDithered.ps")
        return v1, v2, v3, v4, v5, v6
    else:
        return v1, v2, v3

Listing Nine

def decrypt(share1, share2):
    """In visual cryptography the decryption should be done
    only by superimposing the two shares. Here we just simulate
    the process."""

 return OR(share1, share2)





4


