[.NET] Rendering zoomed in rectangle using PDFDraw.

Q: I am using the PDFDraw object to create a bitmap and then
displaying the bitmap (I did this because of highlighting and in some
cases needing to overlay the page). I am setting a scale factor and
zoom factor. I then set a crop region before getting the bitmap to
display. The zooming seems backward and cropping is not coming out
right. I have stepped through to make sure the calculations compare
and they do. I am attaching the latest version. I have tried various
things, but I am missing something. Any pointers would be
appreciated.

public void DrawPage( PaintEventArgs e, Rectangle clientRect, int
rotateAngle, float scale, float zoomFactor, float scrollOffsetX, float
scrollOffsetY, int pageNumber )
  {
    if (pageNumber == 0)
      pageNumber = 1;
    pos = MakeFilePosition(pageNumber - 1, 0);
    // Save the paramters for subsequent get text
    if( pdfDoc == null )
      return;

    if( pdfDraw == null )
      pdfDraw = new PDFDraw();
    PageIterator pageitr = null;
    Page.Rotate origPage_rotation = Page.Rotate.e_0;
    Page.Rotate page_rotation = Page.Rotate.e_0;
    PDFDoc pDoc = null;

    pdftron.PDF.Page currPage = null;

    try
    {
      pageitr = pdfDoc.GetPageIterator( this.CurrentPageNumber + 1 );
      currPage = pageitr.Current();

      page_rotation = currPage.GetRotation();
      origPage_rotation = page_rotation;

      if( rotateAngle == 90 )
      {
        switch(page_rotation)
        {
          case Page.Rotate.e_0:
            page_rotation = Page.Rotate.e_90;
            break;
          case Page.Rotate.e_90:
            page_rotation = Page.Rotate.e_180;
            break;
          case Page.Rotate.e_180:
            page_rotation = Page.Rotate.e_270;
            break;
          case Page.Rotate.e_270:
            page_rotation = Page.Rotate.e_0;
            break;
        }
        currPage.SetRotation(page_rotation);
      }
      else if( rotateAngle == 180 )
      {
        switch(page_rotation)
        {
          case Page.Rotate.e_0:
            page_rotation = Page.Rotate.e_180;
            break;
          case Page.Rotate.e_90:
            page_rotation = Page.Rotate.e_270;
            break;
          case Page.Rotate.e_180:
            page_rotation = Page.Rotate.e_0;
            break;
          case Page.Rotate.e_270:
            page_rotation = Page.Rotate.e_90;
            break;
        }
        currPage.SetRotation(page_rotation);
      }
      else if( rotateAngle == 270 )
      {
        switch(page_rotation)
        {
          case Page.Rotate.e_0:
            page_rotation = Page.Rotate.e_270;
            break;
          case Page.Rotate.e_90:
            page_rotation = Page.Rotate.e_0;
            break;
          case Page.Rotate.e_180:
            page_rotation = Page.Rotate.e_90;
            break;
          case Page.Rotate.e_270:
            page_rotation = Page.Rotate.e_180;
            break;
        }
        currPage.SetRotation(page_rotation);
      }
      Rect pageRect = currPage.GetMediaBox();
      float dpi = e.Graphics.DpiX;

      float pageWidthInBitmap = (float)pageRect.Width();
      float pageHeightInBitmap = (float)pageRect.Height();
      float fScrollOffsetX = scrollOffsetX * 72.0f / dpi;
      float fScrollOffsetY = scrollOffsetY * 72.0f / dpi;

      // We want to compute the cropbox based on the desired scale
      Matrix bitMatrix = new Matrix();
      PointF[] scrnDims = new PointF[2];
      scrnDims[0] = new PointF(0.0f, 0.0f);
      scrnDims[1] = new PointF((float)clientRect.Width * 72.0f / dpi,
(float)clientRect.Height * 72.0f / dpi );

      if( page_rotation == Page.Rotate.e_0 )
        bitMatrix = new Matrix( scale * zoomFactor, 0.0f, 0.0f, scale *
zoomFactor, -fScrollOffsetX, - fScrollOffsetY );
      else if( page_rotation == Page.Rotate.e_90 )
        bitMatrix = new Matrix( 0.0f, scale * zoomFactor, -scale *
zoomFactor, 0.0f, pageHeightInBitmap * scale * zoomFactor -
fScrollOffsetX, - fScrollOffsetY );
      else if( page_rotation == Page.Rotate.e_180 )
        bitMatrix = new Matrix( -scale * zoomFactor, 0.0f, 0.0f, -scale *
zoomFactor, pageWidthInBitmap * scale * zoomFactor - fScrollOffsetX,
pageHeightInBitmap * scale * zoomFactor - fScrollOffsetY );
      else if( page_rotation == Page.Rotate.e_270 )
        bitMatrix = new Matrix( 0.0f, -scale * zoomFactor, scale *
zoomFactor, 0.0f, -fScrollOffsetX, pageWidthInBitmap * scale *
zoomFactor - fScrollOffsetY );

      Matrix invBitMatrix = new Matrix(bitMatrix.Elements[0],
bitMatrix.Elements[1], bitMatrix.Elements[2], bitMatrix.Elements[3],
bitMatrix.Elements[4], bitMatrix.Elements[5] );
      invBitMatrix.Invert();

      invBitMatrix.TransformPoints(scrnDims);

      Matrix transToPDF;
      if( page_rotation == Page.Rotate.e_0 || page_rotation ==
Page.Rotate.e_180 )
        transToPDF = new Matrix(1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
(float)pageRect.Height());
      else
        transToPDF = new Matrix(1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
(float)pageRect.Height());

      transToPDF.TransformPoints( scrnDims );
      // Now we should have the points in the mediabox.
      // We need to limit them to the
      int x = (int)scrnDims[0].X;
      int y = (int)scrnDims[0].Y;
      int xw = (int)scrnDims[1].X;
      int yh = (int)scrnDims[1].Y;
      if( x < 0 )
        x = 0;
      if( y < 0 )
        y = 0;
      Rect crpRect = new Rect((double)x, (double)y, (double)xw,
(double)yh);
      currPage.SetCropBox( crpRect );
      pdfDraw.SetDPI(dpi * scale * zoomFactor );
      pdfDraw.SetPageBox(Page.Box.e_crop);
      System.Drawing.Bitmap bmp = pdfDraw.GetBitmap(currPage);
      // Render the bitmap to the screen and exit.
      Matrix oBitMatrix = new Matrix();
      oBitMatrix = new Matrix( 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
(float)this.frameToolBarHeight );
      e.Graphics.Transform = oBitMatrix;
      e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
      e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
      e.Graphics.DrawImage(bmp, 0, 0);
      bmp.Dispose();
    }
    catch(Exception ex)
    {
      MessageBox.Show(ex.StackTrace, ex.Message);
      pdfDraw = null;
    }
    if(pageitr != null && origPage_rotation != page_rotation )
      currPage.SetRotation(origPage_rotation);
    if( pDoc != null )
    {
      pDoc.Close();
      pDoc.Dispose();
      pDoc = null;
    }
  }
}
-------
A:

The problem does not seem to be related to PDFNet. Changing the
following line:

e.Graphics.DrawImage(bmp, 0, 0);

to

e.Graphics.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height)

solves the problem.

I wonder why you are using PDFDraw class instead of PDFView (e.g.
along the lines of PDFViewSimple or PDFView)? Using PDFView it is much
simpler to implement an interactive PDF viewer.

If there is a reason to use PDFDraw it is possible that you could
somewhat simplify the code. For example, I am not sure what is the
reason for re-setting the page rotation. If the rotation is not reset,
PDFDraw.GetBitmap() will return a rotated bitmap. You could also use
page.GetDefaultMatrix() to obtain a matrix that maps un-rotated/un-
cropped PDF coordinates to cropped/rotates coordinate space and use it
to map zoom rectangle. In this case the initial 'zoom' rectangle
should be Rect(0,0,page.GetPageWidth(),page.GetPageHeight()). Still,
it is hard to say whether this approach is any 'better'.