'Cannot load JPG image Pdfium
I try to do some stuff with PDF for a project. I'm trying to do some interop with Pdfium: https://pdfium.googlesource.com/pdfium/.
I want to convert a JPG image to a PDF (just for the start). So I found some resources on the web and I came to this:
///// My main file
// Create the stream
using FileStream image = new FileStream(@"test.jpg", FileMode.Open, FileAccess.Read);
using FileStream pdf = new FileStream(@"test.pdf", FileMode.OpenOrCreate, FileAccess.Write);
// Init the library to use it
FPDF.InitLibrary();
// Create the PDF
IntPtr document = FPDF.CreateNewDocument();
IntPtr page = FPDFPage.New(document, 0, 3000, 4000);
IntPtr pageObject = FPDFPageObj.NewImageObj(document);
// Create a copy of the delegate
FPDF.m_GetBlockDelegate del = Delegates.m_GetBlockDelegate;
FPDF.FILEACCESS fileAccess = new FPDF.FILEACCESS
{
m_FileLen = (ulong)image.Length,
m_Param = image.SafeFileHandle.DangerousGetHandle(),
m_GetBlock = del,
};
// Create the FILEWRITE struct
byte[] buffer = null;
FPDF.FILEWRITE fileWrite = new FPDF.FILEWRITE
{
WriteBlock = delegate (ref FPDF.FILEWRITE pThis, byte[] pData, ulong size)
{
if (buffer == null || (ulong)buffer.Length < size)
buffer = new byte[size];
pData.CopyTo(buffer, 0);
pdf.Write(buffer, 0, (int)size);
return true;
}
};
// Load the image
FPDPImageObj.LoadJpegFile(IntPtr.Zero, 0, pageObject, ref fileAccess);
FPDFPage.InsertObject(page, pageObject);
// Save the PDF
FPDF.SaveAsCopy(document, ref fileWrite, 0);
// Destroy the library
FPDF.DestroyLibrary();
The problem is with this method: FPDPImageObj.LoadJpegFile(IntPtr.Zero, 0, pageObject, ref fileAccess);
.
The struct has a delegate as a callback function to do some stuff (it does a sort of stream implementation in C).
Here is the code of my delegate, struct, and the implementation of the delegate:
public struct FILEACCESS
{
public ulong m_FileLen { get; set; }
public m_GetBlockDelegate m_GetBlock { get; set; }
public IntPtr m_Param { get; set; }
}
public struct FILEWRITE
{
// Must be 1
public int version = 1;
public WriteBlockDelegate WriteBlock { get; set; }
}
public delegate int m_GetBlockDelegate(IntPtr param, ulong position, [In] byte[] pBuf, ulong size);
public delegate bool WriteBlockDelegate(ref FILEWRITE pThis, [In] byte[] pData, ulong size);
// The implementation of my delegate in another class
public static int m_GetBlockDelegate(IntPtr param, ulong position, [In] byte[] pBuf, ulong size)
{
// Original source code for the delegate
//FILE* fileHandle = (FILE*)param;
//fseek(imageFile, position, SEEK_SET);
//fread(pBuf, size, 1, fileHandle);
using FileStream fs = new FileStream(new SafeFileHandle(param, false), FileAccess.Read);
fs.Seek((long)position, SeekOrigin.Begin);
fs.Read(pBuf, 0, (int)size);
return (int)size;
}
The current problem is that pBuf should be a buffer to hold all the data to read. So it must be the same size as size
. In my case pBuf has a size of 1. I have tested a C variant of my code and it works well (it reads all the data). Here is the code:
#include <stdio.h>
#include <fpdfview.h>
#include <fpdf_edit.h>
#include <fpdf_save.h>
FILE* pdfFile = nullptr;
int m_GetBlockImpl(void* param, unsigned long position, unsigned char* pBuf, unsigned long size)
{
FILE* fileHandle = (FILE*)param;
fseek(fileHandle, position, SEEK_SET);
fread(pBuf, size, 1, fileHandle);
return size;
}
int WriteBlockImpl(FPDF_FILEWRITE* pThis, const void* pData, unsigned long size)
{
fwrite(pData, size, 1, pdfFile);
return TRUE;
}
int main()
{
FILE* jpgFile = fopen("C:\\Users\\tcroi\\Desktop\\test.jpg", "rb");
pdfFile = fopen("C:\\Users\\tcroi\\Desktop\\test.pdf", "wb");
if (jpgFile == nullptr || pdfFile == nullptr)
return 1;
FPDF_InitLibrary();
// Create the PDF
FPDF_DOCUMENT pdf_doc = FPDF_CreateNewDocument();
FPDF_PAGE pdf_page = FPDFPage_New(pdf_doc, 0, 3000, 4000);
// Seek the stream and get the size
fseek(jpgFile, 0, SEEK_END);
long fileSize = ftell(jpgFile);
fseek(jpgFile, 0, SEEK_SET);
// Create the FILEACCESS
FPDF_FILEACCESS fileReadObj;
fileReadObj.m_FileLen = fileSize;
fileReadObj.m_Param = jpgFile;
fileReadObj.m_GetBlock = m_GetBlockImpl;
// Load the image to the PDF
FPDF_PAGEOBJECT page_obj_image = FPDFPageObj_NewImageObj(pdf_doc);
FPDFImageObj_LoadJpegFile(nullptr, 0, page_obj_image, &fileReadObj);
FPDFPage_InsertObject(pdf_page, page_obj_image);
// Create the FILEWRITE
FPDF_FILEWRITE fileWriteObj;
fileWriteObj.version = 1;
fileWriteObj.WriteBlock = WriteBlockImpl;
FPDF_SaveAsCopy(pdf_doc, &fileWriteObj, 0);
FPDF_DestroyLibrary();
fclose(jpgFile);
fclose(pdfFile);
return 0;
}
This code works well until I want to save the PDF, I only get a blank page, maybe I have missed something but according to example no. Here is the example: https://groups.google.com/g/pdfium/c/P73DgvJtgTs
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|