Skip to content

Instantly share code, notes, and snippets.

@planetis-m
Created February 13, 2026 08:14
Show Gist options
  • Select an option

  • Save planetis-m/d509f703cd037220370d3b8afc4e0ae1 to your computer and use it in GitHub Desktop.

Select an option

Save planetis-m/d509f703cd037220370d3b8afc4e0ae1 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Standard JPEG library
#include <jpeglib.h>
// Your local PDFium headers
#include "pdfium/include/fpdfview.h"
#include "pdfium/include/fpdf_text.h"
// --- Helper: Save BGRx buffer to JPEG ---
// PDFium gives us BGRx (Blue-Green-Red-Alpha/Unused).
// LibJPEG expects RGB. We swap channels row-by-row here.
void save_jpeg(const char *filename, const unsigned char *buffer, int width, int height, int stride) {
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *outfile;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
if ((outfile = fopen(filename, "wb")) == NULL) {
fprintf(stderr, "Cannot open %s\n", filename);
return;
}
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 4;
cinfo.in_color_space = JCS_EXT_BGRX;
printf("BEFORE jpeg_set_defaults:\n");
printf(" in_color_space = %d\n", cinfo.in_color_space);
printf(" input_components = %d\n", cinfo.input_components);
jpeg_set_defaults(&cinfo);
printf("AFTER jpeg_set_defaults:\n");
printf(" in_color_space = %d\n", cinfo.in_color_space);
printf(" input_components = %d\n", cinfo.input_components);
printf(" jpeg_color_space = %d\n", cinfo.jpeg_color_space);
printf(" num_components = %d\n", cinfo.num_components);
jpeg_set_quality(&cinfo, 90, TRUE);
printf("BEFORE jpeg_start_compress:\n");
printf(" in_color_space = %d\n", cinfo.in_color_space);
printf(" input_components = %d\n", cinfo.input_components);
jpeg_start_compress(&cinfo, TRUE);
JSAMPROW row_pointer[1];
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = (JSAMPROW)(buffer + (cinfo.next_scanline * stride));
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
fclose(outfile);
jpeg_destroy_compress(&cinfo);
printf("Saved JPEG (Fast Mode) to %s\n", filename);
}
int main() {
const char *input_file = "input.pdf";
const char *output_image = "output.jpg";
// --- INIT ---
FPDF_LIBRARY_CONFIG config;
memset(&config, 0, sizeof(config));
config.version = 2;
FPDF_InitLibraryWithConfig(&config);
// --- LOAD ---
FPDF_DOCUMENT doc = FPDF_LoadDocument(input_file, NULL);
if (!doc) {
fprintf(stderr, "Err: %lu\n", FPDF_GetLastError());
return 1;
}
FPDF_PAGE page = FPDF_LoadPage(doc, 0);
// 3. Calculate High-DPI Dimensions
// FPDF_GetPageWidth returns "points" (1/72 inch)
double pts_width = FPDF_GetPageWidth(page);
double pts_height = FPDF_GetPageHeight(page);
float scale = 2.0;
int px_width = (int)(pts_width * scale);
int px_height = (int)(pts_height * scale);
// 4. Render
FPDF_BITMAP bitmap = FPDFBitmap_Create(px_width, px_height, 0);
FPDFBitmap_FillRect(bitmap, 0, 0, px_width, px_height, 0xFFFFFFFF);
FPDF_RenderPageBitmap(bitmap, page, 0, 0, px_width, px_height, 0, 0);
// 5. Save
const unsigned char *buffer = (const unsigned char *)FPDFBitmap_GetBuffer(bitmap);
int stride = FPDFBitmap_GetStride(bitmap);
save_jpeg(output_image, buffer, px_width, px_height, stride);
// --- CLEANUP ---
FPDFBitmap_Destroy(bitmap);
FPDF_ClosePage(page);
FPDF_CloseDocument(doc);
FPDF_DestroyLibrary();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment