#!/usr/bin/env python3 # © 2017 James R. Barlow: github.com/jbarlow83 # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. from pathlib import Path from cffi import FFI ffibuilder = FFI() ffibuilder.cdef( """ typedef signed char l_int8; typedef unsigned char l_uint8; typedef short l_int16; typedef unsigned short l_uint16; typedef int l_int32; typedef unsigned int l_uint32; typedef float l_float32; typedef double l_float64; typedef long long l_int64; typedef unsigned long long l_uint64; typedef int l_ok; /*!< return type 0 if OK, 1 on error */ struct Pix { l_uint32 w; /* width in pixels */ l_uint32 h; /* height in pixels */ l_uint32 d; /* depth in bits (bpp) */ l_uint32 spp; /* number of samples per pixel */ l_uint32 wpl; /* 32-bit words/line */ l_uint32 refcount; /* reference count (1 if no clones) */ l_int32 xres; /* image res (ppi) in x direction */ /* (use 0 if unknown) */ l_int32 yres; /* image res (ppi) in y direction */ /* (use 0 if unknown) */ l_int32 informat; /* input file format, IFF_* */ l_int32 special; /* special instructions for I/O, etc */ char *text; /* text string associated with pix */ struct PixColormap *colormap; /* colormap (may be null) */ l_uint32 *data; /* the image data */ }; typedef struct Pix PIX; struct PixColormap { void *array; /* colormap table (array of RGBA_QUAD) */ l_int32 depth; /* of pix (1, 2, 4 or 8 bpp) */ l_int32 nalloc; /* number of color entries allocated */ l_int32 n; /* number of color entries used */ }; typedef struct PixColormap PIXCMAP; /*! Array of pix */ struct Pixa { l_int32 n; /*!< number of Pix in ptr array */ l_int32 nalloc; /*!< number of Pix ptrs allocated */ l_uint32 refcount; /*!< reference count (1 if no clones) */ struct Pix **pix; /*!< the array of ptrs to pix */ struct Boxa *boxa; /*!< array of boxes */ }; typedef struct Pixa PIXA; /*! Array of compressed pix */ struct PixaComp { l_int32 n; /*!< number of PixComp in ptr array */ l_int32 nalloc; /*!< number of PixComp ptrs allocated */ l_int32 offset; /*!< indexing offset into ptr array */ struct PixComp **pixc; /*!< the array of ptrs to PixComp */ struct Boxa *boxa; /*!< array of boxes */ }; typedef struct PixaComp PIXAC; struct Box { l_int32 x; l_int32 y; l_int32 w; l_int32 h; l_uint32 refcount; /* reference count (1 if no clones) */ }; typedef struct Box BOX; /*! Array of Box */ struct Boxa { l_int32 n; /*!< number of box in ptr array */ l_int32 nalloc; /*!< number of box ptrs allocated */ l_uint32 refcount; /*!< reference count (1 if no clones) */ struct Box **box; /*!< box ptr array */ }; typedef struct Boxa BOXA; /*! String array: an array of C strings */ struct Sarray { l_int32 nalloc; /*!< size of allocated ptr array */ l_int32 n; /*!< number of strings allocated */ l_int32 refcount; /*!< reference count (1 if no clones) */ char **array; /*!< string array */ }; typedef struct Sarray SARRAY; /*! Pdf formatted encoding types */ enum { L_DEFAULT_ENCODE = 0, /*!< use default encoding based on image */ L_JPEG_ENCODE = 1, /*!< use dct encoding: 8 and 32 bpp, no cmap */ L_G4_ENCODE = 2, /*!< use ccitt g4 fax encoding: 1 bpp */ L_FLATE_ENCODE = 3, /*!< use flate encoding: any depth, cmap ok */ L_JP2K_ENCODE = 4 /*!< use jp2k encoding: 8 and 32 bpp, no cmap */ }; /*! Compressed image data */ struct L_Compressed_Data { l_int32 type; /*!< encoding type: L_JPEG_ENCODE, etc */ l_uint8 *datacomp; /*!< gzipped raster data */ size_t nbytescomp; /*!< number of compressed bytes */ char *data85; /*!< ascii85-encoded gzipped raster data */ size_t nbytes85; /*!< number of ascii85 encoded bytes */ char *cmapdata85; /*!< ascii85-encoded uncompressed cmap */ char *cmapdatahex; /*!< hex pdf array for the cmap */ l_int32 ncolors; /*!< number of colors in cmap */ l_int32 w; /*!< image width */ l_int32 h; /*!< image height */ l_int32 bps; /*!< bits/sample; typ. 1, 2, 4 or 8 */ l_int32 spp; /*!< samples/pixel; typ. 1 or 3 */ l_int32 minisblack; /*!< tiff g4 photometry */ l_int32 predictor; /*!< flate data has PNG predictors */ size_t nbytes; /*!< number of uncompressed raster bytes */ l_int32 res; /*!< resolution (ppi) */ }; typedef struct L_Compressed_Data L_COMP_DATA; /*! Selection */ struct Sel { l_int32 sy; /*!< sel height */ l_int32 sx; /*!< sel width */ l_int32 cy; /*!< y location of sel origin */ l_int32 cx; /*!< x location of sel origin */ l_int32 **data; /*!< {0,1,2}; data[i][j] in [row][col] order */ char *name; /*!< used to find sel by name */ }; typedef struct Sel SEL; enum { REMOVE_CMAP_TO_BINARY = 0, /*!< remove colormap for conv to 1 bpp */ REMOVE_CMAP_TO_GRAYSCALE = 1, /*!< remove colormap for conv to 8 bpp */ REMOVE_CMAP_TO_FULL_COLOR = 2, /*!< remove colormap for conv to 32 bpp */ REMOVE_CMAP_WITH_ALPHA = 3, /*!< remove colormap and alpha */ REMOVE_CMAP_BASED_ON_SRC = 4 /*!< remove depending on src format */ }; /*! Access and storage flags */ enum { L_NOCOPY = 0, /*!< do not copy the object; do not delete the ptr */ L_INSERT = L_NOCOPY, /*!< stuff it in; do not copy or clone */ L_COPY = 1, /*!< make/use a copy of the object */ L_CLONE = 2, /*!< make/use clone (ref count) of the object */ L_COPY_CLONE = 3 /*!< make a new array object (e.g., pixa) and fill */ /*!< the array with clones (e.g., pix) */ }; /*! Flags for method of extracting barcode widths */ enum { L_USE_WIDTHS = 1, /*!< use histogram of barcode widths */ L_USE_WINDOWS = 2 /*!< find best window for decoding transitions */ }; /*! Flags for barcode formats */ enum { L_BF_UNKNOWN = 0, /*!< unknown format */ L_BF_ANY = 1, /*!< try decoding with all known formats */ L_BF_CODE128 = 2, /*!< decode with Code128 format */ L_BF_EAN8 = 3, /*!< decode with EAN8 format */ L_BF_EAN13 = 4, /*!< decode with EAN13 format */ L_BF_CODE2OF5 = 5, /*!< decode with Code 2 of 5 format */ L_BF_CODEI2OF5 = 6, /*!< decode with Interleaved 2 of 5 format */ L_BF_CODE39 = 7, /*!< decode with Code39 format */ L_BF_CODE93 = 8, /*!< decode with Code93 format */ L_BF_CODABAR = 9, /*!< decode with Code93 format */ L_BF_UPCA = 10 /*!< decode with UPC A format */ }; enum { L_SEVERITY_EXTERNAL = 0, /* Get the severity from the environment */ L_SEVERITY_ALL = 1, /* Lowest severity: print all messages */ L_SEVERITY_DEBUG = 2, /* Print debugging and higher messages */ L_SEVERITY_INFO = 3, /* Print informational and higher messages */ L_SEVERITY_WARNING = 4, /* Print warning and higher messages */ L_SEVERITY_ERROR = 5, /* Print error and higher messages */ L_SEVERITY_NONE = 6 /* Highest severity: print no messages */ }; enum { SEL_DONT_CARE = 0, SEL_HIT = 1, SEL_MISS = 2 }; """ ) ffibuilder.cdef( """ PIX * pixRead ( const char *filename ); PIX * pixReadMem ( const l_uint8 *data, size_t size ); PIX * pixReadStream ( FILE *fp, l_int32 hint ); PIX * pixScale ( PIX *pixs, l_float32 scalex, l_float32 scaley ); l_int32 pixFindSkew ( PIX *pixs, l_float32 *pangle, l_float32 *pconf ); l_int32 pixWriteImpliedFormat ( const char *filename, PIX *pix, l_int32 quality, l_int32 progressive ); l_int32 getImpliedFileFormat ( const char *filename ); l_ok pixWriteStream ( FILE *fp, PIX *pix, l_int32 format ); l_ok pixWriteStreamJpeg ( FILE *fp, PIX *pixs, l_int32 quality, l_int32 progressive ); l_ok pixWriteMem ( l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 format ); l_ok pixWriteMemJpeg ( l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 quality, l_int32 progressive ); l_int32 pixWriteMemPng(l_uint8 **pdata, size_t *psize, PIX *pix, l_float32 gamma); void pixDestroy ( PIX **ppix ); l_ok pixEqual(PIX *pix1, PIX *pix2, l_int32 *psame); PIX * pixEndianByteSwapNew(PIX *pixs); PIX * pixDeskew ( PIX *pixs, l_int32 redsearch ); char * getLeptonicaVersion ( ); l_int32 pixCorrelationBinary(PIX *pix1, PIX *pix2, l_float32 *pval); PIX *pixRotate180(PIX *pixd, PIX *pixs); PIX * pixRotateOrth(PIX *pixs, l_int32 quads); l_int32 pixCountPixels ( PIX *pix, l_int32 *pcount, l_int32 *tab8 ); PIX * pixAnd ( PIX *pixd, PIX *pixs1, PIX *pixs2 ); l_int32 * makePixelSumTab8 ( void ); PIX * pixDeserializeFromMemory ( const l_uint32 *data, size_t nbytes ); l_int32 pixSerializeToMemory ( PIX *pixs, l_uint32 **pdata, size_t *pnbytes ); PIX * pixConvertRGBToLuminance(PIX *pixs); PIX * pixConvertTo8(PIX *pixs, l_int32 cmapflag); PIX * pixRemoveColormap(PIX *pixs, l_int32 type); l_int32 pixOtsuAdaptiveThreshold(PIX *pixs, l_int32 sx, l_int32 sy, l_int32 smoothx, l_int32 smoothy, l_float32 scorefract, PIX **ppixth, PIX **ppixd); PIX * pixOtsuThreshOnBackgroundNorm(PIX *pixs, PIX *pixim, l_int32 sx, l_int32 sy, l_int32 thresh, l_int32 mincount, l_int32 bgval, l_int32 smoothx, l_int32 smoothy, l_float32 scorefract, l_int32 *pthresh); PIX * pixMaskedThreshOnBackgroundNorm(PIX *pixs, PIX *pixim, l_int32 sx, l_int32 sy, l_int32 thresh, l_int32 mincount, l_int32 smoothx, l_int32 smoothy, l_float32 scorefract, l_int32 *pthresh); PIX * pixCleanBackgroundToWhite(PIX *pixs, PIX *pixim, PIX *pixg, l_float32 gamma, l_int32 blackval, l_int32 whiteval); BOX * pixFindPageForeground ( PIX *pixs, l_int32 threshold, l_int32 mindist, l_int32 erasedist, l_int32 showmorph, PIXAC *pixac ); PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc); PIX * pixBackgroundNorm(PIX *pixs, PIX *pixim, PIX *pixg, l_int32 sx, l_int32 sy, l_int32 thresh, l_int32 mincount, l_int32 bgval, l_int32 smoothx, l_int32 smoothy); PIX * pixGammaTRC(PIX *pixd, PIX *pixs, l_float32 gamma, l_int32 minval, l_int32 maxval); l_int32 pixNumSignificantGrayColors(PIX *pixs, l_int32 darkthresh, l_int32 lightthresh, l_float32 minfract, l_int32 factor, l_int32 *pncolors); l_int32 pixColorFraction(PIX *pixs, l_int32 darkthresh, l_int32 lightthresh, l_int32 diffthresh, l_int32 factor, l_float32 *ppixfract, l_float32 *pcolorfract); PIX * pixColorMagnitude(PIX *pixs, l_int32 rwhite, l_int32 gwhite, l_int32 bwhite, l_int32 type); PIX * pixMaskOverColorPixels(PIX *pixs, l_int32 threshdiff, l_int32 mindist); l_int32 pixGetAverageMaskedRGB(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, l_int32 type, l_float32 *prval, l_float32 *pgval, l_float32 *pbval); PIX * pixGlobalNormRGB(PIX * pixd, PIX * pixs, l_int32 rval, l_int32 gval, l_int32 bval, l_int32 mapval); PIX * pixInvert(PIX * pixd, PIX * pixs); PIX * pixRemoveColormapGeneral(PIX *pixs, l_int32 type, l_int32 ifnocmap); l_int32 pixGenerateCIData(PIX *pixs, l_int32 type, l_int32 quality, l_int32 ascii85, L_COMP_DATA **pcid); SARRAY * pixProcessBarcodes(PIX *pixs, l_int32 format, l_int32 method, SARRAY **psaw, l_int32 debugflag); PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype); BOX* pixaGetBox (PIXA * pixa, l_int32 index, l_int32 accesstype ); PIXA * pixExtractBarcodes(PIX *pixs, l_int32 debugflag); BOXA * pixLocateBarcodes ( PIX *pixs, l_int32 thresh, PIX **ppixb, PIX **ppixm ); SARRAY * pixReadBarcodes(PIXA *pixa, l_int32 format, l_int32 method, SARRAY **psaw, l_int32 debugflag); PIX * pixGenHalftoneMask(PIX *pixs, PIX **ppixtext, l_int32 *phtfound, PIXA *pixadb); l_int32 l_generateCIDataForPdf(const char *fname, PIX *pix, l_int32 quality, L_COMP_DATA **pcid); BOX * boxClone ( BOX *box ); BOX * boxaGetBox ( BOXA *boxa, l_int32 index, l_int32 accessflag ); SEL * selCreateFromString ( const char *text, l_int32 h, l_int32 w, const char *name ); SEL * selCreateBrick ( l_int32 h, l_int32 w, l_int32 cy, l_int32 cx, l_int32 type ); char * selPrintToString(SEL *sel); PIX * pixDilate ( PIX *pixd, PIX *pixs, SEL *sel ); PIX * pixErode ( PIX *pixd, PIX *pixs, SEL *sel ); PIX * pixHMT ( PIX *pixd, PIX *pixs, SEL *sel ); PIX * pixSubtract ( PIX *pixd, PIX *pixs1, PIX *pixs2 ); void boxDestroy(BOX **pbox); void boxaDestroy ( BOXA **pboxa ); void pixaDestroy(PIXA **ppixa); l_ok pixRenderBoxa ( PIX *pix, BOXA *boxa, l_int32 width, l_int32 op ); void l_CIDataDestroy(L_COMP_DATA **pcid); void sarrayDestroy(SARRAY **psa); void lept_free(void *ptr); void selDestroy ( SEL **psel ); l_int32 setMsgSeverity(l_int32 newsev); void leptSetStderrHandler(void (*handler)(const char *)); """ ) ffibuilder.set_source("ocrmypdf.lib._leptonica", None) if __name__ == '__main__': ffibuilder.compile(verbose=True) if Path('ocrmypdf/lib/_leptonica.py').exists() and Path('src/ocrmypdf').exists(): output = Path('ocrmypdf/lib/_leptonica.py') output.rename('src/ocrmypdf/lib/_leptonica.py') Path('ocrmypdf/lib').rmdir() Path('ocrmypdf').rmdir()