New to Telerik UI for WinForms? Download free 30-day trial

Use a custom JPXDecode filter with RadPdfViewer

Product Version Product Author Last modified
2014_3_1104 RadPdfViewer for WinForms Dimitar Karamfilov December 25, 2014

Problem

Currently, RadPdfViewer does not support the JPXDecode filter and documents that uses this filter will display a blank pages.

Solution

Use a custom filter to view such documents. The following example uses the OpenJPEG library to convert the images that are using this particular filter. To use this library with RadPdfViewer you should create a custom class that implements the IPdfFilter interface. Then you can perform the conversion in the Decode method:  

class JpxFilterCodec : IPdfFilter
{
    private readonly string OpenJpegPath = @"..\..\openjpeg-2.1.0-win32-x86\bin\opj_decompress";

    public byte[] Encode(PdfObject encodedObject, byte[] inputData)
    {
        throw new NotImplementedException();
    }

    public byte[] Decode(PdfObject decodedObject, byte[] inputData, DecodeParameters decodeParameters)
    {
        string filename = Guid.NewGuid().ToString();

        File.WriteAllBytes(filename + ".j2k", inputData);
        ProcessStartInfo processInfo = new ProcessStartInfo(OpenJpegPath, " -i " + filename + ".j2k -o " + filename + ".bmp");
        processInfo.WorkingDirectory = Directory.GetCurrentDirectory();
        processInfo.WindowStyle = ProcessWindowStyle.Hidden;
        processInfo.CreateNoWindow = true;
        var process = Process.Start(processInfo);
        process.WaitForExit();
        System.Drawing.Bitmap bitmap = System.Drawing.Image.FromFile(filename + ".bmp") as Bitmap;
        if (bitmap == null)
        {
            return new byte[0];
        }

        BitmapData bitmapData = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size), ImageLockMode.ReadOnly, bitmap.PixelFormat);

        int length = bitmapData.Stride * bitmapData.Height;
        int stride = bitmapData.Stride;
        byte[] bytes = new byte[length];

        System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, bytes, 0, length);
        bitmap.UnlockBits(bitmapData);

        byte[] bytePixels = new byte[bitmapData.Width * bitmapData.Height * 3];

        int resLength = bytePixels.Length;
        for (int i = 0; i < resLength; i++)
        {
            int row = i / (bitmapData.Width * 3);
            int col = i % (bitmapData.Width * 3);
            bytePixels[i] = bytes[row * stride + col];
        }

        bitmap.Dispose();
        File.Delete(filename + ".j2k");
        File.Delete(filename + ".bmp");

        return bytePixels;
    }

    public string Name
    {
        get { return "JPXDecode"; }
    }
}

Currently, you can use the above class by calling the RegisterFilter method with reflection:

Telerik.Windows.Pdf.Documents.Fixed.FormatProviders.Old.Pdf.Filters.FiltersManager.RegisterFilter(new JpxFilterCodec());

You can download a VB and C# project from the following link.

In this article