How to return base64Encoded Matplotlib Chart? - python

In my matplotlib python code, I have a plt.savefig('test_file.png') and that, of course, works as expected.
But, since this code will be used in a REST service, I need to return the file contents as a Base64Encoded string to the caller (so they can Decode it and view it as png graphics file).
I tried this approach below, but it doesn't generate a large enough file (the actual png created by the plt.saveFig() is about 100KB, this approach below is only 4 KB):
my_stringIObytes = io.BytesIO()
plt.savefig(my_stringIObytes, format='png')
my_stringIObytes.seek(0)
my_base64_jpgData = base64.b64encode(my_stringIObytes.read())
And using the above "my_stringIObytes", I also tried saving this directly to disk (with no encoding), like this:
with open('base64_decode_test.png', 'wb') as fl:
fl.write(my_stringIObytes.getbuffer())
fl.close()
But that did not work either...
It looks like my initial attempt in the first code snippet above is probably the culprit, but I can't find any good examples of how do to what I need.
Would appreciate suggestions.
Thanks very much,
M

Related

Errno 20: Not a directory when saving into zip file

When I try to save a pyplot figure as a jpg, I keep getting a directory error saying that the given file name is not a directory. I am working in Colab. I have a numpy array called z_img and have opened a zip file.
import matplotlib.pyplot as plt
from zipfile import ZipFile
zipObj = ZipFile('slices.zip', 'w') # opening zip file
plt.imshow(z_img, cmap='binary')
The plotting works fine. I did a test of saving the image into Colab's regular memory like so:
plt.savefig(str(ii)+'um_slice.jpg')
And this works perfectly, except I am intending to use this code in a for loop. ii is an index to differentiate between each image, and several hundred images would be created so I want them going in the zipfile. Now when I try adding the path to the zipfile:
plt.savefig('/content/slices.zip/'+str(ii)+'um_slice.jpg')
I get: NotADirectoryError: [Errno 20] Not a directory: '/content/slices.zip/150500um_slice.jpg'
I assume it's because the {}.jpg string is a filename, and not a directory per se. But I am quite new to Python, and don't know how to get the plot into the zip file. That's all I want. Would love any advice!
First off, for anything that's not photographic content (ie. nice and soft), JPEG is the wrong format. You'll have a better time using a different file format. PNG is nice for pixels, SVG for vector graphics (in case you embed this in a website later!), PDF for vector, too.
The error message is quite on point: you cannot just save to a zip file as if it was a directory.
Multiple ways around:
use the tempfile module's mkdtemp to make a temporary directory, save into that, and zip the result
save not into a filename, but into a buffer (BytesIO I guess) and append that to the compressed stream (I'm not too familiar with ZipFile)
use PDF as output and simply generate a multipage PDF; it's not hard, and probably much nicer in the long term. You can still convert that vector graphic result to PNG (or any other pixel format9 as desired, but for the time being, it's space efficient, arbitrarily scaleable and keeps all your pages in one place. It's easy to import selected pages into LaTeX (matter of fact, \includegraphics does it directly) or into websites (pdf.js).
From the docs, matplotlib.pyplot.savefig accepts a binary file-like object. ZipFile.open creates binary file like objects. These two have to get todgether!
with zipobj.open(str(ii)+'um_slice.jpg', 'w') as fp:
plt.savefig(fp)

how to load an image from its binary code

I have created a binary file of an image using the code:
f1=open('file_name.png','rb')
f2=open('newfile.txt ','wb')
byte=f1.read()
f2.write(byte)
I have got the binary file but now I want to load that image using that binary code. Now, I want to load that image (or maybe recreate) that image by the source code itself in other file. how do I do that?
please note: I'm a newbie at python.
I have looked over the Various and found programs that I didn't understand.
this code was present there most of the time I searched. It made a bit sense to me.
I have tried the code with base64:
import base64
with open("t.png", "rb") as imageFile:
str = base64.b64encode(imageFile.read())
print (str)
but this is not doing anything. not showing errors, not printing the string either.
if there is a simple way please I request you to explain by the code.
Thanks in advance!

Binary file (Labview .DAT file) conversion using Python

I work in a lab where we acquire electrophysiological recordings (across 4 recording channels) using custom Labview VIs, which save the acquired data as a .DAT (binary) file. The analysis of these files can then be continued in more Labview VIs, however I would like to analyse all my recordings in Python. First, I need walk through all of my files and convert them out of binary!
I have tried numpy.fromfile (filename), but the numbers I get out make no sense to me:
array([ 3.44316221e-282, 1.58456331e+029, 1.73060724e-077, ...,
4.15038967e+262, -1.56447362e-090, 1.80454329e+070])
To try and get further I looked up the .DAT header format to understand how to grab the bytes and translate them - how many bytes the data is saved in etc:
http://zone.ni.com/reference/en-XX/help/370859J-01/header/header/headerallghd_allgemein/
But I can't work out what to do. When I type "head filename" into terminal, below is what I see.
e.g. >> head 2014_04_10c1slice2_rest.DAT
DTL?
0???? ##????
empty array
PF?c ƀ????l?N?"1'.+?K13:13:27;0.00010000-08??t?޾??DY
??N?t?x???D?
?uv?tgD?~I??
??N?t?x>?n??
????t?x>?n??
????t?޾??D?
????t?x???D?
????t?x?~I??
????tgD>?n??
??N?tgD???D?
??N?t?x???D?
????t????DY
??N?t?x>?n??
??N?t????DY
?Kn$?t?????DY
??N?t??>?n??
??N?tgD>?n??
????t?x?~I??
????tgD>?n??
??N?tgD>?n??
??N?tgD???DY
????t?x???D?
????t???~I??
??N?tgD???DY
??N?tgD???D?
??N?t?޿~I??
??N?t?x???DY
??N?tF>?n??
??N?t?x??%Y
Any help or suggestions on what to do next would be really appreciated.
Thanks.
P.s. There is an old (broken) matlab file that seems to have been intended to convert these files. I think this could probably be helpful, but having spent a couple of days trying to understand it I am still stuck. http://www.mathworks.co.uk/matlabcentral/fileexchange/27195-load-labview-binary-data
Based on this link it looks like the following should do the trick:
binaryFile = open('Measurement_4.bin', mode='rb')
(data.offset,) = struct.unpack('>d', binaryFile.read(8))
Note that mode is set to 'rb' for binary.
With numpy you can directly do this as
data = numpy.fromfile('Measurement_4.bin', dtype='>d')
Please note that if you are just using Python as an intermediate and want to go back to LabVIEW with the data, you should instead use the function Read from Binary file.vi to read the binary file using native LabVIEW.
DAT is a pretty generic suffix, not necessarily something pointing to a specific format. If I'm understanding correctly, that help section is for DIAdem, which may be completely unrelated to how your data is saved from LV.
What you want is this help section, which tells you how LV flattens data to be stored on disk - http://zone.ni.com/reference/en-XX/help/371361J-01/lvconcepts/flattened_data/
You will need to look at the LV code to see exactly what kind of data you're saving and how the write file function is configured (byte order, size prepending, etc.) and then use that document to translate it to the actual representation.

working with .bmp files in python 3

I have a bmp file. It is just a red square. I have to write a program with functions to make it have white stripes. Things I would need to do:
load the bmp file.
read and assess the bmp file.
code certain areas coordinates of the file to be colored white.
close the file
display the end product file as output
i am a novice, and am having trouble reading or displaying the original bmp file, let alone edit the content inside. it is not similar to opening a txt file and "readline()". also, when i copy paste the bmp file in the pydev projects src folder in eclipse, it does not show up on eclipse, so i don't know if how the computer would recognize that the file is there. i want to read up on it before posting here, but i don't seem to get much results googling, since i am not sure exactly what i should search for.
The easy way to do this is with a third-party image-processing library like PIL/Pillow. The code is simple enough that you could figure it out in a few minutes from the examples on the Image module docs…
But if you're not allowed to do that, let's look at how to do this manually.
First, BMP isn't a text file format, it's a binary format. That means you have to read it in binary mode. And you can't read it "line by line", because it doesn't have lines of text to read. Since a bytes object isn't mutable, you will probably want to copy it into a bytearray to work with. So:
with open('spam.bmp', 'rb') as f:
data = bytearray(f.read())
Next, you need to parse the BMP file format. I assume the main point of the exercise is figuring out how to do that yourself, so I'll give you a link to Wikipedia's article, which describes it better than the Microsoft docs, and you can go from there.
The struct module in the standard library will be very helpful for interpreting the headers; it's much easier to read a 32-bit little-endian number with struct.unpack_from('<L', data, offset) than with by reading data[offset], data[offset+1], etc. and re-combining them into a 32-bit number.
I'm guessing you can ignore all the options for BMP compression—otherwise, this would be way too hard an assignment. In fact, you can probably just assume that all of the headers will specify the most common variant and only code for that. But you might want to ask your teacher for feedback on that.
Now, once you've found the "pixel array" portion of the BMP, and you've figured out how to interpret it from the DIB header, you can just set pixels to white at whichever positions you want by setting the values at the appropriate indexes of the bytearray. For example, it may turn out to be as simple as:
pos = pixel_array_offset + row_size * y + pixel_size * x
data[pos:pos+3] = 255, 255, 255
Finally, once you've changed your red pixels to white, you can save it with:
with open('eggs.bmp', 'wb') as f:
f.write(data)

Python/Pygame Converting a .jpg to a string and back to a .jpg: Corruption Issue

I'm making a program in Python using Pygame that will load an image to the screen, open the raw data (as in, the characters you would see if you opened the jpg as a text file), throw some random characters in with the data, and then resave it as a jpg to load into pygame again. This results in a cool looking glitch effect.
I am not having any problems with the desired glitches, but I was finding that despite what kind of random character was placed where, for certain images every time the image went through my glitch function I ended up with a grey bar on the bottom of the image. I simplified my function so that all it did was load the image, open the image as a read binary (even though I'm on a mac), save a string of the raw data, write a new file based on this string and then load that file. The image was not purposefully glitched in any way, and the data was supposedly untouched but I still encountered this grey bar.
Here is the relevant code:
def initializeScreen(x, y):
pygame.display.set_mode((x,y))
return pygame.display.get_surface()
def importImage(fileName):
imgText = open(fileName, 'rb')
imgTextStr = imgText.read()
imgText.close()
return imgTextStr
screenSurf = initializeScreen(800,600)
textOfImg = importImage('/Users/Amoeba/Desktop/GlitchDriving/Clouds.jpg')
newFile = open('/Users/Amoeba/Desktop/GlitchDriving/tempGlitchFile.jpg', 'wb')
newFile.write(textOfImg)
newimgSurf = pygame.image.load('/Users/Amoeba/Desktop/GlitchDriving/tempGlitchFile.jpg')
screenSurf.blit(newimgSurf, (0,0))
pygame.display.flip()
Here is an example of one of the images before and after passing through my function:
It is worth noting that the size of the grey bar depends on the picture. Some pictures even pass through my function visibly unchanged, as they should be. Also, if I open the new version of the jpg written by my program with image viewing software like preview, the grey bar does not appear. My suspicion is that it is a quirk of the pygame image load function or that there is some strange character (or possibly white space) that is being dropped in my conversion from jpg to string or vice-versa. I did compare two of the text files (one with grey bar and one without) and found no difference while using an online "difference finder".
This is my first post here, but I've lurked for answers dozens of times. Any help is greatly appreciated.
You never close the file object you create with open, so probably not all data gets written back (flushed) to your new file.
Either close the file object before trying to read the file again, or better start using the with statement (which will close the file for you) whenever you deal with files:
def importImage(fileName):
with open(fileName, 'rb') as imgText:
return imgText.read()
screenSurf = initializeScreen(800,600)
textOfImg = importImage(r'path/to/file')
with open(r'path/to/otherfile', 'wb') as newFile:
newFile.write(textOfImg)
newimgSurf = pygame.image.load(r'path/to/otherfile')
screenSurf.blit(newimgSurf, (0,0))
pygame.display.flip()

Categories