Rearrange pixels in image so it can't be recognized and then get it back

  • Create a program which can rearrange pixels in image so it can't be recognized.
    However your program should able to convert it back to original image.



    You can write two functions - for encoding and decoding, however one function which applied repeatedly gives original image (example in math - f(x) = 1 - x) is a bonus.



    Also producing some pattern in output gives bonus too.



    Image may be represented as 1D/2D array or image object if your language supports it.
    Note that you can only change order of pixels!



    Will be logical to select as winner code which produces less recognizable image, however I don't know how to measure it exactly, all ways I can imagine can be cheated. Therefore I chose this question to be popularity contest - let users choose what the best answer!



    Test image 1 (800 x 422 px):

    Test image 2 (800 x 480 px):

    Please provide with code output image.


    The question is a very long-winded way of saying "Write an encryption algorithm for images, whose output is an image."

    @DavidRicherby … that uses the same pixels/colors. Five black pixels in the "plain image" -> five black pixels in the "cipher image".

    What's the meaning of your "bonus"?

    @MartinBüttner I thought if two answers will have same votes count, the one with more bonuses will be chosen as accepted. Pretty rare situation I think))

    @user2992539 All right, in that case you might want to explicitly state that this is used as the tie-breaker. Otherwise, just saying it's a bonus isn't very meaningful.

    .jpg isn't helpful as a test image, as saving the output as .jpg again can lose some of the quality so that the pixels no longer match. Is it worth posting a .png version of your Test image 1? I know we could write programs to take account of that and write lossless .jpg files but that seems like a separate challenge.

    This question made me think of Arnold's cat map. I don't think it's quite suitable for this purpose but it's interesting in the same way - repeating the map enough times gets you back to the original image.

    @githubphagocyte Oops seems like I have taken wrong image from my computer) It should be PNG). About Arnold's cat map, cool, didn't know about, however, I don't understand how much iterations do you need to reverse image to original.

    The total number of iterations to get back to the original image can be hundreds even for a small image with Arnold's cat map. You could perform half this many iterations, then repeating that would give you the original again. However, for some image sizes half way through just gives you the original image upside down, which isn't much use here... Also it's only for square images - you'd have to expand it to accept arbitrary rectangles to use it here.

    @githubphagocyte Ok, likely it's too hard to apply this algorithm here, however, thanks anyway for mentioning it.

    Could you edit the question to replace the accidental jpg image with the png image you had originally intended?

    @githubphagocyte I can't, CodeGolf converts it automatically to JPG. It seems first time it also was auto-converted.

    It wasn't you - I've realised in uploading my scrambled images that they are being automatically converted to jpg when uploading png, but only for the larger file sizes - I'm guessing anything over 500 KB. Test image 2 is more compressed and uploads as png. The jpg format did give some interesting distortion in my output images though...

    Ah - I see you already worked this out...

    A similar problem was exposed to me as a introductory student in an assignment and we used a method that completely obscured the image, as opposed to some of the solutions here. I can't post my solution, as it would violate our Honor Code, but I encourage you to take a look at how we did it. If you do use this method, please do not post any code, unless you significantly alter the technique. It's a really cool little assignment for beginners that I had a lot of fun with and I would hate to have it spoiled for anyone else by being able to access a solution online. http://www.cs.princeton.edu/co

    Now elsewhere on the Stack Exchange network: Security.SE of all places

    I'm bit puzzled as why don't I see the FFT as a solution here.

    @PermanentGuest a Fast Fourier Transform wouldn't be self inverse for the first bonus but I'd still like to see a solution using it, and what patterns emerge in the output for the second bonus...

    @PermanentGuest a Hartley Transform would be self inverse but neither transform would maintain the original pixel colours so both would be invalid answers here.

    @githubphagocyte : Ah, I forgot about the color aspect for a moment.

  • G. H. Faust

    G. H. Faust Correct answer

    7 years ago

    Python 2.7 (with PIL) - No Pseudorandomness



    I break the image into 2 by 2 blocks (ignoring the remainder) and rotate each block by 180 degrees, then I do the same with 3 by 3 blocks, then 4, etc. up to some parameter BLKSZ. Then I do the same for BLKSZ-1, then BLKSZ-2, all the way back down to 3, then 2. This method reverses itself exactly; the unscramble function is the scramble function.



    The code:



    from PIL import Image
    import math

    im = Image.open("ST1.png", "r")
    arr = im.load() #pixel data stored in this 2D array

    def rot(A, n, x1, y1): #this is the function which rotates a given block
    temple = []
    for i in range(n):
    temple.append([])
    for j in range(n):
    temple[i].append(arr[x1+i, y1+j])
    for i in range(n):
    for j in range(n):
    arr[x1+i,y1+j] = temple[n-1-i][n-1-j]


    xres = 800
    yres = 480
    BLKSZ = 50 #blocksize
    for i in range(2, BLKSZ+1):
    for j in range(int(math.floor(float(xres)/float(i)))):
    for k in range(int(math.floor(float(yres)/float(i)))):
    rot(arr, i, j*i, k*i)
    for i in range(3, BLKSZ+1):
    for j in range(int(math.floor(float(xres)/float(BLKSZ+2-i)))):
    for k in range(int(math.floor(float(yres)/float(BLKSZ+2-i)))):
    rot(arr, BLKSZ+2-i, j*(BLKSZ+2-i), k*(BLKSZ+2-i))

    im.save("ST1OUT "+str(BLKSZ)+".png")

    print("Done!")


    Depending on the blocksize, you can make the computation eradicate all resemblance to the original image: (BLKSZ = 50)
    enter image description here
    enter image description here



    Or make the computation efficient: (BLKSZ = 10)
    enter image description here
    enter image description here


    Sound like best results will be if BLKSZ will be around half of image size. Anyway, I like algorithm and for small BLKSZ it looks like a modern art! Cool!

    I always upvote python.

    Instead of scrambling for all values from 2 to 50, maybe you should use only prime numbers?

    @Neil Probably then it will look more random and less artistic.

    The `BLKSZ = 10` landscape is really cool!

    It would be a trivial change to find out whether the prime number version is more or less random/artistic.

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM