pdf417lib庫封裝和使用
pdf417lib下載連結
https://master.dl.sourceforge.net/project/pdf417lib/pdf417lib/0.91/pdf417lib-c-0.91.zip?viasf=1
CMake檔案
yh@ubuntu:/Test/pdf417lib$ tree
.
├── build
├── CMakeLists.txt
├── include
│ ├── pdf417.h
│ ├── pdf417lib.h
│ └── pdf417libimp.h
├── main.cpp
└── src
├── pdf417.cpp
└── pdf417lib.c
3 directories, 7 files
CMakeLists.txt檔案
cmake_minimum_required(VERSION 3.0.0)
project(barcode)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB LIBRARY_SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/pdf417lib.c")
#設定靜態庫和動態庫所需的中間檔案列表
set(LIBRARY_OBJS_LIST ${PROJECT_NAME}-objs)
add_library(${LIBRARY_OBJS_LIST} OBJECT ${LIBRARY_SRC_LIST})
#開啟靜態庫和動態庫所需的中間檔案的PIC編譯選項
set_target_properties(${LIBRARY_OBJS_LIST} PROPERTIES POSITION_INDEPENDENT_CODE True)
#生成靜態庫
#設定靜態庫檔案臨時名稱
set(TMP_STATIC_LIB_NAME ${PROJECT_NAME}-static)
#生成靜態庫檔案
add_library(${TMP_STATIC_LIB_NAME} STATIC $<TARGET_OBJECTS:${LIBRARY_OBJS_LIST}>)
#設定靜態庫檔案的最終名稱
set_target_properties(${TMP_STATIC_LIB_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
#生成動態庫
#設定動態庫檔案臨時名稱
set(TMP_SHARED_LIB_NAME ${PROJECT_NAME}-shared)
#生成動態庫檔案
add_library(${TMP_SHARED_LIB_NAME} SHARED $<TARGET_OBJECTS:${LIBRARY_OBJS_LIST}>)
#設定動態庫檔案的最終名稱
set_target_properties(${TMP_SHARED_LIB_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
add_executable(test${PROJECT_NAME} main.cpp)
target_link_libraries(test${PROJECT_NAME} ${TMP_STATIC_LIB_NAME})
pdf417lib.h
#ifndef __PDF417LIB_H__
#define __PDF417LIB_H__
#ifdef __cplusplus
extern "C" {
#endif
//四者取其一,優先判斷PDF417_FIXED_RECTANGLE,若乘積大於(MAX_DATA_CODEWORDS + 2)
//則取最大值(MAX_DATA_CODEWORDS + 2),並且重設資訊塊數的數量和行高。
//接著判斷PDF417_FIXED_COLUMNS和PDF417_FIXED_ROWS若未設定,則採用PDF417_USE_ASPECT_RATIO
//建議不要使用PDF417_USE_ASPECT_RATIO受aspectRatio、yHeight和strlen(text)影響很不穩定
#define PDF417_USE_ASPECT_RATIO 0 //此項為預設值,預設比例為0.5,透過aspectRatio來修改
#define PDF417_FIXED_RECTANGLE 1 //同時指定pdf417條碼的寬度(資料區資訊塊的數量)和高度(最小方塊的數量)
#define PDF417_FIXED_COLUMNS 2 //指定pdf417條碼的寬度(資料區資訊塊的數量)
#define PDF417_FIXED_ROWS 4 //指定pdf417條碼的高度(最小方塊的數量)
//二者取其一
#define PDF417_AUTO_ERROR_LEVEL 0 //此項為預設值,根據內容的位元組數自動設定糾錯等級
#define PDF417_USE_ERROR_LEVEL 16 //指定pdf417條碼的糾錯等級(0到8)
#define PDF417_USE_RAW_CODEWORDS 64 //將text作為二進位制流而非字元流,此時需要設定lenText的大小
#define PDF417_INVERT_BITMAP 128 //反轉pdf417條碼的黑白塊,預設1表示黑塊
//pdf417param中error的值, 表示paintCode()的執行結果
#define PDF417_ERROR_SUCCESS 0 //沒有錯誤
#define PDF417_ERROR_TEXT_TOO_BIG 1 //所需編碼的資訊過大
#define PDF417_ERROR_INVALID_PARAMS 2 //錯在錯誤的條碼引數
typedef struct _pdf417param {
char *outBits;
int lenBits;
int bitColumns;
int codeRows; //最大值90,若與codeColumns大於928,則兩個值會被重設
int codeColumns; //最大值30,若與codeRows大於928,則兩個值會被重設
int codewords[928];
int lenCodewords;
int errorLevel;
char *text;
int lenText;
int options;
float aspectRatio;
float yHeight;
int error;
} pdf417param, *pPdf417param;
void paintCode(pPdf417param p);
void pdf417init(pPdf417param param);
void pdf417free(pPdf417param param);
#ifdef __cplusplus
}
#endif
#endif
pdf417.h
#ifndef __PDF417__
#define __PDF417__
#include <string>
#include <vector>
class pdf417
{
public:
enum class FitPolicy {UseAspectRatio = 0, FixedRectangle = 1, FixedColumns = 2, FixedRows = 4};
public:
pdf417() = default;
~pdf417() = default;
public:
void setBarCodeProperty(int columnfit = 6, int pixelBitDepth = 1, bool ifInvertPixel = false, int errorLevel = -1, FitPolicy shapefit = FitPolicy::FixedColumns, float ratio = 0.5, float yHeight = 3.0, int rowfit = 0);
bool printBarCode(const std::string &data);
bool output2postscript(const std::string &path);
public:
int m_Width = 0;
int m_Height = 0;
int m_BytesPerRow = 0;
int m_PixelBitsDepth = 1;
int m_ColumnFit = 0;
int m_RowFit = 0;
int m_ShapeFit = 0;
int m_ErrorLevel = 0;
float m_YHeight = 3.0;
float m_AspectRatio = 0.5;
bool m_IfInvertPixel = false;
std::vector<unsigned char> m_CacheMap;
std::string m_ErrorMSG;
};
#endif
pdf417.cpp
#include <pdf417.h>
#include <pdf417lib.h>
#include <iostream>
using namespace std;
void pdf417::setBarCodeProperty(int columnfit, int pixelBitDepth, bool ifInvertPixel, int errorLevel, FitPolicy shapefit, float ratio, float yHeight, int rowfit)
{
m_AspectRatio = 0.5;
m_RowFit = 0;
m_ColumnFit = 0;
switch(shapefit)
{
case FitPolicy::FixedRectangle:
{
m_RowFit = rowfit;
m_ColumnFit = columnfit;
m_ShapeFit= PDF417_FIXED_RECTANGLE;
break;
}
case FitPolicy::FixedColumns:
{
m_ShapeFit= PDF417_FIXED_COLUMNS;
m_ColumnFit = columnfit;
break;
}
case FitPolicy::FixedRows:
{
m_ShapeFit= PDF417_FIXED_ROWS;
m_RowFit = rowfit;
break;
}
default:
{
m_ShapeFit= PDF417_USE_ASPECT_RATIO;
m_AspectRatio = ratio;
break;
}
}
m_PixelBitsDepth = pixelBitDepth;
m_IfInvertPixel = ifInvertPixel;
m_ErrorLevel = errorLevel;
m_YHeight = yHeight;
}
bool pdf417::printBarCode(const std::string &data)
{
pdf417param property;
pdf417init(&property);
property.text = const_cast<char*>(data.c_str());
property.errorLevel = m_ErrorLevel;
if(m_IfInvertPixel)
{
property.options |= PDF417_INVERT_BITMAP;
}
property.options |= m_ShapeFit;
property.codeRows = m_RowFit;
property.codeColumns = m_ColumnFit;
property.aspectRatio = m_AspectRatio;
property.yHeight = m_YHeight;
paintCode(&property);
switch(property.error)
{
case PDF417_ERROR_SUCCESS:
{
m_Width = property.bitColumns;
m_Height = property.codeRows;
m_BytesPerRow = (property.bitColumns + 7) / 8;
m_CacheMap = vector<unsigned char>(m_BytesPerRow * m_Height);
for (int k = 0; k < m_CacheMap.size(); ++k)
{
m_CacheMap[k] = property.outBits[k];
}
m_ErrorMSG = "";
return true;
}
case PDF417_ERROR_TEXT_TOO_BIG:
{
m_ErrorMSG = "輸入資料text過大";
break;
}
case PDF417_ERROR_INVALID_PARAMS:
{
m_ErrorMSG = "條款引數設定異常";
break;
}
default:
{
m_ErrorMSG = "未知錯誤";
break;
}
}
pdf417free(&property);
return false;
}
bool pdf417::output2postscript(const std::string &path)
{
FILE *fp = fopen(path.c_str(), "wb");
if(fp)
{
int cols = m_BytesPerRow;
fprintf(fp, "%%!PS1.3\n");
fprintf(fp, "/Times findfont\n");
fprintf(fp, "8 scalefont setfont\n");
fprintf(fp, "100 92 moveto\n");
switch(m_ShapeFit)
{
case PDF417_FIXED_RECTANGLE:
{
fprintf(fp, "(FIXED_RECTANGLE row: %d, column: %d)show\n", m_Height, m_Width);
break;
}
case PDF417_FIXED_COLUMNS:
{
fprintf(fp, "(FIXED_COLUMNS row: %d, column: %d)show\n", m_Height, m_Width);
break;
}
case PDF417_FIXED_ROWS:
{
fprintf(fp, "(FIXED_ROWS row: %d, column: %d)show\n", m_Height, m_Width);
break;
}
case PDF417_USE_ASPECT_RATIO:
{
fprintf(fp, "(USE_ASPECT_RATIO ratio: %f, yheight: %f, row: %d, column: %d)show\n", m_AspectRatio, m_YHeight, m_Height, m_Width);
break;
}
}
fprintf(fp, "stroke\n100 100 translate\n%g %g scale\n", (double)m_Width, (double)m_Height);
fprintf(fp, "%d %d 1 [%d 0 0 %d 0 %d]{<", m_Width, m_Height, m_Width, -m_Height, m_Height);
for (int k = 0; k < m_CacheMap.size(); ++k)
{
if (!(k % cols))
{
fprintf(fp, "\n");
}
fprintf(fp, "%02X", m_CacheMap[k] & 0xff);
}
fprintf(fp, "\n>}image\nshowpage\n");
fclose(fp);
return true;
}
else
{
cerr << "檔案開啟失敗請檢查所在目錄是否擁有訪問和讀寫許可權!" << endl;
}
return false;
}
main.cpp
#include <iostream>
#include <pdf417.h>
int main(int argc, const char *argv[])
{
pdf417 barcode;
int columnfit = 6;
int pixelBitDepth = 1;
bool ifInvertPixel = true;
int errorLevel = -1;
float ratio = 0.5;
float yHeight = 3.0;
int rowfit = 16;
barcode.setBarCodeProperty(columnfit, pixelBitDepth, ifInvertPixel, errorLevel, pdf417::FitPolicy::FixedRows, ratio, yHeight, rowfit);
std::string data = "1234567890abcdefg1234567890abcdefg";
barcode.printBarCode(data);
barcode.output2postscript("file.ps");
return 0;
}
處理pdf417lib往標準輸出裡面輸出除錯資訊的問題
pdf417lib.c第693行
printf("%c%.*s\n", v->type, v->end - v->start, p->param->text + v->start);
修改為
fprintf(stderr, "%c%.*s\n", v->type, v->end - v->start, p->param->text + v->start);
測試
cmake .. && make -j8 && ./testbarcode && ps2pdf12 file.ps file.pdf