Set JPEG metadata - implementation problems - c#

Through prior research, I've found that is isn't too hard to set the MetaData properties on an image. For example, I can read a JPEG image into a Bitmap object and change its "Original Taken" date through the image's SetPropertyItem method (I've already researched the format and enumeration for doing this, too).
However, although the actual MetaData part seems easy, I am faced with a couple of irritating implementation issues:
1) When I call Save() on the bitmap, it doesn't seem that the image's original encoding settings are used. As a result, the compression level changes (presumably to some default value); I can see the file size shrink considerably after my Save() call. I know that you can customize the encoding settings for an image within the call to Save(), but honestly, I only want to change the picture's metadata; isn't there any easy way to just save the image using its original encoding settings? Even if I could directly reference the image's existing encoding settings in the Save() call, that would help.
2) Apparently, the original file is locked when you read it into a Bitmap object. As a result, I can't save the image under its original file name without a lot of messing around: currently, I'm drawing the image I read from file onto an offscreen bitmap, disposing of the original image, and then saving the offscreen bitmap. Again, this seems like an awful lot of extra work when all I want to do is update the metadata in an image file.
Any suggestions you can offer would be most appreciated... the amount of work I'm having to do just to update a JPEG file's meta data (most of which has nothing to do with the actual metadata change) leads me to wonder if I'm missing some easier or better ways of doing this.

What you want to do is edit the EXIF data. What you are doing now is recompressing the image, and this will cause quality loss, as you have noticed.
See this code sample for editing EXIF: http://www.dreamincode.net/code/snippet3144.htm

Related

difference between image bitmap and fromFile methods in c#

I found out that there are two ways to read the image info using default c# library. One of them is
System.Drawing.Image image = new Bitmap("file..path");
Another one is :
Image image = Image.FromFile("file..path");
May anyone tell me which one will run faster if I need to read a lot of images(nearly 100TB data).
I found out that there are two ways to read the image info
You know, if it is just the image info you are after then I wouldn't use either function as both load the entire image into memory from disk - a rather wasteful exercise of the computer's resources.
Instead you should just load the image file header whether it be EXIF; BITMAPINFOHEADER or other depending on the image format. There are ways to load such info via .NET (see links below).
Image headers
Apart from RAW image file formats (not necessarily that which is output from SLR cameras), most image file formats have a header that can be loaded prior to loading the image raster data into memory from disk. In fact it is a generally a requirement that the header is read first because otherwise you would not know how much memory to allocate prior to loading the image.
How wide is it?
How tall?
How many bits per pixel (colour depth)?
...and so forth. These are all answered by reading the image file header first. As the name suggests, information about the image is generally near the start of the file. Exact formats and layout depends on the file format in question. See BMP; PNG resources for more info.
Here's some suggestions on loading image headers
Obtain image width and height without loading image in .NET?
Getting image dimensions without reading the entire file
Bitmap Storage

when to resize an image?

I am building a online store for hand made jewelry. Of course there is a lot of high quality pictures that i need to show, first in small sizes and when a client clicks on the image, than redirect him to a page with a same image in high quality.
What is a better way:
on saving image save two images one in low quality and the second in original quality
or
onload image use Bitmap to lower the quality?
It depends.
Resizing on demand causes a heavier server load. When a lot of people are accessing the site this might be an issue.
Resizing on upload reduces this problem.
Resizing on your client using image processing software does usually produce the best quality with low file size.
The "normal" resize-functions in .NET is far away from that quality.
Also: Consider caching. The IIS offers everything to use this, perhaps in combination with an eTag.
I would resize them on upload/addition. I would also make sure to name them appropriately to their size, like gold_ring_640_480.jpg.
Then, should I need to change the size of the preview, I would add functionality to resize it lazily on demand if a required picture size does not exist.
Image_240p exists?
not: create
save _240p
use the image
You don't need to save all image size . For my all website, I get image on the fly depend on dimension that I need. When have a request with file size, I will create a resized image on disk. In the next time, with the same request, I just check:
if file already in browse cached, I will return the header mention that website just get image from cache.
if file not in browse cache, I will check that "the file already generate in disk". If the file is available, just return the file to response
if file not in browse cache and not in disk. I will generate it and return the file content.
For image caching you can see this reference :https://developers.google.com/speed/docs/best-practices/caching
For image resize on the fly by .net: you can refer to : http://www.codeproject.com/Articles/191424/Resizing-an-Image-On-The-Fly-using-NET

