1

So my code does a very basic form of image manipulation and stores a string into an image.

It achieves this primarily by converting image into a numpy array (x*y*3) and then making every numeric element odd at first.

Thus the array is now like : [ [ [odd_clr_val,odd_clr_val,odd_clr_vlue] ... ] .... ]

Now what I do is convert the text to be stored into binary data and modify as much of array as needed to elements having odd parity for representing zero and even for 1.

Now I just read it back with a simple program.

The code looks like:

from PIL import Image
import numpy as np
import time
#if the value of pixel is:
#Odd = 0 , even = 1
#We make every element odd

img = Image.open('Desktop/test.jpg')

arr = np.array(img)
x,y,z  = np.shape(arr)
count = 0
initial = time.time()

#This nested loop makes every element odd but is very slow and in need to be optimized
for i in range(x):
    for j in range(y):
        count += 1
        k = arr[i][j]
        arr[i][j][0] =  k[0] + int(not(k[0]%2)) # adds 1 if k[i] is odd else 0
        arr[i][j][1] =  k[1] + int(not(k[1]%2))
        arr[i][j][2] =  k[2] + int(not(k[2]%2))

print("Time delta: %f"%(time.time() - initial ))
print("The amount of data you can store in this image is: %d kiBs"%((count*3)/1024))
#every element of this image is odd now

z = input("Enter the string:")

long_array = []
for i in z:
    long_array += list(map(int,list(format(ord(i), '#010b')[2:])))


#everything is in binary now

counter = 0
try:
    for i in range(x):
        for j in range(y):
            k = arr[i][j]

            arr[i][j][0] = k[0] if not(long_array[counter]) else k[0]+1
            counter += 1

            arr[i][j][1] = k[1] if not(long_array[counter]) else k[1]+1
            counter += 1

            arr[i][j][2] = k[2] if not(long_array[counter]) else k[2]+1
            counter += 1
except IndexError:
    print("Done")
except:
    print("An unidentified error occured!")

image = Image.fromarray(arr)

image.show()

image.save("secret.png")

My problem is that i can't optimize the upper loop of my code as it takes about 16ish seconds to finish (with a 800x600x3 picture matrix). Adding to that the lower loop of my code is super fast in comparison to the upper one.

So is there a way to optimize my upper loop using some numpy magic?

1 Answer 1

1

You can use bitwise arithmetic. Making all pixels odd can be done in one line:

arr |= 1

Embedding your bit string:

arr.ravel()[:len(long_array)] += np.array(long_array, arr.dtype)

Btw., adding one can create obvious pixel changes because of overflow. For example bright red (255, 1, 1) will become black (0, 2, 2). You can avoid this by instead subtracting one.

Sign up to request clarification or add additional context in comments.

2 Comments

Awesome!! Thanks a ton! , Can you please give me the links explaining (if possible) the magic that you did with the arr to make em all odd.
@UbdusSamad added a link to the docs. Be sure to look at the examples; they are nicely explained.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.