How do I use pdfdraw.GetBitmap(...) in C/C++?

Q: We're using PDFNET in C++ and we have a question regarding how to
obtain the correct image data from GetBitmap() so that we can save it
to a BMP format:

Below is our sample code:

#include "PDF\Page.h"
#include "PDF\PDFNet.h"
#include "PDF\PDFDoc.h"
#include "PDF\PDFDraw.h"
#include <Filters/StdFile.h>
#include <Filters/FilterWriter.h>

int main()
{
  pdftron::PDFNet::Initialize();
  bool resourcesSet = pdftron::PDFNet::SetResourcesPath("resources\
\pdfnet.res");

  if (resourcesSet == true)
  {
    pdftron::PDF::PDFDraw draw;
    draw.SetRasterizerType(pdftron::PDF::PDFRasterizer::e_BuiltIn);

    pdftron::PDF::PDFDoc doc("C:\\input.pdf");

    pdftron::PDF::Page page = doc.GetPage(1);

    int width = 0, height = 0, stride = 0;
    double dpi = 0;

    const pdftron::UChar* dataRGBA = draw.GetBitmap(page, width, height,
stride, dpi, pdftron::PDF::PDFDraw::e_rgba);

    int dataLength = height * stride;

    pdftron::Filters::StdFile file("C:\\test_MAYBE.bmp",
pdftron::Filters::StdFile::e_write_mode);
    pdftron::Filters::FilterWriter writer(file);
    writer.WriteBuffer((char*)dataRGBA, dataLength);
    writer.Flush();
  }

  pdftron::PDFNet::Terminate();

  return 0;
}

We call pdftron::PDF::PDFDraw::GetBitmap() for our PDF and specify
e_rgba, we then write the resulting buffer to a file.
We then add the below bitmap header to the beginning of the file, to
specify a width of 782, height of 1012, bpp of 32, and an
image data size of 2374150

42 4D 00 00 00 00 00 00 00 00 36 00 00 00 28 00
00 00 0E 03 00 00 0C FC FF FF 01 00 20 00 00 00
00 00 06 3A 24 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00

1) The resulting BMP we get is not correct, the only way to get the
correct output is to substitute each
4th byte of image data (the 'A' byte) with the 2nd byte of data (or
the 'G' byte). This produces the correct BMP.
We would like to know if this is correct, we had assumed that no data
manipulation was necessary to produce RGBA data?

2) Another question we have is whether we specify e_rgb, e_rgba,
e_bgra, etc., the resutling stride is the same, in this case 782 * 4 =
3128.
Going off the formula ((width * bpp) + 7) / 8 to calculate stride,
3128 is correct but is only correct when bpp = 32. So we're not clear
on why GetBitmap() fills the stride value with 3128 when we specify
e_rgb for instance?

3) Also, whether we specify e_rgb or e_rgba for instance, in order for
the resulting bitmap (we create from the image data by adding
the bitmap header to the beginning) to be correct, we have to specify
32 as the bpp in the bitmap header whether it's RGB or RGBA.
We assumed that if we used e_rgb that bpp = 24 for instance, if we
specify the bpp as 24 in the bitmap header of the resulting bitmap we
get a very
warped image. The only way we get the correct BMP is to specify bpp
as 32 in the bitmap header, this leads us to believe that the image
data
that GetBitmap() is producing is always 32bpp, is this correct?

4) When we specify e_rgb, the resulting bitmap (we create from the
image data by adding the bitmap header to the beginning) is not
correct. Should data manipulation be necessary to correctly obtain
RGB data from GetBitmap?

If you can provide us with some direction as the correct way to render
a PDF to a RGB24 for instance that would be most helpful.
-------
A:

The simplest way to export to BMP is to simply call Export() method as
shown below:
  pdfdraw.Export(page, "my.bmp, "BMP");

In case you would rather export the rendered the image on your own...

Passing in e_rgba parameter would return RGBA data in that order (I
believe that BMP is storing 32-bit data in the reverse order - i.e. as
ABRG). Also it seems that some information in your BMP header is
incorrect or is missing (e.g. file size, data offset, etc). You may
also need to take into account image stride which may not be dword
aligned (although in case of 32-bit RGBA output it should be).

why GetBitmap() fills the stride value with 3128 when we specify e_rgb for instance?

PDFDraw is free to assume any value for the stride parameter. This is
important for efficiency and future compatibility reasons. As
mentioned before, you shouldn't assume any fixed value for the stride
parameter. If your export file requires certain padding you could add
it as part of your image export function.

For example, assuming that you are rendering an image using e_rgb
PixelFormat, you could reshuffle the data and add the padding for 24-
bit BMP output as shown in the following snippet:

int write_scan_stride = width * 3;
if (write_scan_stride % 4) {
  write_scan_stride += 4 - (write_scan_stride % 4);
}

// Write the bitmap header
.... use bmphdr_sz + bmpnfo_sz + height*write_scan_stride as file
size...

// Write bitmap data...

const UChar* ptr;
int pad_bytes = write_scan_stride - width * 3;
const UChar *row = image_buf + (height-1) * stride; // write
scanlines in the reverse order.
for (int y=0; y<height; ++y, row -= stride) {
  ptr = row;
  // Swap the order from RGB to BGR..
  for (int x=0; x<width; ++x, ptr+=3) {
    WriteByte(*(ptr+2)); // B
    WriteByte (*(ptr+1)); // G
    WriteByte (*(ptr )); // R
  }
  for (int i=0; i<pad_bytes; ++i) WriteByte (0);
}

4) Should data manipulation be necessary to correctly obtain RGB data from GetBitmap?

Depending on the output image format you are serializing to, you may
need to do some data manipulation.

As another example of how to create Windows Bitmaps using image data
from pdfdraw.GetBitmap() you may want to take a look at PDFView C++
sample project (http://www.pdftron.com/net/samplecode/
PDFViewView.cpp). In this sample the image data is rendered using 32-
bit e_bgra mode and the bitmap header is initialized in
CPDFViewView::InitBitmapInfo(). If you render the image this way there
no need to for any data modification during BMP export (this approach
is appropriate if you need to efficiently draw the bitmap on the
screen).