JPEG XR to Bitmap in C# - c#

I'm using C#, and need to process Jpeg-XR images. However, these images are presented in form of base64 strings, and need to be converted into Bitmap objects directly. I can write it into a file and convert it, but this significantly affects my running time.
I was wondering if anyone could help me with a sample code, or a hint?
(I already tried Magick.Net, but that didn't work for me, and also doesn't seem to be able to load a JXR image directly).
thanks a lot

JPEG XR is formerly known as HD Photo and Windows Media Photo.
You can use the class WmpBitmapDecoder in System.Windows.Media.Imaging in the WPF library to manipulate .jxr images.
This class Defines a decoder for Microsoft Windows Media Photo encoded images.
The following code convert JXR file to Bmp file:
using System.IO;
using System.Windows.Media.Imaging;
public class JXrLib
{
public static void JxrToBmp(string source, string target)
{
Stream imageStreamSource = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.Read);
WmpBitmapDecoder decoder = new WmpBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
var encoder = new BmpBitmapEncoder(); ;
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (var stream = new FileStream(target, FileMode.Create))
{
encoder.Save(stream);
}
}
}
The code is tested and running fine.
Alternative 2:
If you are interested of using Magick.Net, you can use jxrlib library in https://jxrlib.codeplex.com
Copy the file JXRDecApp.exe and JXREncApp.exe to your bin directory and read from a file on disk that has a .jxr extension.
(you have to compile jxrlib using visual studio)
Code example:
// Read first frame of jxr image
//JXRDecApp.exe ,JXREncApp.exe should be located in the path of binaries
using (MagickImage image = new MagickImage(#"images\myimage1.jxr"))
{
// Save frame as bmp
image.Write("myimage2.bmp");
// even , Save frame as jxr
image.Write("myimage2.jxr");
}

Related

How convert Image to png with imagemagik lib in C#?

I've write a aws Lambda to convert my images.
The process of the lambda function is to take input images of any format and in the case of non-png images, convert them to jpeg otherwise add some data and convert it to png by adding transparency. Finally save the generated images on s3.
I write a function in C# using a imagemagick library in .Net Core.
I've a problem with png conversion. The result image have a dashed border!
This is my method to PNG convert.
private MemoryStream ConvertToPNG(MemoryStream inputStream)
{
MemoryStream outputStream = new MemoryStream();
inputStream.Position = 0;
using (MagickImage image = new MagickImage())
{
image.Read(inputStream);
image.Quality = 90;
image.TransformColorSpace(ColorProfile.SRGB, ColorProfile.AdobeRGB1998);
image.Settings.Compression = CompressionMethod.NoCompression;
image.Format = MagickFormat.Png64;
image.Write(outputStream);
}
return outputStream;
}
I tried with another stack, using Pillow library in py and work, generated image is great. Unfortunately I am forced to use C # and .Net for obvious reasons.
Has anyone ever had this problem?
Thanks everyone for the contribution.

C# How to dispose of OpenFileDialog file

I use OpenFileDialog to get the path of an image and then set it to my image source property imgSelected.Source = new BitmapImage(new Uri(filenameSteg, UriKind.Absolute)); in a WPF application.
The thing is, I need to open that file again later but I can't open it since the file is being used by another process ( System.IO.IOException -> The process cannot access the file pathToFile because it is being used by another process.).
The code that needs to access it later it as follow :
bitmapSource = JpegBitmapDecoder.Create(File.Open(filenameSteg, FileMode.Open),
BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames[0];
This bitmapSource is used to give that image to a WriteableBitmap and from there I go through the pixels.
Is there any way to dispose of a File opened with an OpenFileDialog ?
I tried to cast to to IDisposable, to use a using block and so on but this thing is persistent.
EDIT :
1 - I tried this (#ctacke answer) :
using (var stream = File.Open(filenameSteg, FileMode.Open)){
bitmapSource = JpegBitmapDecoder.Create(stream, BitmapCreateOptions.None,
BitmapCacheOption.OnLoad).Frames[0];}
But it still gives me the error about the process being already in used by another process because even though it will be disposed after, I still am trying to open the same file (filenameSteg) than I opened in the OpenFileDialog. (Or at least, that's how I see it.)
2 - I then tried this (based on #ctacke recommended link:
using (FileStream fileStream = new FileStream(filenameSteg+1, FileMode.Create)){
MemoryStream memoryStream = new MemoryStream();
BitmapImage bi = new BitmapImage();
byte[] fileBytes = File.ReadAllBytes(filenameSteg);
memoryStream.Write(fileBytes, 0, fileBytes.Length);
memoryStream.Position = 0;
bi.BeginInit();
bi.StreamSource = memoryStream;
bi.EndInit();
bitmapSource = bi;}
Note : Notice that I here ask for filenameSteg +1. That is because I wanted to test the rest of my method so I create a copy the file and simply added a 1 to its name. That being said, when using filenameSteg for real, it gave me the same error about being already in used which I again suspect is that I still am asking to open the same image that was previously opened in the OpenFileDialog.
3 - I thought of another approach which does not require me to dispose the opened image :
When I open the image for the first time in the OpenFileDialog, I store the byte array of the image in a variable so I could create the WriteableBitmap using the BitmapFactory and the byte array.
// This is in the OpenFileDialog. It is where I stock the image "pixels" in a byte array.
bytesArrayImage = File.ReadAllBytes(filenameSteg);
//And then later when I needed the WriteableBitmap, I used the byte array and the BitmapFactory
//imgSelected being the Image containing the image I opened in the OpenFileDialog, I used it's
//width and height
wb = BitmapFactory.New(Convert.ToInt32(imgSelected.Width),
Convert.ToInt32(imgSelected.Height)).FromByteArray(bytesArrayImage);
The problem with this approach is that, some pictures works fine and I can use the byte array to create the WriteableBitmap and go through it's pixels but in other cases it gives me an AccessViolationException stating : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.. In other words, trying to bypass the dispose problem got me into another problem.
You should release the original image, something like this:
if(imgSelected.Source != null)
{
imgSelected.Source.Dispose;
}
imgSelected.Source = new BitmapImage(new Uri(filenameSteg, UriKind.Absolute));
Next, File.Open returns a stream, which you need to explicitly release.
using(var stream = File.Open(filenameSteg, FileMode.Open))
{
var bitmapSource = JpegBitmapDecoder.Create(stream,
BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames[0];
}
See also: Load a BitmapSource and save using the same name in WPF -> IOException

Save XAML Image into file in metro apps

i convert a PDF file to BitmapImage in C#. After i manipulate it (resize, rotate) and i want to save it to new PNG or JPEG file but i'm not found how can i make that. I'm developed a windows store apps in C#.
According to this blog post: Save XAML as PNG in a Windows Store App
You should be able to do this using the class BitmapEncoder, the method BitmapSource.CopyPixels will give you the pixels data that BitmapEncoder requires.
Use LibPdf, for PDF to Image conversion
This library converts converts PDF file to an image. Supported image formats are PNG and BMP, but you can easily add more.
Usage example:
using (FileStream file = File.OpenRead(#"..\path\to\pdf\file.pdf")) // in file
{
var bytes = new byte[file.Length];
file.Read(bytes, 0, bytes.Length);
using (var pdf = new LibPdf(bytes))
{
byte[] pngBytes = pdf.GetImage(0,ImageType.PNG); // image type
using (var outFile = File.Create(#"..\path\to\pdf\file.png")) // out file
{
outFile.Write(pngBytes, 0, pngBytes.Length);
}
}
}
ImageMagick, you should also look at this freely available and powerful tool. It's capable of doing what you want and also provides some .NET bindings (as well as bindings to several other languages).

Preserving Image quality

I have a winform C# desktop application.
I have a constant stream of jpegs coming in.
I am comparing the current image with the previous 1.
By using a 3rd party tool - Emgu - I can create a new image that contains just the differences.
I then convert that image to a memory stream and then to a byte array.
In the receiving application I take this byte array and load the image via a memory stream using these bytes.
The trouble is that the image degrades quite a lot.
If I save the image to the hard drive before converting it to a memory stream on the client side the quality of the image is good.
The problem lies when i load it as a memory stream.
I encode it as jpeg.
If I encode it as a PNG before sending to the server the quality is good again.
The trouble with encoding to PNG the size in the byte array shoots up.
What my intention was all along was to reduce the number of bytes I have to upload to improve response time.
Am I doing something wrong or can this not be done?
This is my code:
Bitmap imgContainingDifference
= GetDiffFromEmgu(CurrentJpegImage, PreviousJpegImage);
using (System.IO.MemoryStream msIn = new System.IO.MemoryStream())
{
holding.Save(msIn, System.Drawing.Imaging.ImageFormat.Jpeg);
data = msIn.ToArray();
}
//test here
using (System.IO.MemoryStream msOut = new System.IO.MemoryStream(_data))
{
Bitmap testIMG = (Bitmap)Image.FromStream(msOut);
}
//result is image is poor/degrades
If I do this instead:
using (System.IO.MemoryStream msIn = new System.IO.MemoryStream())
{
holding.Save(msIn, System.Drawing.Imaging.ImageFormat.Png);
data = msIn.ToArray();
}
using (System.IO.MemoryStream msOut = new System.IO.MemoryStream(_data))
{
Bitmap testIMG = (Bitmap)Image.FromStream(msOut);
}
//Image is good BUT the size of the byte array is
//10 times the size of the CurrentFrame right at the start.
This is what the image looks like when using the kid suggestion from :
I have now tried using a encoder from the kind suggestion from #MagnatLU and I also get the same quality of image if I use FreeImage.Net.
You can set JPEG compression level when encoding your file to value that is the best empirical tradeoff between quality and size.

Compression image without very high quality image in c#

I do not need a very high quality image. I will sent this image with socket so I need this image small as possible I need a method to compression image
private void button1_Click_1(object sender, EventArgs e)
{
OpenFileDialog Open_File = new OpenFileDialog();
if (Open_File.ShowDialog() == DialogResult.OK)
{
FileStream fileStream = new FileStream(Open_File.FileName, FileMode.Open, FileAccess.Read);
int length = (int)fileStream.Length;
byte[] buffer = new byte[length];
fileStream.Read(buffer, 0, length);
Image x = byteArrayToImage(buffer);//this image I want to compression
//.............................
}
}
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
Motaz,
I worked on an image processing project some while back. The project required the Compression/Decompression of the images. You have two options to do what you want:
1) You can write the algorithm yourself.
2) You can use a library for the Compression/Decompression of the images.
If you want to use a library, you also have to options:
A- You can use open source libraries and articles available on the internet such as the following:
http://www.codeproject.com/Articles/4769/In-Memory-Image-Compression
Or you can use a library such as Aforge
B- You can use commercial library such as leadtools sdk that allows you to increase the compression by just changing the quality factor. Also, for their j2k format you can set the size you want the image to have. For a code sample: see the following links:
For quality factor:
www.leadtools.com/help/leadtools/v175/dh/co/leadtools.codecs~leadtools.codecs.codecspngoptions.html#Example_CS
http://www.leadtools.com/help/leadtools/v175/dh/co/leadtools.codecs~leadtools.codecs.codecsjpegoptions.html#Example_CS
For the setting the J2K file size:
www.leadtools.com/help/leadtools/v175/dh/co/leadtools.codecs~leadtools.codecs.codecsjpeg2000options.html#Example_CS
Using the TargetFileSize property you can set the file size.
In my cause, we decided to go with the commercial toolkit because it gave us more features, better quality and better performance.

Categories

Resources