Search code examples
c#silverlightjpegdicomfjcore

C#: Decoding JPEG images with 12-bit precision using Silverlight FJCore library?


In my C# Silverlight application, I am trying to decode DICOM images in compressed JPEG transfer syntax, using the FJCore class library.

The DICOM images are normally compressed with 12-bit precision. When trying to decode such an image using the original FJCore source code, I get an exception saying "Unsupported codec type", because in the original FJCore implementation only SOF0 (Baseline DCT) and SOF2 (Progressive DCT) Start-of-Frame markers are supported. If I change the implementation to also accept the SOF1 marker (Extended Sequential DCT) and treat SOF1 frames the same way as SOF0 frames, the images are decoded, but only 8 bits are accounted for.

A typical 12-bit precision image now looks like this after decoding with the modified FJCore library:

12-bit precision JPEG image encoded to 8-bit precision by FJCore

Ideally, the image should look like this:

12-bit precision JPEG image encoded to full 12-bit precision

As far as I have been able to tell from the FJCore implementation, the image precision is recorded in the JpegFrame class, but it is never used. The original FJCore implementation seems to only fully support grayscale images with 8 bit precision.

I am planning to "take the bull by the horns" and try to extend FJCore myself to support 12-bit precision for grayscale images. But before I do, I thought I should pose the question here in StackOverflow to see if anyone has encountered and solved this problem before? In that case, I would be very happy to learn how you solved the problem.

Many thanks in advance!
Anders @ Cureos


Solution

  • I just updated my own JPEG decoder to handle the extended mode and what I needed to change was my inverse DCT. Before changing the code, the output looked similar to your sample image above. I have always stored 16-bit coefficient values from the entropy decode, but my DCT calculation was corrupting the larger values by using 16-bit integers to hold temporary values while doing the math. I changed the DCT code to use 32-bit integers for the calculations and that solved the problem.