I have previously asked this question: How to write exif metadata to an image.
I now have found a way to inject metadata. However, it results in a copy of the image into memory. With large images, and the need to already have a copy in memory, this is going to have performance, and possibly cause a memory crash.
Is there a correct way to inject metadata without having to make a copy of the image? Perhaps it could be tacked on to a file, after it is written to disk?
I would prefer native implementations, without having to resort to a third party library just for this, if at all possible.
This question could require a small or large amount of code depending on what you need. EXIF data is stored in a JPEG APP1 marker (FFE1). It looks very much like a TIFF file with a TIFF header, IFD and individual tags with the data. If you can build your own APP1 marker segment, then inserting it or replacing it in a JPEG file is trivial. If you are looking to read the metadata from an existing file, add some new tags and then write it back, that can be more involved. The tricky part of EXIF data are those tags which require more than 4-bytes. Each TIFF tag is 12 bytes: 2-byte tag, 2-byte data type, 4-byte count, 4-byte data. If the data doesn't fit completely in the 4 bytes of the tag, then the tag specifies an absolute offset into the file of where to find the data. If the existing data has any tags with data like this (e.g. make, model, capture date, capture time, etc), you will need to repack that data by fixing the offsets and then add your own. In a nutshell:
1) If you are adding a pre-made APP1 marker to a JPEG file, this is simple and requires little code.
2) If you need to read the existing meta-data from a JPEG file, add your own and write it back, the code is a bit more involved. It's not "difficult", but it involves a lot more than just reading and writing blocks of data.
Start by reading the TIFF 6.0 spec to understand the tag and directory structure:
TIFF 6.0 spec
Next, take a look at the JPEG EXIF spec:
EXIF 2.2 Spec
I would expect the existing exif manipulator software can do it, but haven't tested.
Links:
http://www.exiv2.org/
http://libexif.sourceforge.net/
http://www.kraxel.org/blog/linux/fbida/
CGImageSourceRef could be used to get image properties including its thumbnail without loading all image data into memory. This way memory is not wasted by UIImage and NSData.
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], NULL);
Then save CGImageDestinationRef adding the source image and exif data.
CGImageDestinationAddImageFromSource (destRef,
imageSource,
0,
(CFDictionaryRef)propertes );//exif
BOOL success = CGImageDestinationFinalize(destRef);
Related
I'm storing .tiff files on google cloud storage. I'd like to manipulate them using a distributed Dask cluster installed with Helm on Kubernetes..
Based on the dask-image repo, the Dask documentation on remote data services, and the use of storage_options, right now it looks like remote reads from .zarr, .tdb, .orc, .txt, .parquet, and .csv formats are supported. Is that correct? If so, is there any recommended workaround for accessing remote .tiff files?
There are many ways to do this. I would probably use a library like skimage.io.imread along with dask.delayed to read the TIFF files in parallel and then arrange them into a Dask Array
I encourage you to take a look at this blogpost on loading image data with Dask, which does something similar.
I believe that the skimage.io.imread function will happily read data from a URL, although it may not know how to interoperate with GCS. If the data on GCS is also available by a public URL (this is easy to do if you have access to the GCS bucket) then that would be easy. Otherwise you might use the gcsfs library to get the bytes from the file and then feed those bytes into some Python image reader.
Building off #MRocklin's answer, I found two ways to do it with gcsfs. One way with imageio for image parsing:
fs = gcsfs.GCSFileSystem(project="project_name")
img_bytes = fs.cat("bucket/blob_name.tif")
imageio.core.asarray(imageio.imread(img_bytes, "TIFF"))
And another with opencv-python for image parsing:
fs = gcsfs.GCSFileSystem(project="project_name")
fs.get("bucket/blob_name.tif", "local.tif")
img = np.asarray(cv2.imread("local.tif", cv2.IMREAD_UNCHANGED))
this issue has troubled me for some time。i should allow user to scale image,so i choose svg instend of jpg/png ,one of question is that i hava to store svg because such svg resource are loaded form netWork,but i find that if i archiver svg into data,read data from disk transform to svg,it cost some time to render svg。so i change other method ,i want to archiver JAMSVGImage instance ,but what i stuck in is that i can't find any way to archiver JAMSVGImage。now i just cache JAMSVGImage into memory with singleton,but as we all know,every time when the app has killed or stop running background ,we lost the cache data in singleton,who can help me to slove this issus,thanks!
What you probably want to do is store the SVG, render it to a new UIImage (using JAMSVGImage's imageAtSize: method), and store a PNG representation of that UIImage in your application's cache directory.
When you application starts, you check whether the corresponding PNG in the cache directory exists and load that instead of the SVG. You would then only load the SVG when you really need it, for example when resizing.
I have texture, loaded from a .DDS file using the method D3DX11CreateTextureFromFile(). The DDS is created using Block Compression 1 compression, so when I query IDXGISurface1 from the ID3D11Texture2D, the pixel format of the surface is DXGI_FORMAT_BC1_UNORM.
So my question is: can I change (convert) the format of the surface to DXGI_FORMAT_B8G8R8A8_UNORM. I tried ID3D11DeviceContext::CopyResource method but it seems it is unable to convert from BC1 to 32bppBGRA.
Any suggestions are appreciated.
If this is a one-time or build-time process, use the TexConv tool included in DirectXTex. If you need to do this at run-time, you can either render the image to a B8G8R8A8 render target, or use the CPU conversion code included in the DirectXTex library.
In a particular Rails application, I'm pulling binary data out of LDAP into a variable for processing. Is there a way to check if the variable contains binary data? I don't want to continue with processing of this variable if it's not binary. I would expect to use is_a?...
In fact, the binary data I'm pulling from LDAP is a photo. So maybe there's an even better way to ensure the variable contains binary JPEG data? The result of this check will determine whether to continue processing the JPEG data, or to render a default JPEG from disk instead.
There is actually a lot more to this question than you might think. Only since Ruby 1.9 has there been a concept of characters (in some encoding) versus raw bytes. So in Ruby 1.9 you might be able to get away with requesting the encoding. Since you are getting stuff from LDAP the encoding for the strings coming in should be well known, most likely ISO-8859-1 or UTF-8.
In which case you can get the encoding and act on that:
some_variable.encoding # => when ASCII-8BIT, treat as a photo
Since you really want to verify that the binary data is a photo, it would make sense to run it through an image library. RMagick comes to mind. The documentation will show you how to verify that any binary data is actually JPEG encoded. You will then also be able to store other properties such as width and height.
If you don't have RMagick installed, an alternative approach would be to save the data into a Tempfile, drop down into Unix (assuming you are on Unix) and try to identify the file. If your system has ImageMagick installed, the identify command will tell you all about images. But just calling file on it will tell you this too:
~/Pictures$ file P1020359.jpg
P1020359.jpg: JPEG image data, EXIF standard, comment: "AppleMark"
You need to call the identify and file commands in a shell from Ruby:
%x(identify #{tempfile})
%x(file #{tempfile})
I am working on creating an Easter egg for a website. I want to hide some lines of data in an image`s EXIF comment field which can be used to reconstitute a tarball that contains a text file with a riddle. Is this possible? If so, how do I get the code/data for the tarball which I can then include in the EXIF data?
It is possible, although you may have to encode the data (e.g. using base64) if you use a field intended to hold ASCII text.
The best way to generate a tarball is to use the appropriately-named tar utility.