How to render the PDF page as EMF or meta file in PDFium - pdfium

Currently I have generated the PDF page as bitmap by using FPDF_RenderPageBitmap method.
is there any method for rendering the PDF page as EMF or as metafile in PDFium?

In the pdfium project there is a sample folder that has a pdfium_test.cc file that has examples of output in different formats. PNG, EMF, BMP, TXT, and PPM are all in the at the present time.
The current code to render an EMF
void WriteEmf(FPDF_PAGE page, const char* pdf_name, int num) {
int width = static_cast<int>(FPDF_GetPageWidth(page));
int height = static_cast<int>(FPDF_GetPageHeight(page));
char filename[256];
snprintf(filename, sizeof(filename), "%s.%d.emf", pdf_name, num);
HDC dc = CreateEnhMetaFileA(nullptr, filename, nullptr, nullptr);
HRGN rgn = CreateRectRgn(0, 0, width, height);
SelectClipRgn(dc, rgn);
DeleteObject(rgn);
SelectObject(dc, GetStockObject(NULL_PEN));
SelectObject(dc, GetStockObject(WHITE_BRUSH));
// If a PS_NULL pen is used, the dimensions of the rectangle are 1 pixel less.
Rectangle(dc, 0, 0, width + 1, height + 1);
FPDF_RenderPage(dc, page, 0, 0, width, height, 0,
FPDF_ANNOT | FPDF_PRINTING | FPDF_NO_CATCH);
DeleteEnhMetaFile(CloseEnhMetaFile(dc));
}

On Windows, you want to call FPDF_RenderPage and pass in the HDC this should allow you to get the EMF data out. You can see the chromium printing code for example usage. There is also FPDF_SetPrintMode which lets you set different modes.

Related

Convert from Android.Media.Image to Android.Graphics.Bitmap (possibily with Xamarin)

I have a Android.Media.Image frame acquired from Camera2 API Preview (in a Xamarin app), that I want to process.
The image format is YUV_420_888.
In a previous iteration I was able to get a Android.Graphics.Bitmap from the CameraPreview (but not anymore), and with that bitmap I was able to:
crop it
convert it to JPEG, save it or send it to server
convert it to a Mat to process with Emgu in real time
I searched for how to convert from Android.Media.Image to Android.Graphics.Bitmap thinking it was going to be quite straightforward, but it's not.
I found mostly java code that I tried to convert to C# Xamarin but without success.
First step is supposed to be to convert to a YuvImage (found 2 different versions, hence the comments):
private static byte[] YUV_420_888toNV21(Android.Media.Image image)
{
byte[] nv21;
ByteBuffer yBuffer = image.GetPlanes()[0].Buffer;
ByteBuffer uBuffer = image.GetPlanes()[1].Buffer;
ByteBuffer vBuffer = image.GetPlanes()[2].Buffer;
int ySize = yBuffer.Remaining();
int uSize = uBuffer.Remaining();
int vSize = vBuffer.Remaining();
nv21 = new byte[ySize + uSize + vSize];
//yBuffer.Get(nv21, 0, ySize);
//vBuffer.Get(nv21, ySize, vSize);
//uBuffer.Get(nv21, ySize + vSize, uSize);
yBuffer.Get(nv21, 0, ySize);
uBuffer.Get(nv21, ySize, uSize);
vBuffer.Get(nv21, ySize + uSize, vSize);
return nv21;
}
And then the saving:
var bbitmap = YUV_420_888toNV21(image);
YuvImage yuv = new YuvImage(bbitmap, ImageFormatType.Nv21, image.Width, image.Height, null);
var ms = new MemoryStream();
yuv.CompressToJpeg(new Android.Graphics.Rect(0, 0, image.Width, image.Height), 100, ms);
File.WriteAllBytes("/sdcard/Download/testFrame.jpg", ms.ToArray());
But this is the result:
This was just a test to actually save and check the captured frame, because at the end of this I still don't have a Bitmap (even if it was working).
In cas of real time processing, I don't want/need the JPG conversion becaus it would only slow down everything.
I'd like to convert the Image to a Bitmap, crop it and feed it to Emgu as a Mat.
Any suggestion?
Thanks

Retrieve Physical Font Data from Logical Font Handle

