C# WPF Image loading and saving - c#

I have been trying to load my image in bitmap image class. But whenever I am trying to save an image (using a third party library called Image Processor) the quality drops. So my question is that:
Is there any way i can save image in its full quality?
src.BeginInit();
src.UriSource = new Uri("picture.jpg", UriKind.Relative);
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();

You can achieve image saving without any thirdparty libraries. But you should know, that saving JPEG always drops quality a bit - its a nature of that format, not an issue with library. Using the JpegBitmapEncoder you can configure the quality, and with the maximum value you will not see a picture degradation, but anyway it present. So, consider using of PNG format instead.
Here is a short snippet how to load and save a JPEG image:
// Load from file or any other source.
var uri = new Uri(#"D:\InputImage.jpg");
var bitmap = new BitmapImage(uri);
// Save to file.
var encoder = new JpegBitmapEncoder(); // Or any other, e.g. PngBitmapEncoder for PNG.
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.QualityLevel = 100; // Set quality level 1-100.
using (var stream = new FileStream(#"D:\OutputImage.jpg", FileMode.Create))
{
encoder.Save(stream);
}

WebImage works very well and I use often this class in my application. It has a lot of nice built-in features, for example, saving proportins when resizing an image:
WebImage wi = new WebImage(imageName);
wi.Resize(314, 235, true);
wi.Save(imageName, "png");

Related

Creating a Bitmap object with transparency from a URI of a PNG file

I'm having issues trying to use a PNG image with a build action of 'Resource' with the map marker generation of GMap.NET, which expects type Bitmap.
I create a BitmapImage using the pack Uri, and then convert the BitmapImage to a Bitmap by using the code provided by Sascha Henning in their answer here:
Converting BitmapImage to Bitmap and vice versa
The resulting code is as follows:
BitmapImage bmi = new BitmapImage(
new Uri("pack://application:,,,/Images/MapMarker_JobComplete.png"));
System.Drawing.Bitmap markerBitmap = Helpers.BitmapImageToBitmap(bmi);
GMarkerGoogle marker = new GMarkerGoogle(jobLoc, markerBitmap);
Where Helpers.BitmapImageToBitmap() is:
public static Bitmap BitmapImageToBitmap(BitmapImage bitmapSource)
{
using( MemoryStream outstream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapSource));
enc.Save(outstream);
return new System.Drawing.Bitmap(outstream);
}
}
The above works, but the image is rendered with a black background instead of a transparent background. I can only assume that the conversion to a BitmapImage or from a BitmapImage to Bitmap is responsible.
I found a reference to needing to save PNG images to a lower depth, but with currently installed software (Affinity), I couldn't export with a bit depth of 16 as said, only PNG-8 (bit depth of 8; red background, presumaby due to reduced quality) or the standard PNG-24 (bit depth of 32; black background)
PNG-24 PNG-8
Currently to get the desired results (transparency supported), I use the PNG with a build action of 'Content', with the following code:
System.Drawing.Image imgMarker = System.Drawing.Bitmap.FromFile(
System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
"Images/MapMarker_JobComplete.png"));
GMarkerGoogle marker = new GMarkerGoogle(jobLoc, (System.Drawing.Bitmap)imgMarker);
The above works fine, so Bitmap must support transparency, but this leaves me with the PNG files as content and I would prefer them embedded into the executable, as well as be able to use the pack Uri in XAML if/when needed.
It's clear that there's some knowledge that I'm missing or haven't been able to glean out, and there's quite a few topics about people wanting to preserve transparency, but with the end result of a BitmapImage and not a Bitmap like I require.
Copying user2819245's old comment here, as it was/is the answer:
I am not sure, but i guess (based on your explanation) that BmpBitmapEncoder does not support (creating) 32bpp BMPs. Why don't you try using PngBitmapEncoder instead?

TiffBitmapEncoder not saving in color

