Converting Images with Python - python

I'm having problems getting images to convert out of bytes/strings/etc. I can turn an image into a string, or a byte array, or use b64encode on it, but when I try decode/revert it back to an image, it never works. I've tried a lot of things, locally converting an image and then reconverting it, saving it under a different name. However, the resulting files will never actually show anything. (black on Linux, "can't display image" on windows)
My most basic b64encoding script is as follows:
import base64
def convert(image):
f = open(image)
data = f.read()
f.close()
string = base64.b64encode(data)
convertit = base64.b64decode(string)
t = open("Puppy2.jpg", "w+")
t.write(convertit)
t.close()
if __name__ == "__main__":
convert("Puppy.jpg")
I've been stuck on this for a while. I'm sure it's a simple solution, but being new to Python, it's been a bit difficult trying to sort things out.
If it helps with any insight, the end goal here is to transfer images over a network, possibly MQTT.
Any help is much appreciated. Thanks!
Edit** This is in Python 2.7.
Edit 2** Wow, you guys move fast. What a great intro to the community - thanks a lot for the quick responses and super fast results!

For python3, you need to open and write in binary mode:
def convert(image):
f = open(image,"rb")
data = f.read()
f.close()
string = base64.b64encode(data)
convert = base64.b64decode(string)
t = open("Puppy2.jpg", "wb")
t.write(convert)
t.close()
Using python 2 on linux, simply r and w should work fine. On windows you need to do the same as above.
from the docs:
On Windows, 'b' appended to the mode opens the file in binary mode, so there are also modes like 'rb', 'wb', and 'r+b'. Python on Windows makes a distinction between text and binary files; the end-of-line characters in text files are automatically altered slightly when data is read or written. This behind-the-scenes modification to file data is fine for ASCII text files, but it’ll corrupt binary data like that in JPEG or EXE files. Be very careful to use binary mode when reading and writing such files. On Unix, it doesn’t hurt to append a 'b' to the mode, so you can use it platform-independently for all binary files.
You can also write your code a little more succinctly by using with to open your files which will automatically close them for you:
from base64 import b64encode, b64decode
def convert(image):
with open(image, "rb") as f, open("Puppy2.jpg", "wb") as t:
conv = b64decode(b64encode(f.read()))
t.write(conv)

import base64
def convert(image):
f = open(image)
data = f.read()
f.close()
return data
if __name__ == "__main__":
data = convert("Puppy2.jpg")
string = base64.b64encode(data)
convert = base64.b64decode(string)
t = open("Puppy2.jpg", "w+")
t.write(convert)
t.close()

Related

Edit Minecraft .dat File in Python

I'm looking to edit a Minecraft Windows 10 level.dat file in python. I've tried using the package nbt and pyanvil but get the error OSError: Not a gzipped file. If I print open("level.dat", "rb").read() I get a lot of nonsensical data. It seems like it needs to be decoded somehow, but I don't know what decoding it needs. How can I open (and ideally edit) one of these files?
To read data just do :
from nbt import nbt
nbtfile = nbt.NBTFile("level.dat", 'rb')
print(nbtfile) # Here you should get a TAG_Compound('Data')
print(nbtfile["Data"].tag_info()) # Data came from the line above
for tag in nbtfile["Data"].tags: # This loop will show us each entry
print(tag.tag_info())
As for editing :
# Writing data (changing the difficulty value
nbtfile["Data"]["Difficulty"].value = 2
print(nbtfile["Data"]["Difficulty"].tag_info())
nbtfile.write_file("level.dat")
EDIT:
It looks like Mojang doesn't use the same formatting for Java and bedrock, as bedrock's level.dat file is stored in little endian format and uses non-compressed UTF-8.
As an alternative, Amulet-Nbt is supposed to be a Python library written in Cython for reading and editing NBT files (supposedly works with Bedrock too).
Nbtlib also seems to work, as long as you set byteorder="little when loading the file.
Let me know if u need more help...
You'll have to give the path either relative to the current working directory
path/to/file.dat
Or you can use the absolute path to the file
C:user/dir/path/to/file.dat
Read the data,replace the values and then write it
# Read in the file
with open('file.dat', 'r') as file :
filedata = file.read()
# Replace the target string
filedata = filedata.replace('yuor replacement or edit')
# Write the file out again
with open('file.dat', 'w') as file:
file.write(filedata)

How to move pointer to specific bytes and read using Pickle Library in Python?

everyone!
I need a little bit of help in working with Binary Files (.dat) in python.
I am using Pickle Library to input in file which succeeds but when it comes to reading from file, my program does not work.
I need help in;
calculating the file size of the specific file, in bytes.
moving the pointer to specific bytes in file. (using .seek would be better.)
reading a specific byte from file. (using pickle.load would be better.)
looping over the specific file to print all bytes. (I get EOFError using while True: )
Any help would be appreciated.
This is my testing code so far and it has a lot of issues.
import pickle
with open ("BinaryFile.dat" , mode = "ab") as MyFile:
pickle.dump("New" , MyFile)
with open("BinaryFile.dat" , mode = "rb") as MyReadFile:
MyReadFile.seek(3)
NewLine = pickle.load(MyReadFile)
print (NewLine)
input("-> ")
pickle will do everything for you, just check its API
import pickle
with open ('BinaryFile.dat', mode='ab') as MyFile:
pickle.dump('New', MyFile)
pickle.dump([1, 2], MyFile)
pickle.dump(pickle.dump, MyFile)
# etc.
with open('BinaryFile.dat', mode='rb') as MyReadFile:
try:
while 1:
print pickle.load(MyReadFile)
except EOFError:
pass

