2

I'm trying to convert a PDF page to a .NET Bitmap using Pdfium. I want to use it directly in the WPF so WinForm methods is not intended. I already asked this question (based on my initial understanding) as I was trying to do that using FPDF_RenderPage. From what I learnt till now from SDK and the sole .NET port of it (PdfViewer) there are two ways to render to a bitmap.

I want to know if I'm doing the steps correctly in first method specifically the memory device context and what is needed to correctly bring the native bitmap to .NET in second method.

  1. Using FPDF_RenderPage by feeding a memory device context

    var hMemDC = NativeMethods.CreateCompatibleDC(IntPtr.Zero);
    IntPtr hDC = NativeMethods.GetDC(IntPtr.Zero);
    
    // Create a bitmap for output 
    var hBitmap = NativeMethods.CreateCompatibleBitmap(hDC, width, height);
    
    // Select the bitmap into the memory DC 
    hBitmap = NativeMethods.SelectObject(hMemDC, hBitmap);
    
    IntPtr brush = NativeMethods.CreateSolidBrush((int)ColorTranslator.ToWin32(Color.White));
    NativeMethods.FillRgn(hMemDC, NativeMethods.CreateRectRgn(0, 0, width, height), brush);
    
    // _file is an instance of PdfFile from PdfViewer port
    // Now render the page onto the memory DC, which in turn changes the bitmap                 
    bool success = _file.RenderPDFPageToDC(
                 page,
                 hMemDC,
                 (int)dpiX, (int)dpiY,
                 bounds.X, bounds.Y, bounds.Width, bounds.Height,
                 true /* fitToBounds */,
                 true /* stretchToBounds */,
                 true /* keepAspectRatio */,
                 true /* centerInBounds */,
                 true /* autoRotate */,
                 forPrinting
            );
    
    hBitmap = NativeMethods.SelectObject(hMemDC, hBitmap);
    
    Bitmap myBitmap = Bitmap.FromHbitmap(hBitmap);
    
  2. Using FPDF_RenderPageBitmap

    IntPtr bitmapHandle = NativeMethods.FPDFBitmap_Create(bounds.Width, bounds.Height, 0);    
    
    // _file is an instance of PdfFile from PdfViewer port
    bool success = _file.RenderPDFPageToBitmap(
       page,
       bitmapHandle,
       (int)dpiX, (int)dpiY,
       bounds.X, bounds.Y, bounds.Width, bounds.Height,
       true /* fitToBounds */,
       true /* stretchToBounds */,
       true /* keepAspectRatio */,
       true /* centerInBounds */,
       true /* autoRotate */,
       forPrinting
    );                
    
    if (!success)
      throw new Win32Exception();
    else
    {
        byte[] bytes = new byte[bounds.Width * bounds.Height * 4];
        Marshal.Copy(bitmapHandle, bytes, 0, bytes.Length);
        bitmap = Convert_BGRA_TO_ARGB(bytes, bounds.Width, bounds.Height);
    }
    

// Convert BGRA to ARGB

    public Bitmap Convert_BGRA_TO_ARGB(byte[] DATA, int width, int height)
    {
        Bitmap Bm = new Bitmap(width, height, PixelFormat.Format32bppArgb);

        int index;
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // BGRA TO ARGB
                index = 4 * (x + (y * width));
                Color c = Color.FromArgb(
                     DATA[index + 3],
                    DATA[index + 2],
                    DATA[index + 1],
                    DATA[index + 0]);
                Bm.SetPixel(x, y, c);
            }
        }
        return Bm;
    }

Render: enter image description here

Community
  • 1
  • 1
Mohsen Afshin
  • 13,273
  • 10
  • 65
  • 90
  • Looks like you aren't accounting for the stride for each row (think DWORD alignment). [This](https://stackoverflow.com/questions/28049838/correct-stride-formula-for-bitmap) formula should help. – Studlyer Sep 22 '17 at 20:59

0 Answers0