- 전체
- 명
- 오늘 찾아주신 분
- 명
우선, PNG 파일을 만들기 전에 윈도우에 깔려 있어야 하는 라이브러리들이 있다.
- libpng
- zlib
그지같은 설명서에서는 PDF 파일 여는 것만 있지 이걸 어떻게 사용하라는 안내도 없고, 헤더파일 열자니 이건 무슨말인 지 모르겠고 해서 소스로 파악 해서 간추려 보았다.
소스는 일전에 빌드파일 만들어놓았던 pdfium 폴더에 있는 sample/pdfium_test.cc 를 참조하였다.
#include <iostream>
#include <vector>
#include <stdlib.h>
#include "fpdfview.h"
#include "cpp/fpdf_scopers.h"
#include <png.h>
// PNG 복사 버퍼 구조체
struct Buffer {
explicit Buffer(std::vector<uint8_t> *o) : buffer(o) {}
std::vector<uint8_t> *buffer;
}
void copyToBuffer(png_structp png_ptr, png_bytep data, png_size_t size){
Buffer *b = static_cast<Buffer*>(png_get_io_ptr(png_ptr));
size_t old = b->buffer->size();
b->buffer->resize(old + size);
memcpy(&(*b->buffer)[old], data, size);
}
void unknown(png_structp p){}
int main(){
const char *path = PDF_FILE_PATH;
int indexToLoad = 0; // 열고 싶은 페이지 인덱스 (0 번부터 1페이지이다)
// PDFium 을 초기화한다. 이걸 해야 사용할 수 있음
FPDF_InitLibrary();
// PDF 파일을 연다
FPDF_DOCUMENT doc = FPDF_LoadDocument(path, NULL);
if(!doc){
// 에러를 코드로 알려준다.
unsigned long code = FPDF_GetLastError();
}
// 페이지를 로드한다.
FPDF_PAGE page = FPDF_LoadPage(doc, indexToLoad);
int originW = FPDF_GetPageWidth(page);
int originH = FPDF_GetPageHeight(page);
// 비트맵을 만든다. PNG 파일을 만들려면 FPDFBitmap_Create 의 마지막 숫자를 1로 놓는다.
// 마지막 인자 값은 Alpha 가 있는 지 없는 지 확인하는 것이다.
ScopedFPDFBitmap panel(FPDFBitmap_Create(originW, originH, 1));
// PNG 의 뒷 배경을 흰색으로 먼저 채운다. 안채우면 테두리에 뭔가 검정색이 보인다.
FPDFBitmap_FillRect(panel.get(), 0, 0, originW, originH, 0xFFFFFFFF);
// 페이지를 렌더한다. 배경위에 올리는 것이다.
FPDF_RenderPageBitmap(panel.get(), page, 0, 0, originW, originH, 0, FPDF_ANNOT);
// 다 올렸으면 페이지를 종료한다. 페이지가 사용되면 항상 종료하도록 한다.
FPDF_ClosePage(page);
// 렌더가 제대로 되었으면 width 랑 height 가 originW/H 와 같은 값이 나올 것이다.
int width = FPDFBitmap_GetWidth(panel.get());
int height = FPDFBitmap_GetHeight(panel.get());
// Stride 라는 것으로 렌더된 비트맵의 한 줄 사이즈를 가져오는 듯 하다.
// height * rowBytes 를 하게 되면 해당 PNG 가 그려진다.
int rowBytes = FPDFBitmap_GetStride(panel.get());
// 렌더된 비트맵을 버퍼로부터 가져와 담는다
// 버퍼가 void * 형태라서 형변환을 시켜주었다.
uint8_t *bitmap = static_Cast<uint8_t*>(FPDFBitmap_GetBuffer(panel.get());
FPDF_CloseDocument(doc);
FPDF_DestroyLibrary();
// ------------- 여기까지가 PDFium 에서 페이지를 불러와 렌더하는 로직이었다.
std::vector<uint8_t> output;
Buffer ob(&output);
// PNG 를 사용하려 한다.
png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
// PNG 파일 메타데이터를 다루는 객체인 것 같다.
png_info* info_ptr = png_create_info_struct(png_ptr);
if(!info_ptr){
//제대로 안만들어지면 PNG 만드는 일을 무효화 한다.
png_destroy_write_struct(&png_ptr, NULL);
}
// 이미지 압축 퍼센트를 얘기하는 것 같은데 아직 만져보진 않았다.
// Z_DEFAULT_COMPRESSION 은 zlib 에 있는 상수 값이다.
png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
// 무슨 역할 인 지는 모름
if(setjmp(png_jmpbuf(png_ptr))) return;
// PNG 를 만들 때 콜백함수를 입력하는 것 같다.
// unknown 부분은 Flush 메소드 부분이라는데 PDFium 소스에서도 따로 사용하진 않았다.
png_set_write_fn(png_ptr, &ob, copyToBuffer, unknown);
png_set_IHDR(png_ptr, info_ptr, width, height, 8,
PNG_COLOR_TYPE_RGB_ALPHA, // 타입을 ALPHA 로 안해놓으면 깨진 이미지가 나온다
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
// 기본적인 메타데이터를 작성했다.
png_write_info(png_ptr, info_ptr);
// PNG 로 비트맵 버퍼를 작성한다.
for(int y=0; y < originH; y++){
png_write_row(png_ptr, &bitmap[y * rowBytes])
}
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
// -------- 여기까지 PNG 로 작성하는 로직이었다.
FILE *fp = fopen("export.png", "wb");
fwrite(&output[0], 1, output.size(), fp);
fclose();
}
나는 클래스화 하여 개발을 한 상태이고, 이 소스는 일부분을 오려다가 붙인거라 다른 곳에 복붙하면 틀림없이 오류발생할 가능성이 100% 있을 것이기 때문에 가져다가 사용하는 것이라면 하나하나 전부 입력하면서 개발을 해야 좋을 것이다.
[Linux] PHP Composer 다른 방식으로 설치하기 (무설치) (0) | 2022.03.14 |
---|---|
[Linux] Nginx 소스 컴파일 (베껴)설치하기 (0) | 2022.03.10 |
[Linux] 자주 쓰는 커맨드 모음 (0) | 2022.03.08 |
[Windows] PDFium 와 boost::gil 을 함께 사용하기 (0) | 2022.02.04 |
[Windows] PDFium Windows DLL 추출하기 (0) | 2022.02.04 |