I am getting multiple pngs from another process from its standard output as a stream. I want to take this memory stream and save it as multiple png files. I have looked at PngBitmapEncoder/PngBitmapDecoder, but I can't seem to get a multiple page out of it (whenever I create a decoder using PngBitmapDecoder.Create, decoder.Frames.Count is always 1. Here is how I create the decoder:
BitmapDecoder decoder = PngBitmapDecoder.Create(memStream,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
Am I doing something wrong?
There is no such thing a s multi-page PNG.
A PNG decoder will never return more than one frame.
You need to read each image separately.
You have sample here on msdn
http://msdn.microsoft.com/fr-fr/library/system.windows.media.imaging.bitmapdecoder.aspx
i am getting multiple pngs from another process from its standard
output as a stream
It's not clear what this means. PNG does not support multiple image or pages in one file. Are you receiving several PNG files concatenated as a single stream? If this is the case (that would be rather strange) you don't really need to decode the PNGs, just to split the stream and write each one (blindly) in a different file. A quick and dirty approach (not totally foolproof) is to scan the stream for the PNG signature (8 bytes) to detect the start of a new image.
If you rather want to decode the succesive streams (seems overkill), you can use this pngcs library, instantiating a PngReader for each image; just be sure to call
PngReader.ShouldCloseStream(false) so that the stream is not close when each image ends.
Yes, there is such a thing as a multi-page PNG. It's called MNG (Multiple-image Network Graphics). It's almost as old as PNG (Check libpng.org for the format MNG).
And there is a C# library that can help you with that
http://www.codeproject.com/Articles/35289/NET-MNG-Viewer
In the last 4 years a format called APNG (Animated Portable Network Graphics) started being accepted and used by browsers like Firefox. There is a wrapper for C#
https://code.google.com/p/sharpapng/
Saving multiple PNGs using one file only will be much faster than using multiple files.
Related
Currently I am utilizing a List-variable to store BitmapSources provided by a camera and save them as an AVI file with the help of SharpAvi. In a second step I then encode the saved file via Nrecos ffmpeg wrapper to decrease file size. Finally I delete the original AVI file and only keep the encoded one.
To me this seems poorly designed and might cause harmful write-cycles to the SSD the application is running on (I'll probably create up to a TB a day in unencoded video), which is why I want to change it to a more integrated solution utilizing the PC's RAM.
SharpAvi as well as Nreco however rely on creating and reading actual files.
Nreco does have the ConvertLiveMedia method that accepts a stream - however in my experiments it simply did not create a file while giving me no error warnings.
Ok I think I solved it:
I changed the SharpAvi code so that the AviWriter has an additional constructor accepting a MemoryStream instead of just a string. This MemoryStream is then passed to the BinaryWriter and no FileStream is created.
Also the close Method had to be changed so that the MemoryStream stays alive even when the BinaryWriter is closed.fileWriter.Closeis replaced with
if (fileWriter.BaseStream is MemoryStream)
fileWriter.Flush();
else
fileWriter.Close();
This leaves me with a usable MemoryStream in my main application.
memstream.Position = 0; //crucial or otherwise ffmpeg will not work
var task = nrecoconverter.ConvertLiveMedia(memstream, "avi", filepath, "avi", settings);
task.Start();
task.Wait();
Edit: SharpAvi has officially been changed on github to allow the use of Streams now.
I am trying to get image from a stream (MemoryStream to be more precise). I can not find anything from Microsoft that can solve my problem.
I am getting my streams from SQL so if there is some way to get an image from there, it will be OK.
I have checked ffmpeg and the problem is that I need to save the video files. The files can reach up to 2GB and if there is a way not writing to the disk it will be helpful. If there is a way to read only the first 10MB or other limited size and read the image from it, that can also be a solution.
Video feed might be as simple as raw uncompressed video frames side by side to more complex multiplexed file format compatible chunk of data, e.g. .MP4 file. While the former case might be pretty simple, the latter requires you to demultiplex the file, seek within the stream, start decoding, possibly skip a few frames, then grab the frame of interest. The point is that it might be not as simple as it seems.
Video processing APIs in Windows are DirectShow, Media Foundation. With DirectShow it is possible to create a custom data source on top of SQL backed data stream and stream from there fetching DB data on demand, using API interfaces components (stock and third party) to do the rest of the task.
It is possible to capture frames with free VideoConverter for .NET that actually is a wrapper to FFMpeg tool. The idea is using live streaming capabilities (to C# Stream) of VideoConverter for special FFMpeg format "rawvideo" that actually is bitmap stream that can be processed by C# program, something like that:
var videoConv = new FFMpegConverter();
var ffMpegTask = videoConv.ConvertLiveMedia(
"input.mp4",
null, // autodetect live stream format
rawBmpOutputStream, // this is your special stream that will capture bitmaps
"rawvideo",
new ConvertSettings() {
VideoFrameSize = "320x200", // lets resize to exact frame size
CustomOutputArgs = " -pix_fmt bgr24 ", // windows bitmap pixel format
VideoFrameRate = 5, // lets consume 5 frames per second
MaxDuration = 5 // lets consume live stream for first 5 seconds
});
VideoConverter can read live streams from another .NET Stream (if input format can be used with live stream conversion).
I'm having difficulties when trying to save huge images with C# (I'm talking about over one gigabyte).
Basically I'm trying to do this in parts - I have around 200 bitmap sources and I need a way to combine them before or after encoding them to a .png file.
I know this is going to require lots of RAM unless I somehow stream the data directly from hard drive but I have no idea how to do this either.
Each bitmap source is 895x895 pixels so combining the images after encoding doesn't seem easy because C# doesn't let you create a bitmap with size of 13425 x 13425.
This PngCs library (disclaimer: I'm the author) lets you read and write huge PNG images line by line, so that you don't need to keep the full image in memory; perhaps you find it useful.
I need to store XML data on a server that only accepts jpeg images. I thought of writing my XML data inside a valid jpeg file. After all, other than the jpeg header, the content of the image file is arbitrary data right?
Is it possible to produce a valid jpeg file, but have its "body" filled with custom bytes?
Of course, I also need to be able to decode the custom jpeg file and restore the data.
I'm not familiar with the jpeg file format, so I'd appreciate an explicit example.
Perhaps just appending the data to a small jpeg will work?
Create a small jpeg.
Append your (obfuscated/encrypted) XML to the file.
Upload to server.
FWIW, you can easily see this works using a Hex editor. Just create a small jpeg and append your xml to the end. Then open it using any image editor.
This is a perfectly valid thing to do to a jpeg file:
Will random data appended to a JPG make it unusable?
Uhmmm it is a strange architecture... but anyway I think this post would be useful:
How to Add 'Comments' to a JPEG File Using C#
so the proposal is add the data as a metadata of a jpeg blank image.
If you want to add your data as the actually jpeg data, you first create a BitmapSource with BitmapSource.Create and put your data in the buffer parameter. Than use the JpegBitmapEncoder to save it as a jpeg file (an example is here).
However, as far as I know, the .Net jpeg encoder is not lossless (even if you set it's quality to 100%) so you will need a third party library that can encode JPEG lossless.
I don't know of a JPEG specific way but there is a PNG/GIF method to encode arbitrary data and pixels. Check out this post. Some sites allow you to upload PNGs and GIFs renamed to JPEG so you could try that.
http://blog.nihilogic.dk/2008/05/compression-using-canvas-and-png.html
He's saving javascript but you could use and text, really.
I have a raw pixel data in a byte[] from a DICOM image.
Now I would like to convert this byte[] to an Image object.
I tried:
Image img = Image.FromStream(new MemoryStream(byteArray));
but this is not working for me. What else should I be using ?
One thing to be aware of is that a dicom "image" is not necessarily just image data. The dicom file format contains much more than raw image data. This may be where you're getting hung up. Consider checking out the dicom file standard which you should be able to find linked on the wikipedia article for dicom. This should help you figure out how to parse out the information you're actually interested in.
You have to do the following
Identify the PIXEL DATA tag from the file. You may use FileStream to read byte by byte.
Read the pixel data
Convert it to RGB
Create a BitMap object from the RGB
Use Graphics class to draw the BitMap on a panel.
The pixel data usually (if not always) ends up at the end of the DICOM data. If you can figure out width, height, stride and color depth, it should be doable to skip to the (7FE0,0010) data element value and just grab the succeeding bytes. This is the trick that most normal image viewers use when they show DICOM images.
There is a C# library called EvilDicom (http://rexcardan.com/evildicom/) that can be used to pull the image out of a DICOM file. It has a tutorial on how to do it on the website.
You should use GDCM.
Grassroots DiCoM is a C++ library for DICOM medical files. It is automatically wrapped to python/C#/Java (using swig). It supports RAW, JPEG 8/12/16bits (lossy/lossless), JPEG 2000, JPEG-LS, RLE and deflated (zlib).
It is portable and is known to run on most system (Win32, linux, MacOSX).
http://gdcm.sourceforge.net/wiki/index.php/GDCM_Release_2.4
See for example:
http://gdcm.sourceforge.net/html/DecompressImage_8cs-example.html
Are you working with a pure standard DICOM File? I've been maintainning a DICOM parser for over a two years and I came across some realy strange DICOM files that didn't completely fulfill the standard (companies implementing their "own" twisted standard DICOM files) . flush you byte array into a file and test whether your image viewer(irfanview, picassa or whatever) can show it. If your code is working with a normal JPEG stream then from my experience , 99.9999% chance that this simply because the file voilate the standard in some strange way ( and believe me , medical companies does that a lot)
Also note that DICOM standard support several variants of the JPEG standard . could be that the Bitmap class doesn't support the data you get from the DICOM file. Can you please write down the transfer syntax?
You are welcome to send me the file (if it's not big) yossi1981#gmail.com , I can check it out , There was a time I've been hex-editing DICOM file for a half a year.
DICOM is a ridiculous specification and I sincerely hope it gets overhauled in the near future. That said Offis has a software suite "DCMTK" which is fairly good at converting dicoms with the various popular encodings. Just trying to skip ahead in the file x-bytes will probably be fine for a single file but if you have a volume or several volumes a more robust strategy is in order. I used DCMTK's conversion code and just grabbed the image bits before they went into a pnm. The file you'll be looking for in DCMTK is dcm2pnm or possibly dcmj2pnm depending on the encoding scheme.
I had a problem with the scale window that I fixed with one of the runtime flags. DCMTK is open source and comes with fairly simple build instructions.