Our users needed the ability to change images (rotate\insert scan between pages etc) so I wrote an app that allows them to load a Tiff image and edit as needed.
The problem I have is that when the image is saved it is saved as black and white and not in color. The loaded image displays in color no problem so it seems that it is the saving that is causing the issue.
This is the code I am using to save the Tiff image from an array of BitmapSource:
//create encoder
TiffBitmapEncoder tiffEncoder = new TiffBitmapEncoder();
tiffEncoder.Compression = TiffCompressOption.Ccitt4;
//loop through images and create frames
foreach (BitmapSource src in bitmapList)
{
BitmapFrame bmFrame = BitmapFrame.Create(src);
tiffEncoder.Frames.Add(bmFrame);
}
//create stream to write file
FileStream fStream = null;
try
{
fStream = new FileStream(path, FileMode.Create);
//Save Tiff image to disc
tiffEncoder.Save(fStream);
}
finally
{
if (fStream != null)
{
fStream.Close();
}
}
When I look at the properties of the original file it has a bit depth of 24 but the newly saved image has a bit depth of 1 (black and white?), is this the problem?
I am new to working with Tiffs so any guidance would be greatly appreciated.
Please let me know if you need any other info.
Tx
The images are probably converted to black/white, because of the TiffCompressOption.Ccitt4 compression in use. The CCITT compressions are intended for fax documents, and only supports black/white images.
Instead, use a more general purpose compression, like LZW or Deflate. This will let the image data pass unchanged as 24 or 32 bit color data.

Modify existing BitmapImage in memory

My WinRT XAML page loads an image from a file asset like this:
Image img = new Image(); // Windows.UI.Xaml.Controls.Image
BitmapImage bmp = new BitmapImage(new Uri(Page.BaseUri, "Assets/myImage.png"));
img.Source = bmp;
So far so good. Now, at a later time, I'd like to do some transformations such as resizing and cropping.
It looks like this can be done using BitmapEncoder and BitmapTransform, but will require reading and writing to disk - in particular, writing out the modified image to a new file.
Since my app does potentially do many transformations, I'd prefer to do this in memory without any disk I/O but can't figure out how.
Any ideas?
Have a look at the WriteableBitmap class, this allows modifications in memory.
WriteableBitmap bmi2 = new WriteableBitmap(bitmapSource);
More infomation can be found here:
http://msdn.microsoft.com/en-us/library/windows/apps/BR243259

how to convert a jpeg in an array into a bitmap

I have a functioning application in c#/.net that currently accepts raw image data in a bayer format from a set of embedded cameras and converts them to jpeg images. To save transmission time, I have modified the embedded devices to encode the images as jpegs prior to transmission. I'm an experienced embedded programmer but a total c#/.net noob. I have managed to modify the application to save the arrays to file with a jpeg name using this snippet: ( the offset of 5 is to skip header data in the transmission frame)
FileStream stream = File.Create(fileName);
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(multiBuff.msgData, 5, multiBuff.dataSize - 5);
writer.Close();
The files open up fine, but now I want to treat the data as a bitmap without having to save & load from file. I tried the following on the data array:
MemoryStream stream = new MemoryStream(data);
BinaryReader reader = new BinaryReader(stream);
byte[] headerData = reader.ReadBytes(5);
Bitmap bmpImage = new Bitmap(stream);
But this throws a parameter not valid exception. As a newbie, I'm a little overwhelmed with all the classes and methods for images and it seems like what I'm doing should be commonplace, but I can't find any examples in the usual places. Any ideas?
I think you are looking for Bitmap.FromStream() :
Bitmap bmpImage = (Bitmap)Bitmap.FromStream(stream);
Actually using new Bitmap(stream) should have worked as well - this means that the data in the stream does not constitute a valid image - are you sure the jpg is valid? Can you save it to disk and open it i.e. in Paint to test?
You use the Image class.
Image image;
using (MemoryStream stream = new MemoryStream(data))
{
image = Image.FromStream(stream);
}
FYI it didn't work because reader.ReadBytes(5) returns the 5 first bytes of stream not the bytes after position 5

Saving Bitmap Images in WPF via C#

I display images in my WPF app using BitmapImage.
However, I would like an easy way to save these (as JPG) to a different location (ideally into a Stream or object that can be passed around).
Is it possible using BitmapImage or do I have to use other means? If so what other means are there for either loading an Image and saving as JPG or converting a BitmapImage into this element to then save off?
Thanks
Something like:
public byte[] GetJPGFromImageControl(BitmapImage imageC)
{
MemoryStream memStream = new MemoryStream();
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(imageC));
encoder.Save(memStream);
return memStream.GetBuffer();
}
(from: WPF Image to byte[])

Categories