Python urllib2 Images Distorted

I'm making a program using the website http://placekitten.com, but I've run into a bit of a problem. Using this:
im = urllib2.urlopen(url).read()
f = open('kitten.jpeg', 'w')
f.write(im)
f.close()
The image turns out distorted with mismatched colors, like this:
http://imgur.com/zVg64Kn.jpeg
I was wondering if there was an alternative to extracting images with urllib2. If anyone could help, that would be great!
You need to open the file in binary mode:
f = open('kitten.jpeg', 'wb')
Python will otherwise translate line endings to the native platform form, a transformation that breaks binary data, as documented for the open() function:
The default is to use text mode, which may convert '\n' characters to a platform-specific representation on writing and back on reading. Thus, when opening a binary file, you should append 'b' to the mode value to open the file in binary mode, which will improve portability.
When copying data from a URL to a file, you could use shutil.copyfileob() to handle streaming efficiently:
from shutil import copyfileobj
im = urllib2.urlopen(url)
with open('kitten.jpeg', 'wb') as out:
copyfileobj(im, out)
This will read data in chunks, avoiding filling memory with large blobs of binary data. The with statement handles closing the file object for you.
Change
f = open('kitten.jpeg', 'w')
to read
f = open('kitten.jpeg', 'wb')
See http://docs.python.org/2/library/functions.html#open for more information. What's happening is that the newlines in the jpeg are getting modified in the process of saving, and opening as a binary file will prevent this.
If you're using Windows, you have to open the file in binary mode:
f = open('kitten.jpeg', 'wb')
Or more Pythonically:
import urllib2
url = 'http://placekitten.com.s3.amazonaws.com/homepage-samples/200/140.jpg'
image = urllib2.urlopen(url).read()
with open('kitten.jpg', 'wb') as handle:
handle.write(image)

Simple Python code to scramble descramble file contents

I'm looking for a small easy program to scramble and descramble a file's contents. The file is a zip file so it might contain any characters. Was thinking something like two's complement or something, but not sure how to do it in Python.
The reason for this is that my current employer has draconian internet and file installation laws and I would like to mail myself files without the mailer detecting the attachment as a zip file (which it does even if you rename it to .jpg).
I already have Python installed on my work machine.
You could try xor'ing the contents of the file with a specific value, creating an XOR-cipher, just be sure to read/write the file in binary mode. You'd have to test this out to see if this works for your purposes (it does fine with text files, and I don't see why it wouldn't work for binaries.)
Of course you have to use the same (key) value (for instance a character) to encode and decode - though you can use the same code for both of these operations.
Here's some code I recently put together which does just that:
import sys
def processData(filename, key):
with open(filename, 'rb') as inf, open(filename+'.xor', 'wb') as outf:
for line in inf:
line = ''.join([chr(ord(c)^ord(key)) for c in line])
outf.write(line)
if __name__ == '__main__':
if len(sys.argv) != 3:
print 'Usage: xor_it filename key'
print ' key = a single character'
else:
processData(sys.argv[1], sys.argv[2])
I have had success with stealthZip getting through e-mail and proxy restrictions!
However, if you do want to do it in python, you could try using pickle. Load the file in binary mode, pickle it, send it over, and unpickle it on the receiving end. I don't know how well pickle functions with binaries though.
You could also simply base64 encode the file. This will make your file larger, but has the benefit of being all ascii text (which you could then just paste in the email.)
Note this will overwrite the current file. It wouldn't be hard to change it to output to another file.
#b64.py
import base64
import sys
def help():
print """Usage: python b64.py -[de] file
-d\tdecode
-e\tencode"""
sys.exit(0)
def decode(filename):
with open(filename) as f:
bin = base64.b64decode(f.read())
with open(filename,'wb') as f:
f.write(bin)
def encode(filename):
with open(filename,'rb') as f:
text = base64.b64encode(f.read())
with open(filename,'w') as f:
f.write(text)
if len(sys.argv) != 3:
help()
if sys.argv[1] == "-d":
decode(sys.argv[2])
elif sys.argv[1] == "-e":
encode(sys.argv[2])
else:
help()

Why Python on Windows can't read an image in binary mode?

I want to read a image in binary mode so that I could save it into my database, like this:
img = open("Last_Dawn.jpg")
t = img.read()
save_to_db(t)
This is working on Mac. But on Windows, what img.read() is incorrect. It's just a little out of the whole set.
So my first question is: why code above doesn't work in Windows?
And second is: is there any other way to do this?
Thanks a lot!
You need to open in binary mode:
img = open("Last_Dawn.jpg", 'rb')
You need to tell Python to open the file in binary mode:
img = open('whatever.whatever', 'rb')
See the documentation for the open function here: http://docs.python.org/library/functions.html#open
Can't say for sure but I do know that the ISO C standard doesn't distinguish between the binary and non-binary modes when calling fopen and yet Windows does.
It's likely that the Python code just uses fopen("Last_Dawn.jpg","r") under the covers (since it's written in C) and this is being opened in Windows in non-binary mode.
This will most likely convert line end characters (LF -> CRLF) and possibly others.
If you yourself specify the mode as 'rb' on your open statement, that should fix it:
img = open("Last_Dawn.jpg", "rb")
open(filename, 'rb')

Categories

Resources