I wrote a font parser and renderer based on some functionality in the freetype library, but it currently only works for font files that I specify. I'd like to be able to retrieve fonts from the Windows Font Mapper and then parse and render them, but I can't figure out how to get the actual font data from a logical font.
I thought that the easy way to accomplish this would be to get the font file name from the logical font, but based on other stack overflow posts, there isn't any good solution to this because there isn't a 1 to 1 mapping of physical fonts to the logical font you specify.
This code shows how I'm currently retrieving a handle to a logical font:
HFONT windowsFont = CreateFontA(72, 0, 0, 0, 0,
0, 0, 0, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, "Arial");
HDC deviceContext = GetDC(windowHandle);
SelectObject(deviceContext, windowsFont);
DWORD fontSize = GetFontData(deviceContext, 0, 0, NULL, 0);
void *fontData = malloc(fontSize);
fontSize = GetFontData(deviceContext, 0, 0, fontData, 0);
char *fontFileData;
size_t fontFileSize;
// This is a function that I wrote that does what you'd expect. It opens
// a file, reads all the bytes to a buffer and closes the file
readFileToBuff(&fontFileData, &fontFileSize, "c:/windows/fonts/arial.ttf");
assert(fontFileSize == fontSize); // This passes
assert(((char)fontFileData) == ((char)fontData)); // This fails
Based on this stack overflow post which is for Java, I'm thinking that what I want to do may not be possible. It seems that the only solution may be to look at all the system font files and try to figure out what they are.
How to get ttf font data from system fonts in java
This surprises me though, because it seems that it would be relatively common for a program to want to render fonts themselves, without relying on the Windows renderer. Does anyone know of a way to get the font data, or how other people have solved this problem?
I don't understand why it's getting the exact same amount of bytes as
the file, but the data isn't the same.
From the official sample, I found the correct way to use GetFontData.
This is the modified code, and the returned data is the same as fontFileData.
HRESULT hr = S_OK;
LPVOID ptr = NULL;
HGLOBAL hGlobal = NULL;
...
HFONT windowsFont = CreateFontA(72, 0, 0, 0, 0,
0, 0, 0, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, "Arial");
HDC deviceContext = GetDC(hWnd);
SelectObject(deviceContext, windowsFont);
DWORD fontSize = GetFontData(deviceContext, 0, 0, NULL, 0);
hGlobal = GlobalAlloc(GMEM_MOVEABLE, fontSize);
ptr = GlobalLock(hGlobal);
if (!ptr)
{
hr = HRESULT_FROM_WIN32(GetLastError());
fwprintf(stderr, L"ERROR: Could not lock global memory object: %08X\n", hr);
}
else
{
if (GetFontData(deviceContext, 0, 0, ptr, fontSize) == GDI_ERROR)
{
fwprintf(stderr, L"ERROR: Could not get font data\n");
hr = E_UNEXPECTED;
}
GlobalUnlock(hGlobal);
}
char *fontFileData;
size_t fontFileSize;
// This is a function that I wrote that does what you'd expect. It opens
// a file, reads all the bytes to a buffer and closes the file
readFileToBuff(&fontFileData, &fontFileSize, "c:/windows/fonts/arial.ttf");
assert(fontFileSize == fontSize); // This passes
assert(((char)fontFileData) == ((char)fontData)); // This fails

Working with HBitmaps

