Reputation: 17
Trying to make an encode process but have an error line:
Look at my whole fuction ,please, for the whole getting it. I think it isn't big enough.
Trying to add the header to the file data:
#Add the header to the file data
headerdata = struct.pack("4s"+\
"I"+\
str(Header.MAX_FORMAT_LENGTH)+"s",header.magicnum, header.size, header.fformat)
filebytes = headerdata + data
Have an error:
str(Header.MAX_FORMAT_LENGTH)+"s",header.magicnum, header.size, header.fformat) struct.error: argument for 's' must be a bytes object
I was trying to change it:(this line, addin 'b')
str(Header.MAX_FORMAT_LENGTH)+b"s",header.magicnum, header.size, header.fformat)
Have another error:
str(Header.MAX_FORMAT_LENGTH)+b's',header.magicnum, header.size, header.fformat) TypeError: must be str, not bytes
the whole fucnton:
def encode(image, data, filename, encryption=False, password=""):
im = Image.open(image)
px = im.load()
#Create a header
header = Header()
header.size = len(data)
header.fformat = "" if (len(filename.split(os.extsep))<2)\
else filename.split(os.extsep)[1]
#Add the header to the file data
headerdata = struct.pack("4s"+\
"I"+\
str(Header.MAX_FORMAT_LENGTH)+"s",header.magicnum, header.size, header.fformat)
filebytes = headerdata + data
#Optional encryption step
if encrypt:
if password:
filebytes = encrypt(filebytes, password,\
padding=im.width*im.height - len(filebytes))
else:
print ("Password is empty, encryption skipped")
#Ensure the image is large enough to hide the data
if len(filebytes) > im.width*im.height:
print ("Image too small to encode the file. \
You can store 1 byte per pixel.")
exit()
for i in range(len(filebytes)):
coords = (i%im.width, i/im.width)
byte = ord(filebytes[i])
px[coords[0], coords[1]] = encode_in_pixel(byte, px[coords[0],\
coords[1]])
im.save("output.png", "PNG")
Upvotes: 2
Views: 173
Reputation: 1283
since you said they are all strings, here you go
headerdata = struct.pack("4s"+\
"I"+\
str(Header.MAX_FORMAT_LENGTH)+"s",header.magicnum.encode(), int(header.size), header.fformat.encode())
This should work for the formats and types you want
According to this, and specifically section 7.1.2.2, we can find the types needed as arguments for the following format characters:
-----------------------------------------
|Formatting Character | Type (in python)|
-----------------------------------------
|s | integer |
-----------------------------------------
|I | bytes |
-----------------------------------------
and since the data you want to format is of type str
, we need to change it.
Lets start with making a str
to and integer
since it's the simplest.
>>> x = '123'
>>> type(x)
str
>>> y = int(x)
>>> type(y)
int
Easy, all we need to do is call int()
on our string.
Next up is turning a string into bytes. We use strings encode()
method to do this (documentation)
>>> x = '123'
>>> type(x)
str
>>> y = e.encode()
>>> type(y)
bytes
>>> print(y)
b'123'
Upvotes: 0
Reputation: 191
Your original code was correct, except that the type of header.magicnum
was unexpected. Your code snippet should read
#Add the header to the file data
headerdata = struct.pack("4s"+\
"I"+\
str(Header.MAX_FORMAT_LENGTH)+"s","{:04d}".format(header.magicnum).encode('UTF-8'), header.size, header.fformat)
filebytes = headerdata + data
or some other suitable format code and encoding that turns header.magicnum
into your expected result.
Upvotes: 1