I get Out of Memory exception when using System.Drawing.Graphics.FromImage (using latest versions of .NET software on Windows 2012 server), ONLY on a very few specific image files. Most of the time the code works fine.
Typical answers to above issue indicate that certain resources are not being released.
Please consider the following before answering:-
This specific image is 34KB in size, is a .JPG image. Server is idle and has over 32GB RAM.
If I look at properties of
this jpg file, using windows explorer, by right-clicking on file, Windows says: 96 dpi and 32 bit depth.
BUT, if I open this jpg file using any graphics program (e.g. photoshop), the file properties show as: 72 dpi and 24 bit depth.
So, there is a mis-match between what I think file header properties
say and what the file actually contains.
Further, if I open the jpg
file using a graphics program and just re-save without changing
anything, the file properties in windows explorer now match/read correct
(72 dpi and 24 bit depth); and the file is processed by
System.Drawing.Graphics correctly, without throwing exception.
Due to my limited knowledge of the subject, I don't know if the file header of an image file can contain different data from actual file contents.
Questions:
How can I fix this problem? Or how can I tell System.Drawing.Graphics to ignore file header data and just look at actual image file contents? (as all graphics programs such as photoshop appear to do).
Thanks!
While I'm not a guru on the JPEG file format i did some research on the subject and here's what i found that could help you with your problem/questions.
Note that this answer will assume rather than specifically pinpoint the source of your problem due to the lack of an example file to inspect and tell what differs it from what the .Net/GDI+ JPEG/JFIF decoder expects.
The JPEG/JFIF format
Starting off, you might want to have some insight into the JPEG/JFIF format itself. After all, you have just encountered a file that .Net/GDI+ cannot load/parse. Since i don't have the file you experience issues with i would suggest you load it up in a hex editor of choice... that has the capability to highlight the file based on a template/code/parser.
I used 010 Editor and the JPEG Template from Sweetscape's online template repository.
010 Editor comes with a 30-day free trial.
What you are specifically looking for is the SOFn identifier and data in your bad JPEG.
In the SOFn data i can see that my image is Y (154) pixels high and X (640) pixels wide with a precision of 8 bits per component using 3 components, making it 24 bits per pixel.
The JPEG/JFIF format is a huge mix of many different implementations/formats. Obviously, you won't find every variant of the format in any library that has been around since long long ago before the odd JPEG formats appeared. Which the GDI+ library has.
In your case, i suspect you have run into the commonly asked about CMYK color profile on your JPEG files.
The .Net implementation
You said you used System.Drawing.Graphics.FromImage so i will assume your code looks like one of the following:
Graphics.FromImage(Image.FromFile("nope.jpg"));
Graphics.FromImage(Image.FromFile("nope.jpg", true));
Graphics.FromImage(Image.FromStream(nopeJpegStream));
From those calls, you may get an OutOfMemoryException when the native gdiplus.dll calls...
GdipGetImageGraphicsContext
GdipLoadImageFromFile
GdipLoadImageFromFileICM (or their respective *Stream variants) or
GdipImageForceValidation
... returns code 3 or 5 (Out of memory or Insufficient buffer respectively)
Which i gathered from referencesource.microsoft.com looking through the .Net sources there.
In any case, this most likely isn't an issue with .Net but an issue with GDI+ (gdiplus.dll) which Microsoft doesn't provide source code for. Which also means that there is no way of controlling how the image loads using the .Net wrappers and there's no way to check WHY it fails. (though i still suspect your JPEG is saved with CMYK)
Unfortunately, you are going to find many many more of these strange exceptions/errors as you move along in GDI+ land. As the library is all but deprecated in favor of the Windows Presentation Framework (WPF) and the Windows Imaging Component. (WIC)
My own testing
Since you never provided an image or any additional details on the subject i attempted to reproduce your issue. Which was a task in of itself, Image.FromFile (GdipLoadImageFromFile) will fail on many different file formats. At least it doesn't care what the file extension is, which thankfully Photoshop does.
So with your information, i finally managed to reproduce a .jpg file that loads fine in Photoshop, shows DPI as 96 and bit depth as 32. Of course, if i knew more about the JPEG format i probably could have gotten to the solution right away.
Showing this file (which i had to set to CMYK color space in Photoshop) in 010 Editor gave me the following SOFn data: Y (154) pixels high and X (640) pixels wide with a precision of 8 bits per component using 4 components, making it 32 bits per pixel.
I suspect you would see the same on your "bad" file.
And yes, Image.FromFile now throws an OutOfMemoryException!
Possible solutions
Use an external library for loading image files. (An exercise i leave to you but ImageMagick A.K.A Magick.NET seems like a good bet)
Make use of a command line tool (invoked when you get this exception) that can convert an image from one format to another. Or from JPEG to JPEG as it may be in this case. (Once again, ImageMagick's "convert" command line tool seems like a good bet)
Use the Windows Presentation Framework assemblies...
public static Image ImageFromFileWpf(string filename) {
/* Load the image into an encoder using the Presentation Framework.
* This is done by adding a frame (which in laymans terms is a layer) to a class derived BitmapEncoder.
* Only TIFF, Gif and JPEG XR supports multiple frames.
* Since we are going to convert our image to a GDI+ resource we won't support this as GDI+ doesn't (really) support it either.
* If you want/need support for layers/animated Gif files, create a similar method to this one that takes a BitmapFrame as an argument and then...
* 1. Instanciate the appropriate BitmapDecoder.
* 2. Iterate over the BitmapDecoders frames, feeding them to the new method.
* 3. Store the returned images in a collection of images.
*
* Finally, i opted to use a PngBitmapEncoder here which supports image transparency.
*/
var bitmapEncoder = new PngBitmapEncoder();
bitmapEncoder.Frames.Add(BitmapFrame.Create(new Uri(filename)));
// Use a memorystream as a handover from one file format to another.
using (var memoryStream = new MemoryStream()) {
bitmapEncoder.Save(memoryStream);
/* We MUST create a copy of our image from stream, MSDN specifically states that the stream must remain
* open throughout the lifetime of the image.
* We cannot instanciate the Image class, so we instanciate a Bitmap from our temporary image instead.
* Bitmaps are derived from Image anyways, so this is perfectly fine.
*/
var tempImage = Image.FromStream(memoryStream);
return new Bitmap(tempImage);
}
}
Based on this answer...
... Which i would say is a good option as it keeps you within the .Net framework.
Please keep in mind that when the method returns, you do specifically get a PNG image back. If you call Image.Save(string) on it you WILL save a PNG file, no matter what extension you save it as.
There is an overload Image.Save(string, ImageFormat) that will save the file using the intended file format. However, using that overload with ImageFormat.Jpeg will cause a loss in quality in the resulting file on more than one level.
That can be somewhat remedied by using the third overload:
foreach (var encoder in ImageCodecInfo.GetImageEncoders()) {
if (encoder.MimeType == "image/jpeg")
image.Save(filename, encoder, new EncoderParameters { Param = new [] { new EncoderParameter(Encoder.Quality, 100L) }});
}
Which, at least, will save a JPEG with "almost" no compression. GDI+ still doesn't do a good job at it.
However, no matter how much you twist and turn it. GDI+ will not be as good as a proper image library, which once again would most likely be ImageMagick. The further away you can get from GDI+, the better off you will be.
Conclusion / TL:DR and other notes.
Q: Can i load these files in .Net?
A: Yes, with a bit of fiddling and not using GDI+ for the initial loading of the file as GDI+ doesn't support the CMYK color space in JPEG files.
And even so, GDI+ lacks support for many things which is why i would recommend an external image library over GDI+.
Q: Mismatch in DPI and bit depth for file between Windows and <insert photo app here>
A: This is just proof that Windows JPEG loading differs from other applications JPEG loading routines. Only applications that use GDI or GDI+ would see the same information that Windows does when showing image details.
If you are using Windows 7+ then it isn't using GDI+ to show the information nor the image. It is using WPF or WIC to do so which are somewhat more up to date.
Q: If I open the jpg file using a graphics program and just re-save without changing anything, the file properties in windows explorer now match/read correct (72 dpi and 24 bit depth)
A: If you are using Adobe Photoshop and you use "Save for web" then the JPEG image will not be saved in CMYK format. Use "Save As..." instead and you will find that the color space (and bit depth) stays the same.
However, i wasn't able to reproduce your discrepancy in DPI and bit depth when loading my file in Photoshop. They are reported as the same in both Windows and Photoshop.
I had the same issue with this bug - seems as though the Graphics / Bitmap / Image library throws an exception with certain malformed images. Narrowing it down more than that, as Cadde shows, is difficult.
Following on from the great answer made by Cadde (which left using an external library as an exercise to the reader), I changed my code to the following using MagickNet which you can get here, or simply with NuGet: PM> Install-Package Magick.NET-Q16-x86.
The code tries to create a Graphics object from the image, and if it fails, uses ImageMagick to load the image again, convert to a Bitmap, and attempts to load from there.
Image bitmap = Bitmap.FromFile(filename, false);
Graphics graphics = null;
try
{
graphics = Graphics.FromImage(bitmap);
}
catch (OutOfMemoryException oome)
{
// Well, this looks like a buggy image.
// Try using alternate method
ImageMagick.MagickImage image = new ImageMagick.MagickImage(filename);
image.Resize(image.Width, image.Height);
image.Quality = 90;
image.CompressionMethod = ImageMagick.CompressionMethod.JPEG;
graphics = Graphics.FromImage(image.ToBitmap());
}
I had the same problem. My jpg file was generated from Photoshop. A simple solution is to open the jpg file with Winodws Paint, and save as a new jpg file. Import the new jpg file to C# project and the problem will be disappear.
Related
I am using C# and want to save images using JPEG format. However .NET reduces quality of the images and saves them with compression that is not enough.
I want to save files with their original quality and size. I am using the following code but compression and quality are not like the original ones.
Bitmap bm = (Bitmap)Image.FromFile(FilePath);
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo ici = null;
foreach (ImageCodecInfo codec in codecs)
{
if (codec.MimeType == "image/jpeg")
ici = codec;
}
EncoderParameters ep = new EncoderParameters();
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100);
bm.Save("C:\\quality" + x.ToString() + ".jpg", ici, ep);
I am archiving studio photos and quality and compression is very important. Thanks.
The .Net encoder built-in to the library (at least the default Windows library provided by Microsoft) is pretty bad:
http://b9dev.blogspot.com/2013/06/nets-built-in-jpeg-encoder-convenient.html
Partial Update
I'm now using an approach outlined here, that uses ImageMagick for the resize then jpegoptim for the final compression, with far better results. I realize that's a partial answer but I'll expand on this once time allows.
Older Answer
ImageMagick is the best choice I've found so far. It performs relatively solid jpeg compression.
http://magick.codeplex.com/
It has a couple downsides:
It's better but not perfect. In particular, its Chroma subsampling is set to high detail at 90% or above, then jumps down to a lower detail level - one that can introduce a lot of artifacts. If you want to ignore subsampling, this is actually pretty convenient. But if you wanted high-detail subsampling at say, 50%, you have a larger challenge ahead. It also still won't quite hit quality/compression levels of Photoshop or Google PageSpeed.
It has a special deployment burden on the server that's very easy to miss. It requires a Visual Studio 2008 SDK lib installed. This lib is available on any dev machine with Visual Studio on it, but then you hit the server for the first time and it implodes with an obscure error. It's one of those lurking gotchas most people won't have scripted/automated, and you'll trip over it during some future server migration.
Oldest Answer
I dug around and came across a project to implement a C# JPEG encoder by translating a C project over:
http://www.codeproject.com/Articles/83225/A-Simple-JPEG-Encoder-in-C
which I've simplified slightly:
https://github.com/b9chris/ArpanJpegEncoder
It produces much higher quality JPEGs than the .Net built-in, but still is not as good as Gimp's or Photoshop's. Filesizes also tend to be larger.
BitMiracle's implementation is practically identical to the .Net built-in - same quality problems.
It's likely that just wrapping an existing open source implementation, like Google's jpeg_optimizer in PageSpeed Tools - seemingly libjpeg underneath, would be the most efficient option.
Update
ArpanJpegEncoder appears to have issues once it's deployed - maybe I need to increase the trust level of the code, or perhaps something else is going on. Locally it writes images fine, but once deployed I get a blank black image from it every time. I'll update if I determine the cause. Just a warning to others considering it.
It looks like you're setting the quality to 100%. That means that there will be no compression.
If you change the compression level (80, 50, etc.) and you're unsatisifed with the quality, you may want to try a different image library. LEADTools has a good (non-free) engine.
UPDATE: As a commenter mentioned, 100% quality still does not mean lossless compression when using JPEG. Loading the image, doing something to it, and then saving it again will ultimately result in image degradation. If you need to alter and save an image without losing any of the data you need to use a lossless format such as TIFF, PNG or BMP. I'd go with compressed TIFF (since it's still lossless even though it's compressed) or PNG.
Compression and quality are always a trade off.
JPEGs are always going to be lossy.
You may want to consider using PNG and minifying the files using PNGCrush or PNGauntlet
Regarding the setup of the compression level in .NET, please check this link (everything included): http://msdn.microsoft.com/en-us/library/bb882583.aspx
Rearding your question:
Usually you will save the uploaded image from users as PNG, then you use this PNG as base to generate your JPGs with different sizes (and you put a watermark ONLY on the JPGs, never on the original PNG!)
Advantage of this is: if you change your images-dimensions later on for your platform, you have the original PNG saved and based on this you can re-compute any new image sizes.
It must save the file like its orjinal quality and size
That doesn't make a lot of sense. When you are using lossy compression you are going to lose some information by definition. The point of compressing an image is to reduce the file size. If you need high quality and jpeg isn't doing it for you you may have to go with some type of lossless compression, but your file sizes will not be reduced by much. You could always try using the 'standard' library for compressing to jpeg (libjpeg) and see if that gives you any different results (I doubt it, but I don't know what .NET is using under the hood.)
Compressing the jpeg format by its very nature reduces quality. Perhaps you should look into file compression, such as #ziplib. You may be able to get a reasonable compression over a group of files.
This is for a .NET 4.5 Console Application running on a 64-bit Windows 8 system with 32GB of memory. The application is targeted for 64-bit platforms and has the gcAllowVeryLargeObjects flag enabled, which allows the application create objects larger than .NET limit of 2Gb. So, I am able to create an array of integers as large as 15GB.
I create a 32,767 by 32,767 pixel System.Windows.Media.Imaging.WriteableBitmap which uses WIC (Windows Imaging Component and not GDI+ as WIC can handle higher resolution than GDI+) using the following constructor
WriteableBitmap wbit = new WriteableBitmap(32767, 32767, 300, 300, PixelFormats.Bgra32, null);
I have tried to save it as a JPG using following code
using (FileStream stream = new FileStream("c:\\test.jpg",FileMode.Create))
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(wbit));
encoder.Save(stream);
}
I have also tried to save it as a PNG using following code
using (FileStream stream = new FileStream("c:\\test.png",FileMode.Create))
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(wbit));
encoder.Save(stream);
}
For both JPG and PNG, I can go up to 23,170 x 23,170 resolution, and it work fine, but going up to 23,171 x 23,171 throws the following exception
System.AccessViolationException: Attempted to read or write protected memory. Tis is often an indication that other memoryis corrupt. at MS.Wind32.PresentationCore.UnsafeNativeMethods.WICBitmapFrameEncode.WriteSource(SafeMILHandle THIS_PTR, SafeMILHandle pIBitmapSource, Int32Rect& r) at System.Windows.Media.Imaging.BitmapEncoder.Save(Stream stream)
Does anyone know the cause of this exception, and how I might be able to get around it so that I can save the full maximum resolution at 32,767 x 32,767? Maybe I have to use another encoder or even start looking outside .NET framework. I would ideally like to be able to work with images at the JPEG maximum resolution of 65,535 x 65,535, or even higher at 100,000 x 100,000 pixels in PNG. I would appreciate any help with this matter or suggestion towards the right direction. Thanks.
You're right about the JPEG format itself supporting higher resolutions. I tested using a huge JPEG image that's 40,000 x 33,000 pixels in size. The JPEG failed to load using System.Drawing.Bitmap, but it opened correctly using at least 2 different programs:
Windows 7 Photo Viewer, probably because it uses WIC, not GDI+.
IrfanView 64-bit, but it resized it to half-width and half-height
during loading.
This indicates the test JPEG image was indeed valid even though GDI+ can't load it.
Since this is not a limitation of the JPEG specification, it must be a limitation within Microsoft’s implementation. It’s unlikely there’s a work-around with their encoder here. If you must have a higher resolution (and you indicated you do), your best solution is likely to find a different library to do the encoding.
Is this possible or do I have to use WPF. I am new to Winforms and have created a couple simple applications, now I need to read a TIFF file and then display a subsection of it...
I tried doing something like this:
Graphics g = e.Graphics;
Bitmap b = new Bitmap(Image.FromFile(#"W:\ILHSR_Merged_2011\compressed\overviews\ILHSR11_0405-101-1.tif"));
g.DrawImage(b, 10, 10, 350, 300);
But I get out of memory exceptions. Can someone point me to some readin, or is this simply something that should be developed in WPF.
I think you need to implement you own TIFF loader using libTiff.
TIFF image format allow to store image data in tiles. LibTiff allows you to load single tiles: in this way you can display only portion of the image (without decoding the entire TIFF!, that can have prohibitive sizes).
Unfortunately, I don't think that .NET imaging supports that TIFF feature. My suggestion is to wrap libTiff in a library written in C++/CLI, and integrate it in your application.
(Due comment: if some existing library has already wrapped libTiff, and its interface match nicely with your application, even the better)
If you need to display parts, consider using tiled Tif files, and possibly even image pyramids (see TIF pyramid for background info on how to create/use them) tif files. All of these can be read with LibTiff and LibTiff.NET
Of course this depends on how often you need to do it. My experience is that very large bitmaps cannot be displayed properly using 32bit windows versions, unless the file itself is tiled. I have made a wrapper for LibTiff.NET, which allows Tile access also for non tiled (uncompressed, or line based) files. Of course, access is slower then; you'd need to read the entire rows which are on display. Still response time was reasonable for gigapixel images.
BitMiracle LibTiff.NET mentioned in previous post/comment works great: see How to implement pan/zoom on gigapixel bitmaps? and How to implement pan/zoom on gigapixel bitmaps?; it is a native c# implementation of LibTiff, which I found easier to handle than a wrapper class (because there is no unmanaged memory blocks to take care of in c# app).
[Edit]Added link to TIF pyramid image documentation[/Edit]
I am using C# and want to save images using JPEG format. However .NET reduces quality of the images and saves them with compression that is not enough.
I want to save files with their original quality and size. I am using the following code but compression and quality are not like the original ones.
Bitmap bm = (Bitmap)Image.FromFile(FilePath);
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo ici = null;
foreach (ImageCodecInfo codec in codecs)
{
if (codec.MimeType == "image/jpeg")
ici = codec;
}
EncoderParameters ep = new EncoderParameters();
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100);
bm.Save("C:\\quality" + x.ToString() + ".jpg", ici, ep);
I am archiving studio photos and quality and compression is very important. Thanks.
The .Net encoder built-in to the library (at least the default Windows library provided by Microsoft) is pretty bad:
http://b9dev.blogspot.com/2013/06/nets-built-in-jpeg-encoder-convenient.html
Partial Update
I'm now using an approach outlined here, that uses ImageMagick for the resize then jpegoptim for the final compression, with far better results. I realize that's a partial answer but I'll expand on this once time allows.
Older Answer
ImageMagick is the best choice I've found so far. It performs relatively solid jpeg compression.
http://magick.codeplex.com/
It has a couple downsides:
It's better but not perfect. In particular, its Chroma subsampling is set to high detail at 90% or above, then jumps down to a lower detail level - one that can introduce a lot of artifacts. If you want to ignore subsampling, this is actually pretty convenient. But if you wanted high-detail subsampling at say, 50%, you have a larger challenge ahead. It also still won't quite hit quality/compression levels of Photoshop or Google PageSpeed.
It has a special deployment burden on the server that's very easy to miss. It requires a Visual Studio 2008 SDK lib installed. This lib is available on any dev machine with Visual Studio on it, but then you hit the server for the first time and it implodes with an obscure error. It's one of those lurking gotchas most people won't have scripted/automated, and you'll trip over it during some future server migration.
Oldest Answer
I dug around and came across a project to implement a C# JPEG encoder by translating a C project over:
http://www.codeproject.com/Articles/83225/A-Simple-JPEG-Encoder-in-C
which I've simplified slightly:
https://github.com/b9chris/ArpanJpegEncoder
It produces much higher quality JPEGs than the .Net built-in, but still is not as good as Gimp's or Photoshop's. Filesizes also tend to be larger.
BitMiracle's implementation is practically identical to the .Net built-in - same quality problems.
It's likely that just wrapping an existing open source implementation, like Google's jpeg_optimizer in PageSpeed Tools - seemingly libjpeg underneath, would be the most efficient option.
Update
ArpanJpegEncoder appears to have issues once it's deployed - maybe I need to increase the trust level of the code, or perhaps something else is going on. Locally it writes images fine, but once deployed I get a blank black image from it every time. I'll update if I determine the cause. Just a warning to others considering it.
It looks like you're setting the quality to 100%. That means that there will be no compression.
If you change the compression level (80, 50, etc.) and you're unsatisifed with the quality, you may want to try a different image library. LEADTools has a good (non-free) engine.
UPDATE: As a commenter mentioned, 100% quality still does not mean lossless compression when using JPEG. Loading the image, doing something to it, and then saving it again will ultimately result in image degradation. If you need to alter and save an image without losing any of the data you need to use a lossless format such as TIFF, PNG or BMP. I'd go with compressed TIFF (since it's still lossless even though it's compressed) or PNG.
Compression and quality are always a trade off.
JPEGs are always going to be lossy.
You may want to consider using PNG and minifying the files using PNGCrush or PNGauntlet
Regarding the setup of the compression level in .NET, please check this link (everything included): http://msdn.microsoft.com/en-us/library/bb882583.aspx
Rearding your question:
Usually you will save the uploaded image from users as PNG, then you use this PNG as base to generate your JPGs with different sizes (and you put a watermark ONLY on the JPGs, never on the original PNG!)
Advantage of this is: if you change your images-dimensions later on for your platform, you have the original PNG saved and based on this you can re-compute any new image sizes.
It must save the file like its orjinal quality and size
That doesn't make a lot of sense. When you are using lossy compression you are going to lose some information by definition. The point of compressing an image is to reduce the file size. If you need high quality and jpeg isn't doing it for you you may have to go with some type of lossless compression, but your file sizes will not be reduced by much. You could always try using the 'standard' library for compressing to jpeg (libjpeg) and see if that gives you any different results (I doubt it, but I don't know what .NET is using under the hood.)
Compressing the jpeg format by its very nature reduces quality. Perhaps you should look into file compression, such as #ziplib. You may be able to get a reasonable compression over a group of files.
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.