Reading and Writing all JPEG metadata in Silverlight

I've developed a Silverlight application that needs to compress JPEG images on the client. I've been using a library called FJCore to achieve this goal.
One of the biggest issues I'm encountering, however, is the fact that this toolkit requires you to convert the JPEG to a WriteableBitmap first which strips off all the metadata associated with the JPEG such as EXIF, XMP, JFIF, etc. I've modified the source of the FJCore library to persist the EXIF, compress the image, and then reattach the EXIF data. This process works but loses other types of metadata information.
Instead of having to implement a function that saves and writes each different type of metadata that exists for the JPEG format, I am looking for a simplified approach that will allow me to extract all metadata, regardless of type or format, use the FJCore toolkit to compress/resize that image, and then reattach all the previously saved metadata. Some direction or sample code that could help me achieve my goal would be greatly appreciated. Remember, this is a Silverlight application, so those .NET libraries are what I have to work with.
Thank you.
You can do this using FJCore aka ImageTools. All you need to do is add this on line 212:
// Exif. Do something?
headers.Add(header);
https://github.com/briandonahue/FluxJpeg.Core/blob/master/FJCore/Decoder/JpegDecoder.cs
And make sure you copy those headers when resizing:
jpegOut = new DecodedJpeg(
new ImageResizer(jpegIn.Image)
.Resize(320, ResamplingFilters.NearestNeighbor),
jpegIn.MetaHeaders); // Retain EXIF details
Recompile and you should be good to go.

Image size got bigger when trying to reduce its size

I am trying to resize a pic of format jpg, reduce it's resolution in order for it to be smaller when I download it to the site HTML. Using the tutorial in the link:
image resizing tutorial
I managed to resize the resolution including cropping when needed. My problem is that actual size of the image got bigger instead of smaller as I expected.
Any ideas please?
If a JPEG image file is getting bigger when you are reducing the dimensions, it's because you are saving it with a higher quality setting than the original.
This is quite normal when you use a compressed image format like jpeg. It is caused by the filter you selected when you reduced the image size. A default selection for the Graphics class, for example, is InterpolationMode.Bilinear. Which does a pretty nice job of making a good looking shrunk version of the image. But at a cost of adding a lot of extra colors to the image due to the filtering algorithm. The resulting image won't compress as well as the original and can in fact require more storage.
You'd have to pick a lower quality filter to avoid this, like InterpolationMode.NearestNeighbor. Yes, won't look nearly as good. In general you should avoid re-compressing an image that was already compressed in a lossy format like jpeg.

saving the inkcanvas

In my application the user can create multiple objects (so called drawings) each of which has a SurfaceInkCanvas, very similar with the Photopad (the Photo Paint app)in the SDKSamples(provided by MS Surface SP1 SDK).
What would be the best way to save the content of the inkCanvas(the drawing object) given the fact that there may be tens or even hundreds of them created.
After some research, one option popped-out: converting it to an image, jpg or png, but this method doesn't seem that scalable IMO.
Would it be possible to store the points in a database(preferably sqlite)?
The goal is to be able to restore the drawings(contents of the inkCanvas) for further editing upon loading.
Saving to an image isn't really viable for what it sounds like you want to do because restoring vector lines from a bitmap is much harder and potentially lossy than the vector to bitmap conversion, in addition to not being very efficient from a data density perspective.
You could write some code to save and restore the collection of lines that's stored in the Strokes property. This would allow you to reduce the size of your data down to a minimum and easily store in a database. Each Stroke has some data about what the line looks like and a set of points that make up the line. It's fairly simple to extract and restore that data to another InkCanvas when reloading.
You might also be able to use XamlWriter/XamlReader to just serialize the entire InkCanvas to xml but you would need to be able to put the new deserialized instance into your UI and make sure there aren't any naming or resource complications in your XAML that tend to cause errors with this method.
there's already a format that microsoft uses to save the strokes in, which is ISF - standing for Ink Serialized format that saves the Strokes collection in an .isf file.
However in this example each drawing is saved in a separate (but small-size) .isf file that can be easily loaded back for further editing or even converting (exporting) it to bitmap.
So a good method would be to save each drawing in files(even though this is a bit more expensive, time-wise, than simply storing it in a sqlite db)and save the path of each along with an id in the database to identify each session.
Any suggestion for further optimising this method from a scalability point of view?

Categories