My program is often working with numpy arrays that are very large ((819200, 460800, 4), uint8). To store this in memory (as just pure zeros) I would need over 1.3TB of memory which is absurd. My goal is to be able to save these numpy arrays as an image. I also want it to be as fast as it can, but speed is less of an issue.
What I was doing at the very beginning was storing the numpy array in an HDF5 file (using H5PY), then I would do processing on that array, then use CV2 to save. Not only was it slow, CV2 seems to load the image into memory, so that idea went out of the window very quickly. Now, I have tried over 20 different methods of saving these large arrays, so to shorten the post, I'll just mention some of the latest one.
After using CV2, I found a library called 'numpngw'. Its a numpy and python based png writer. This was my code:
f = h5py.File("mytestfile.hdf5", "w")
dset = f.create_dataset("mydataset", (100000,100000,4), dtype=np.uint8, compression='gzip')
shp = dset.shape
step = 10000
png = open("new.png", "wb")
numpngw._write_header_and_meta(png, 8, shp, color_type=6, bitdepth=8, palette=None, #i'm manually writing to the png file rather than writing all data at once, so i can append data over and over again.
interlace=0, text_list=None, timestamp=None, sbit=None, gamma=None, iccp=None,
chromaticity=None, trans=None, background=None, phys=None)
for i in range(0, shp[0]+step, step): #from step to
numpngw._write_data(png, dset[i:i+step, i:i+step], bitdepth=8, max_chunk_len=step, #writing the data in largest chunks I can
filter_type=None, interlace=0)
png.flush()
#gc.collect()
numpngw._write_iend(png)
png.close()
f.close()
The idea of this is that it just writes chunks of the numpy array over and over again until the whole array is written. I never even knew if this version was working because it was so extremely slow.
I then tried the same chunk writing method with PIL. And instead of a PNG, I used TIFF since it seemed a lot faster. Unfortunately, PIL doesn't support appending to a TIFF in chunks. The "append" parameter is used for animating TIFFs, so I couldn't do it that way.
The last, and most recent library I used was tifffile. It seemed to do everything I needed. It also has a memmap implementation to make a TIFF file out of a memory mapped numpy array.
blank = numpy.zeros((256,256,3))
memmap_image = tifffile.memmap('temp.tif', shape=blank.shape, dtype='uint8')
memmap_image[:] = blank[:]
memmap_image.flush()
del memmap_image
This creates a blank TIFF file. Combining this with H5PY allowed me to save large images - or so I thought. The large TIFF files seem to be corrupt. I tried opening them in (Windows) Photos, Adobe Acrobat Reader DC and Affinity Photo. All said the file was not recognised (sometimes Affinity Photo even crashed on opening - could be a memory issue though).
I don't know what would be making the image corrupt since it seems to work with smaller arrays. I came back to it the next day and started getting memory errors on this line (out of nowhere) memmap_image[:] = blank[:].
The last thing I tried was combining the chunk method with tifffile:
f = h5py.File("mytestfile.hdf5", "w")
dset = f.create_dataset("mydataset", (100000,100000,3), dtype=np.uint8)
shp = dset.shape
step = 10000
a = tiffile.memmap('temp.tif', shape=(100000,100000,3), dtype=np.uint8)
for i in range(0, shp[0]+step, step):
a[i:i+step,i:i+step] = dset[i:i+step,i:i+step]
a.flush()
del a
It takes about 2 minutes (not bad!) and it created a large file (~29GB, compression will make it smaller), however, again it is corrupt and nothing can read the TIFF file.
I really don't want to give up on this project but I'm stuck on what else I can try. Could anyone recommend a TIFF/PNG library that supports appending to the image, but also doesn't want to load it into memory?