I'm trying to save some HBITMAPs into an array, and display them at a later time. Creating a HBITMAP from a DC works, but when I try to display a saved HBITMAP I seem to get the wrong one. This leads me to think that I haven't really understood how HTBIMAPs are stored in memory. I was assuming that the data type HBITMAP is essentially a pointer to the object in memory and that that's all I need, but maybe there is more to it?
Here's a sample code:
HBITMAP aBitMaps[NUM_BITMAPS];
int iNumBitMaps;
void SaveScreen(CDC *dc)
{
if (iNumBitMaps>0)
{
if (iNumBitMaps>=NUM_BITMAPS)
{
iNumBitMaps=NUM_BITMAPS-1;
DeleteObject(aBitMaps[iNumBitMaps]);
}
for (int i=iNumBitMaps;i>0;i--)
{
aBitMaps[i] = aBitMaps[i-1];
}
}
iNumBitMaps++;
aBitMaps[0] = CreateCompatibleBitmap(dc->m_hDC, 800, 800);
HDC hdcMem = CreateCompatibleDC(dc->m_hDC);
SelectObject(hdcMem, aBitMaps[0]);
BitBlt(hdcMem, 0, 0, 800, 800, dc->m_hDC, 0, 0, SRCCOPY);
ReleaseDC(hdcMem);
}
void RestoreScreen(CDC *dc, int i)
{
if (i>=NUM_BITMAPS) i = NUM_BITMAPS-1;
if (i<0) i = 0;
HDC hdcMem = CreateCompatibleDC(dc->m_hDC);
SelectObject(hdcMem, aBitMaps[i]);
BitBlt(dc->m_hDC, 0, 0, 800, 800, hdcMem, 0, 0, SRCCOPY);
ReleaseDC(hdcMem);
}
So, the idea is essentially to push the HBITMAP pointers to an array, and at a later time display any of the stored images by selecting it into a memory DC and then copying it to the actual DC. What's wrong with this?
I'm using VC++, Visual Studio 2010, no MFC.
EDIT:
I did some more tests. For debugging, I tried to display all stored bitmaps (shifted in position) by adding the following for loop to SaveScreen
...
BitBlt(hdcMem, 0, 0, 800, 800, dc->m_hDC, 0, 0, SRCCOPY);
for (int j=0; j<iNumBitMaps;j++)
{
SelectObject(hdcMem, aBitMaps[j]);
BitBlt(dc->m_hDC, 20*(j+1), 100*(j+1), 800+20*(j+1), 800+100*(j+1), hdcMem, 0, 0, SRCCOPY);
}
ReleaseDC(hdcMem);
This then does display iNumBitMaps times the image, but it's always the same image (namely the one I stored in aBitMaps[0]). I did verify in the debugger, that aBitMaps contains all different pointers. So, somehow I think I don't correctly load the bitmaps into the memory DC.
I figured it out. In my code above there were two mistakes (of which I'm aware of). First, the memory DC must be deleted after use, so ReleaseDC must be replaced by DeleteDC.
Second, one must know that an object that is selected into a DC cannot be selected into another DC. Hence it is important that after operating on an object in the memory DC, the object must be unloaded by selecting the DC's previous object. The correct contruction is thus essentially
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, aBitMaps[0]);
BitBlt(...);
HBITMAP hbmNew = (HBITMAP)SelectObject(hdcMem, hbmOld);
where now hbmNew points to the same object as aBitMaps[0].

Unexpected failure when using XCreateImage with LodePNG

I am trying to add a background image to a X11 window, in Linux. I use the simple LodePNG to decode the PNG image into raw data (RGBA) then I try to set the window background.
What happens is that the window shows up for a while then it unexpectedly closes back. If I comment out the XCreateImage and XPutImage function (including the destructors) the window shows up correctly, so the window creation is not a problem.
My code looks like this:
// Headers here (xlib, lodepng) ...
// Global vars ...
Display *display;
Window window;
int window_width = 640;
int window_height = 480;
// Entry point, initialization, window creation ...
int main(int argc, char* argv[]) {
vector<unsigned char> image; //the raw pixels
unsigned width, height;
// Decode
unsigned error = lodepng::decode(image, width, height, "bg.png");
// If there's no error continue
if(!error)
{
Pixmap pixmap = XCreatePixmap
(
display,
XDefaultRootWindow(display),
width,
height,
DefaultDepth(display, 0)
);
XGCValues gr_values;
GC gr_context = XCreateGC
(
display,
window,
GCBackground,
&gr_values
);
// Here is where it fails !!!
unsigned rowbytes = 0;
XImage *ximage = XCreateImage
(
display,
CopyFromParent,
32,
XYPixmap,
0,
(char*)image.data(),
width,
height,
32,
rowbytes
);
XPutImage(
display,
pixmap,
gr_context,
ximage,
0, 0,
0, 0,
window_width,
window_height
);
XSetWindowBackgroundPixmap(display, window, pixmap);
XFreePixmap(display, pixmap);
XFreeGC(display, gr_context);
XDestroyImage(ximage);
}
}
After I decode the PNG I can see that I get the correct width and height of the image. The size of the raw data (image variable) is always 819200, no matter what image I choose, which is a bit weird and I wonder if LodePNG is not loading the image correctly (yet it gives no error and correct width and height). Other causes of this problem, I don't know. I don't get any error message, the window just closes after being saw a little bit. Maybe some of the arguments of XCreateImage is wrong but I can't figure out which.

