PDF preview using MuPDf library [SOLVED]

Hit to all!

I’m struggling guys, I reached a good point but now I need some precious help from you.

In my application (only Windows for now) I need to preview a pdf file inside a component or viewport.
I’ve integrated MuPDF library inside my juce app project (Visual Studio 2012).

I’m facing this problem: trying to feed a juce Image with the raw pixel data coming from MuPDF APIs. Unfortunatelly the facility method ImageCache::getFromMemory(...) doesn’t work because it cannot recognize the format (jpg, gif and png). My raw data I think is something close to BMP but I’m ot sure, without header.

I’ve tried something using BitmapData class inside Image class but seems I cannot overwrite the uint8 data pointer, right?

Have you any idea to solve the problem?

Thank you!


Depending on what the data is, you might need to write yourself a custom ImageType class?

Hi @jules,
I’m trying to understand reading the mupdf code, but I think it could be bitmap due to the fact that in the example app, done in standard C, it takes the samples pointer and pass to Windows drawing apis like this:

typedef struct tagBITMAPINFOHEADER{
        DWORD      biSize;
        LONG       biWidth;
        LONG       biHeight;
        WORD       biPlanes;
        WORD       biBitCount;
        DWORD      biCompression;
        DWORD      biSizeImage;
        LONG       biXPelsPerMeter;
        LONG       biYPelsPerMeter;
        DWORD      biClrUsed;
        DWORD      biClrImportant;

typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER    bmiHeader;
    RGBQUAD             bmiColors[1];

static BITMAPINFO *dibinf;

int image_w = fz_pixmap_width(gapp.ctx, gapp.image);
int image_h = fz_pixmap_height(gapp.ctx, gapp.image);
int image_n = fz_pixmap_components(gapp.ctx, gapp.image);
unsigned char *samples = fz_pixmap_samples(gapp.ctx, gapp.image);

				gapp.panx, gapp.pany, image_w, image_h,
				0, 0, 0, image_h, samples,
				dibinf, DIB_RGB_COLORS);

The image data of a BMP follows the BITMAPINFOHEADER in memory., so.

void* hImage = … // a pointer to your BMP image
memcpy(&ds,hImage, sizeof(ds));
int effwdt = ((((ds.biBitCount * ds.biWidth ) + 31) / 32) * 4);

unsigned char* pbBits = (unsigned char*)hImage + ds.biSize + ds.biClrUsed * sizeof(RGBQuad);[/code]

Check to see the value of ds.biBitCount. For you this could be 8 or 24, since you might be working in greyscale PDF.

here’s what i do for 24,

int w = ds.biWidth;
int h = ds.biHeight;
  Image img(Image::RGB, w, h, false); // make RGB juce image
                Image::BitmapData bd(img, 0, 0, w, h, Image::BitmapData::writeOnly); // access bits
                  memcpy(bd.data, pbBits, effwdt * h);

like a hacker, i just memcpy the data in, although there will be padding in a 24 bit image. I just assume the padding is the same!

Sorry, if this is not very clear, i just cut & pasted some of my code. i do something similar to you but not the exact same.

hope this helps,

Thank you! I found it very clear. My current escamotage is exporting the pdf page as png and re-import it with juce, but it is a slow solution.

Now I try yours.

if you have 8 bit data (and its not palettized), you could copy in the data similarly, but the padding might be different.

Alternatively, you could create a juce RGB anyhow and go through setting R, G and B to the same. I’ve had problems with Juce `SingleChannel’ images (because sooner or later you want alpha).

Hi to all, after many trials I've tried the right solution for MuPDF:

m_pdfApp.image: is the MuPDF pixmap

        int w = m_pdfApp.image->w;
        int h = m_pdfApp.image->h;
        int n = m_pdfApp.image->n;

        Image img(Image::ARGB, w, h, false); // make ARGB juce image
        Image::BitmapData bd(img, 0, 0, w, h, Image::BitmapData::writeOnly); // access bits
        memcpy(bd.data, fz_pixmap_samples(m_pdfApp.ctx, m_pdfApp.image), w * h * n );

thanks to all for the right inspiration! Love juce community!