Correctly release resources after flipping a bitmap

I have an application that writes a very large data set as a bitmap. [~500MB] I am writing the data patch wise from top to down. Due to the nature of BMP's file structure it must be flipped once written to the disk. (I wrote it this way because I assumed that flipping a bitmap would be a common application and I would find libraries to do the task)
I am using a code snippet I found on the internet to flip the bitmap. This one:
// GetInvertedBitmap - Creates a new bitmap with the inverted image
// Returns - Handle to a new bitmap with inverted image
// hBitmap - Bitmap to invert
// bLateral - Flag to indicate whether to invert laterally or vertically
HBITMAP CRisatImport::GetInvertedBitmap( HBITMAP hBitmap, BOOL bLateral )
{
// Create a memory DC compatible with the display
CDC sourceDC, destDC;
sourceDC.CreateCompatibleDC( NULL );
destDC.CreateCompatibleDC( NULL );
// Get logical coordinates
BITMAP bm;
::GetObject( hBitmap, sizeof( bm ), &bm );
// Create a bitmap to hold the result
HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL),
bm.bmWidth, bm.bmHeight);
// Select bitmaps into the DCs
HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
if( bLateral )
destDC.StretchBlt( 0, 0, bm.bmWidth, bm.bmHeight, &sourceDC,
bm.bmWidth-1, 0, -bm.bmWidth, bm.bmHeight, SRCCOPY );
else
destDC.StretchBlt( 0, 0, bm.bmWidth, bm.bmHeight, &sourceDC,
0, bm.bmHeight-1, bm.bmWidth, -bm.bmHeight, SRCCOPY );
// Reselect the old bitmaps
::SelectObject( sourceDC.m_hDC, hbmOldSource );
::SelectObject( destDC.m_hDC, hbmOldDest );
return hbmResult;
}
The problem is that I have a limited understanding of the above code. I tried to write a function to use the above snippet the best I could from sample code from MSDN. I do not think I am releasing all resources correctly. And I cant seem to figure out the error - mainly because my lack of knowledge about GDI. I would really appreciate it if some one pointed out what I am doing wrong.
The program crashes if I try to call this function twice - that is why I suspect that I am releasing resources incorrectly.
This is the function I wrote:
void CRisatImport::flipBitMapSaveAsJPG( CString outputFileName, CString outputJPGName, bool saveAsJpg)
{
// Flip the bitmap to correct odd file structure
HBITMAP hBitmap;
hBitmap = (HBITMAP)::LoadImage(NULL, outputFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
hBitmap = GetInvertedBitmap( hBitmap, FALSE );
CImage image;
image.Attach(hBitmap);
image.Save(outputFileName,Gdiplus::ImageFormatBMP);
if(saveAsJpg){
image.Save(outputJPGName,Gdiplus::ImageFormatJPEG);
}
image.Destroy();
DeleteObject( hBitmap );
}
I am using MFC and VS2010 for this application - I have 4GB of RAM and no other applications running.
This is the error I get:
When you Attach your bitmap handle to CImage you're handing over responsibility for the handle's lifetime to CImage so you don't want to Destory it after. But you're also using the same variable name for your new bitmap. Try this instead:
void CRisatImport::flipBitMapSaveAsJPG( CString outputFileName, CString outputJPGName, bool saveAsJpg)
{
// Flip the bitmap to correct odd file structure
HBITMAP hBitmapLoad = (HBITMAP)::LoadImage(NULL, outputFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HBITMAP hBitmapInverted = GetInvertedBitmap( hBitmapLoad , FALSE );
DeleteObject( hBitmapLoad );
CImage image;
image.Attach(hBitmapInverted );
image.Save(outputFileName,Gdiplus::ImageFormatBMP);
if(saveAsJpg){
image.Save(outputJPGName,Gdiplus::ImageFormatJPEG);
}
image.Destroy();
}

Resources