/* leptonica 1.62 doesn't have this function yet, so here it is. */ int fileformat(char *filename){ FILE *fp; int format; if ((fp = fopenReadStream(filename)) == NULL) return ERROR_INT("image file not found", "fileformat", 1); #ifdef NEWLEPT findFileFormat(filename,&format); #else format=findFileFormat(fp); #endif fclose(fp); return format; }
/*! * pixReadRGBAPng() * * Input: filename (of png file) * Return: pix, or null on error * * Notes: * (1) Wrapper to keep the alpha channel of a png, if it exists. * (2) The default behavior of pix read functions is to ignore * the alpha channel. * (3) This always leaves alpha stripping in the same mode as * when this function begins. So if alpha stripping is in * default mode, this disables it, reads the file (including * the alpha channel), and resets back to stripping. Otherwise, * it leaves stripping disabled. */ PIX * pixReadRGBAPng(const char *filename) { l_int32 format; PIX *pix; PROCNAME("pixReadRGBAPng"); if (!filename) return (PIX *)ERROR_PTR("filename not defined", procName, NULL); /* Make sure it's a png file */ findFileFormat(filename, &format); if (format != IFF_PNG) { L_ERROR_STRING("file format is %s, not png", procName, ImageFileFormatExtensions[format]); return NULL; } /* If alpha channel reading is enabled, just read it */ if (var_PNG_STRIP_ALPHA == FALSE) return pixRead(filename); l_pngSetStripAlpha(0); pix = pixRead(filename); l_pngSetStripAlpha(1); /* reset to default */ if (!pix) L_ERROR("pix not read", procName); return pix; }
/* * writeImageCompressedToPSFile() * * Input: filein (input image file) * fileout (output ps file) * res (output printer resolution) * &firstfile (<input and return> 1 if the first image; * 0 otherwise) * &index (<input and return> index of image in output ps file) * Return: 0 if OK, 1 on error * * Notes: * (1) This wraps a single page image in PS. * (2) The input file can be in any format. It is compressed as follows: * * if in tiffg4 --> use ccittg4 * * if in jpeg --> use dct * * all others --> use flate * (3) @index is incremented if the page is successfully written. */ l_int32 writeImageCompressedToPSFile(const char *filein, const char *fileout, l_int32 res, l_int32 *pfirstfile, l_int32 *pindex) { const char *op; l_int32 format, retval; FILE *fp; PROCNAME("writeImageCompressedToPSFile"); if (!pfirstfile || !pindex) return ERROR_INT("&firstfile and &index not defined", procName, 1); if ((fp = fopenReadStream(filein)) == NULL) return ERROR_INT("filein not found", procName, 1); findFileFormat(fp, &format); fclose(fp); if (format == IFF_UNKNOWN) { L_ERROR_STRING("Format of %s not known", procName, filein); return 1; } op = (*pfirstfile == TRUE) ? "w" : "a"; if (format == IFF_JFIF_JPEG) { retval = convertJpegToPS(filein, fileout, op, 0, 0, res, 1.0, *pindex + 1, TRUE); if (retval == 0) { *pfirstfile = FALSE; (*pindex)++; } } else if (format == IFF_TIFF_G4) { retval = convertTiffG4ToPS(filein, fileout, op, 0, 0, res, 1.0, *pindex + 1, FALSE, TRUE); if (retval == 0) { *pfirstfile = FALSE; (*pindex)++; } } else { /* all other image formats */ retval = convertFlateToPS(filein, fileout, op, 0, 0, res, 1.0, *pindex + 1, TRUE); if (retval == 0) { *pfirstfile = FALSE; (*pindex)++; } } return retval; }
/*! * extractJpegDataFromFile() * * Input: filein * &data (<return> binary data consisting of the entire jpeg file) * &nbytes (<return> size of binary data) * &w (<optional return> image width) * &h (<optional return> image height) * &bps (<optional return> bits/sample; should be 8) * &spp (<optional return> samples/pixel; should be 1 or 3) * Return: 0 if OK, 1 on error */ l_int32 extractJpegDataFromFile(const char *filein, l_uint8 **pdata, l_int32 *pnbytes, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp) { l_uint8 *data; l_int32 format, nbytes; FILE *fpin; PROCNAME("extractJpegDataFromFile"); if (!filein) return ERROR_INT("filein not defined", procName, 1); if (!pdata) return ERROR_INT("&data not defined", procName, 1); if (!pnbytes) return ERROR_INT("&nbytes not defined", procName, 1); if (!pw && !ph && !pbps && !pspp) return ERROR_INT("no output data requested", procName, 1); *pdata = NULL; *pnbytes = 0; if ((fpin = fopen(filein, "rb")) == NULL) return ERROR_INT("filein not defined", procName, 1); findFileFormat(fpin, &format); fclose(fpin); if (format != IFF_JFIF_JPEG) return ERROR_INT("filein not jfif jpeg", procName, 1); if ((data = arrayRead(filein, &nbytes)) == NULL) return ERROR_INT("inarray not made", procName, 1); *pnbytes = nbytes; *pdata = data; /* On error, free the data */ if (extractJpegDataFromArray(data, nbytes, pw, ph, pbps, pspp)) { FREE(data); *pdata = NULL; *pnbytes = 0; } return 0; }
/*! * \brief l_getIndexFromFile() * * \param[in] filename * \param[out] pindex found index * \return 0 if found, 1 on error. */ static l_int32 l_getIndexFromFile(const char *filename, l_int32 *pindex) { char buf[256]; char *word; FILE *fp; l_int32 notfound, format; SARRAY *sa; PROCNAME("l_getIndexFromFile"); if (!pindex) return ERROR_INT("&index not defined", procName, 1); *pindex = 0; if (!filename) return ERROR_INT("filename not defined", procName, 1); /* Open the stream, read lines until you find one with more * than a newline, and grab the first word. */ if ((fp = fopenReadStream(filename)) == NULL) return ERROR_INT("stream not opened", procName, 1); do { if ((fgets(buf, sizeof(buf), fp)) == NULL) { fclose(fp); return ERROR_INT("fgets read fail", procName, 1); } } while (buf[0] == '\n'); fclose(fp); sa = sarrayCreateWordsFromString(buf); word = sarrayGetString(sa, 0, L_NOCOPY); /* Find the index associated with the word. If it is not * found, test to see if the file is a compressed pix. */ notfound = l_getIndexFromStructname(word, pindex); sarrayDestroy(&sa); if (notfound) { /* maybe a Pix */ if (findFileFormat(filename, &format) == 0) { l_getIndexFromStructname("Pix", pindex); } else { return ERROR_INT("no file type identified", procName, 1); } } return 0; }
int addGageToRainFile(int i) // // Input: i = rain gage index // Output: returns 1 if successful, 0 if not // Purpose: adds a gage's rainfall record to rain interface file // { FILE* f; // pointer to rain file int fileFormat; // file format code int hdrLines; // number of header lines skipped //////////////////////////////////// //// New line added. (LR - 7/5/06 ) //////////////////////////////////// // --- let StationID point to NULL StationID = NULL; // --- check that rain file exists if ( (f = fopen(Gage[i].fname, "rt")) == NULL ) report_writeErrorMsg(ERR_RAIN_FILE_DATA, Gage[i].fname); else { fileFormat = findFileFormat(f, i, &hdrLines); if ( fileFormat == UNKNOWN_FORMAT ) { report_writeErrorMsg(ERR_RAIN_FILE_FORMAT, Gage[i].fname); } else { readFile(f, fileFormat, hdrLines, Gage[i].startFileDate, Gage[i].endFileDate); } fclose(f); } if ( ErrorCode ) return 0; else return 1; }
/*! * regTestCheckFile() * * Input: rp (regtest parameters) * localname (name of output file from reg test) * Return: 0 if OK, 1 on error (a failure in comparison is not an error) * * Notes: * (1) This function does one of three things, depending on the mode: * * "generate": makes a "golden" file as a copy @localname. * * "compare": compares @localname contents with the golden file * * "display": makes the @localname file but does no comparison * (2) The canonical format of the golden filenames is: * /tmp/golden/<root of main name>_golden.<index>.<ext of localname> * e.g., * /tmp/golden/maze_golden.0.png * It is important to add an extension to the local name, because * the extension is added to the name of the golden file. */ l_int32 regTestCheckFile(L_REGPARAMS *rp, const char *localname) { char *ext; char namebuf[256]; l_int32 ret, same, format; PIX *pix1, *pix2; PROCNAME("regTestCheckFile"); if (!rp) return ERROR_INT("rp not defined", procName, 1); if (!localname) { rp->success = FALSE; return ERROR_INT("local name not defined", procName, 1); } if (rp->mode != L_REG_GENERATE && rp->mode != L_REG_COMPARE && rp->mode != L_REG_DISPLAY) { rp->success = FALSE; return ERROR_INT("invalid mode", procName, 1); } rp->index++; /* If display mode, no generation and no testing */ if (rp->mode == L_REG_DISPLAY) return 0; /* Generate the golden file name; used in 'generate' and 'compare' */ splitPathAtExtension(localname, NULL, &ext); snprintf(namebuf, sizeof(namebuf), "/tmp/golden/%s_golden.%02d%s", rp->testname, rp->index, ext); FREE(ext); /* Generate mode. No testing. */ if (rp->mode == L_REG_GENERATE) { /* Save the file as a golden file */ ret = fileCopy(localname, namebuf); #if 0 /* Enable for details on writing of golden files */ if (!ret) { char *local = genPathname(localname, NULL); char *golden = genPathname(namebuf, NULL); L_INFO("Copy: %s to %s\n", procName, local, golden); FREE(local); FREE(golden); } #endif return ret; } /* Compare mode: test and record on failure. GIF compression * is lossless for images with up to 8 bpp (but not for RGB * because it must generate a 256 color palette). Although * the read/write cycle for GIF is idempotent in the image * pixels for bpp <= 8, it is not idempotent in the actual * file bytes. Tests comparing file bytes before and after * a GIF read/write cycle will fail. So for GIF we uncompress * the two images and compare the actual pixels. From my tests, * PNG, in addition to being lossless, is idempotent in file * bytes on read/write, so comparing the pixels is not necessary. * (It also increases the regression test time by an an average * of about 8%.) JPEG is lossy and not idempotent in the image * pixels, so no tests are constructed that would require it. */ findFileFormat(localname, &format); if (format == IFF_GIF) { same = 0; pix1 = pixRead(localname); pix2 = pixRead(namebuf); pixEqual(pix1, pix2, &same); pixDestroy(&pix1); pixDestroy(&pix2); } else { filesAreIdentical(localname, namebuf, &same); } if (!same) { fprintf(rp->fp, "Failure in %s_reg, index %d: comparing %s with %s\n", rp->testname, rp->index, localname, namebuf); fprintf(stderr, "Failure in %s_reg, index %d: comparing %s with %s\n", rp->testname, rp->index, localname, namebuf); rp->success = FALSE; } return 0; }
bool TessPDFRenderer::imageToPDFObj(Pix *pix, char *filename, long int objnum, char **pdf_object, long int *pdf_object_size) { size_t n; char b0[kBasicBufSize]; char b1[kBasicBufSize]; char b2[kBasicBufSize]; if (!pdf_object_size || !pdf_object) return false; *pdf_object = NULL; *pdf_object_size = 0; if (!filename) return false; L_COMP_DATA *cid = NULL; const int kJpegQuality = 85; // TODO(jbreiden) Leptonica 1.71 doesn't correctly handle certain // types of PNG files, especially if there are 2 samples per pixel. // We can get rid of this logic after Leptonica 1.72 is released and // has propagated everywhere. Bug discussion as follows. // https://code.google.com/p/tesseract-ocr/issues/detail?id=1300 int format, sad; findFileFormat(filename, &format); if (pixGetSpp(pix) == 4 && format == IFF_PNG) { pixSetSpp(pix, 3); sad = pixGenerateCIData(pix, L_FLATE_ENCODE, 0, 0, &cid); } else { sad = l_generateCIDataForPdf(filename, pix, kJpegQuality, &cid); } if (sad || !cid) { l_CIDataDestroy(&cid); return false; } const char *group4 = ""; const char *filter; switch (cid->type) { case L_FLATE_ENCODE: filter = "/FlateDecode"; break; case L_JPEG_ENCODE: filter = "/DCTDecode"; break; case L_G4_ENCODE: filter = "/CCITTFaxDecode"; group4 = " /K -1\n"; break; case L_JP2K_ENCODE: filter = "/JPXDecode"; break; default: l_CIDataDestroy(&cid); return false; } // Maybe someday we will accept RGBA but today is not that day. // It requires creating an /SMask for the alpha channel. // http://stackoverflow.com/questions/14220221 const char *colorspace; if (cid->ncolors > 0) { n = snprintf(b0, sizeof(b0), " /ColorSpace [ /Indexed /DeviceRGB %d %s ]\n", cid->ncolors - 1, cid->cmapdatahex); if (n >= sizeof(b0)) { l_CIDataDestroy(&cid); return false; } colorspace = b0; } else { switch (cid->spp) { case 1: colorspace = " /ColorSpace /DeviceGray\n"; break; case 3: colorspace = " /ColorSpace /DeviceRGB\n"; break; default: l_CIDataDestroy(&cid); return false; } } int predictor = (cid->predictor) ? 14 : 1; // IMAGE n = snprintf(b1, sizeof(b1), "%ld 0 obj\n" "<<\n" " /Length %ld\n" " /Subtype /Image\n", objnum, (unsigned long) cid->nbytescomp); if (n >= sizeof(b1)) { l_CIDataDestroy(&cid); return false; } n = snprintf(b2, sizeof(b2), " /Width %d\n" " /Height %d\n" " /BitsPerComponent %d\n" " /Filter %s\n" " /DecodeParms\n" " <<\n" " /Predictor %d\n" " /Colors %d\n" "%s" " /Columns %d\n" " /BitsPerComponent %d\n" " >>\n" ">>\n" "stream\n", cid->w, cid->h, cid->bps, filter, predictor, cid->spp, group4, cid->w, cid->bps); if (n >= sizeof(b2)) { l_CIDataDestroy(&cid); return false; } const char *b3 = "endstream\n" "endobj\n"; size_t b1_len = strlen(b1); size_t b2_len = strlen(b2); size_t b3_len = strlen(b3); size_t colorspace_len = strlen(colorspace); *pdf_object_size = b1_len + colorspace_len + b2_len + cid->nbytescomp + b3_len; *pdf_object = new char[*pdf_object_size]; if (!pdf_object) { l_CIDataDestroy(&cid); return false; } char *p = *pdf_object; memcpy(p, b1, b1_len); p += b1_len; memcpy(p, colorspace, colorspace_len); p += colorspace_len; memcpy(p, b2, b2_len); p += b2_len; memcpy(p, cid->datacomp, cid->nbytescomp); p += cid->nbytescomp; memcpy(p, b3, b3_len); l_CIDataDestroy(&cid); return true; }
/* * convertToPSEmbed() * * Input: filein (input image file -- any format) * fileout (output ps file) * level (compression: 1 (uncompressed), 2 or 3) * Return: 0 if OK, 1 on error * * Notes: * (1) This is a wrapper function that generates a PS file with * a bounding box, from any input image file. * (2) Do the best job of compression given the specified level. * @level=3 does flate compression on anything that is not * tiffg4 (1 bpp) or jpeg (8 bpp or rgb). * (3) If @level=2 and the file is not tiffg4 or jpeg, it will * first be written to file as jpeg with quality = 75. * This will remove the colormap and cause some degradation * in the image. * (4) The bounding box is required when a program such as TeX * (through epsf) places and rescales the image. It is * sized for fitting the image to an 8.5 x 11.0 inch page. */ l_int32 convertToPSEmbed(const char *filein, const char *fileout, l_int32 level) { const char nametif[] = "/tmp/junk_convert_ps_embed.tif"; const char namejpg[] = "/tmp/junk_convert_ps_embed.jpg"; l_int32 d, format; FILE *fp; PIX *pix, *pixs; PROCNAME("convertToPSEmbed"); if (!filein) return ERROR_INT("filein not defined", procName, 1); if (!fileout) return ERROR_INT("fileout not defined", procName, 1); if (level != 1 && level != 2 && level != 3) { L_ERROR("invalid level specified; using level 2", procName); level = 2; } if (level == 1) { /* no compression */ pixWritePSEmbed(filein, fileout); return 0; } /* Find the format and write out directly if in jpeg or tiff g4 */ if ((fp = fopen(filein, "rb")) == NULL) return ERROR_INT("filein not found", procName, 1); findFileFormat(fp, &format); fclose(fp); if (format == IFF_JFIF_JPEG) { convertJpegToPSEmbed(filein, fileout); return 0; } else if (format == IFF_TIFF_G4) { convertTiffG4ToPSEmbed(filein, fileout); return 0; } /* If level 3, flate encode. */ if (level == 3) { convertFlateToPSEmbed(filein, fileout); return 0; } /* OK, it's level 2, so we must convert to jpeg or tiff g4 */ if ((pixs = pixRead(filein)) == NULL) return ERROR_INT("image not read from file", procName, 1); d = pixGetDepth(pixs); if ((d == 2 || d == 4) && !pixGetColormap(pixs)) pix = pixConvertTo8(pixs, 0); else if (d == 16) pix = pixConvert16To8(pixs, 1); else pix = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); d = pixGetDepth(pix); if (d == 1) { pixWrite(nametif, pix, IFF_TIFF_G4); convertTiffG4ToPSEmbed(nametif, fileout); } else { pixWrite(namejpg, pix, IFF_JFIF_JPEG); convertJpegToPSEmbed(namejpg, fileout); } pixDestroy(&pix); pixDestroy(&pixs); return 0; }
bool TessPDFRenderer::imageToPDFObj(Pix *pix, char *filename, long int objnum, char **pdf_object, long int *pdf_object_size) { size_t n; char b0[kBasicBufSize]; char b1[kBasicBufSize]; char b2[kBasicBufSize]; if (!pdf_object_size || !pdf_object) return false; *pdf_object = nullptr; *pdf_object_size = 0; if (!filename) return false; L_Compressed_Data *cid = nullptr; const int kJpegQuality = 85; int format, sad; findFileFormat(filename, &format); if (pixGetSpp(pix) == 4 && format == IFF_PNG) { Pix *p1 = pixAlphaBlendUniform(pix, 0xffffff00); sad = pixGenerateCIData(p1, L_FLATE_ENCODE, 0, 0, &cid); pixDestroy(&p1); } else { sad = l_generateCIDataForPdf(filename, pix, kJpegQuality, &cid); } if (sad || !cid) { l_CIDataDestroy(&cid); return false; } const char *group4 = ""; const char *filter; switch(cid->type) { case L_FLATE_ENCODE: filter = "/FlateDecode"; break; case L_JPEG_ENCODE: filter = "/DCTDecode"; break; case L_G4_ENCODE: filter = "/CCITTFaxDecode"; group4 = " /K -1\n"; break; case L_JP2K_ENCODE: filter = "/JPXDecode"; break; default: l_CIDataDestroy(&cid); return false; } // Maybe someday we will accept RGBA but today is not that day. // It requires creating an /SMask for the alpha channel. // http://stackoverflow.com/questions/14220221 const char *colorspace; if (cid->ncolors > 0) { n = snprintf(b0, sizeof(b0), " /ColorSpace [ /Indexed /DeviceRGB %d %s ]\n", cid->ncolors - 1, cid->cmapdatahex); if (n >= sizeof(b0)) { l_CIDataDestroy(&cid); return false; } colorspace = b0; } else { switch (cid->spp) { case 1: colorspace = " /ColorSpace /DeviceGray\n"; break; case 3: colorspace = " /ColorSpace /DeviceRGB\n"; break; default: l_CIDataDestroy(&cid); return false; } } int predictor = (cid->predictor) ? 14 : 1; // IMAGE n = snprintf(b1, sizeof(b1), "%ld 0 obj\n" "<<\n" " /Length %ld\n" " /Subtype /Image\n", objnum, (unsigned long) cid->nbytescomp); if (n >= sizeof(b1)) { l_CIDataDestroy(&cid); return false; } n = snprintf(b2, sizeof(b2), " /Width %d\n" " /Height %d\n" " /BitsPerComponent %d\n" " /Filter %s\n" " /DecodeParms\n" " <<\n" " /Predictor %d\n" " /Colors %d\n" "%s" " /Columns %d\n" " /BitsPerComponent %d\n" " >>\n" ">>\n" "stream\n", cid->w, cid->h, cid->bps, filter, predictor, cid->spp, group4, cid->w, cid->bps); if (n >= sizeof(b2)) { l_CIDataDestroy(&cid); return false; } const char *b3 = "endstream\n" "endobj\n"; size_t b1_len = strlen(b1); size_t b2_len = strlen(b2); size_t b3_len = strlen(b3); size_t colorspace_len = strlen(colorspace); *pdf_object_size = b1_len + colorspace_len + b2_len + cid->nbytescomp + b3_len; *pdf_object = new char[*pdf_object_size]; char *p = *pdf_object; memcpy(p, b1, b1_len); p += b1_len; memcpy(p, colorspace, colorspace_len); p += colorspace_len; memcpy(p, b2, b2_len); p += b2_len; memcpy(p, cid->datacomp, cid->nbytescomp); p += cid->nbytescomp; memcpy(p, b3, b3_len); l_CIDataDestroy(&cid); return true; }
/* * convertToPSEmbed() * * Input: filein (input image file -- any format) * fileout (output ps file) * level (compression: 1 (uncompressed), 2 or 3) * Return: 0 if OK, 1 on error * * Notes: * (1) This is a wrapper function that generates a PS file with * a bounding box, from any input image file. * (2) Do the best job of compression given the specified level. * %level=3 does flate compression on anything that is not * tiffg4 (1 bpp) or jpeg (8 bpp or rgb). * (3) If %level=2 and the file is not tiffg4 or jpeg, it will * first be written to file as jpeg with quality = 75. * This will remove the colormap and cause some degradation * in the image. * (4) The bounding box is required when a program such as TeX * (through epsf) places and rescales the image. It is * sized for fitting the image to an 8.5 x 11.0 inch page. */ l_int32 convertToPSEmbed(const char *filein, const char *fileout, l_int32 level) { char *tname; l_int32 d, format; PIX *pix, *pixs; PROCNAME("convertToPSEmbed"); if (!filein) return ERROR_INT("filein not defined", procName, 1); if (!fileout) return ERROR_INT("fileout not defined", procName, 1); if (level != 1 && level != 2 && level != 3) { L_ERROR("invalid level specified; using level 2\n", procName); level = 2; } if (level == 1) { /* no compression */ pixWritePSEmbed(filein, fileout); return 0; } /* Find the format and write out directly if in jpeg or tiff g4 */ findFileFormat(filein, &format); if (format == IFF_JFIF_JPEG) { convertJpegToPSEmbed(filein, fileout); return 0; } else if (format == IFF_TIFF_G4) { convertG4ToPSEmbed(filein, fileout); return 0; } else if (format == IFF_UNKNOWN) { L_ERROR("format of %s not known\n", procName, filein); return 1; } /* If level 3, flate encode. */ if (level == 3) { convertFlateToPSEmbed(filein, fileout); return 0; } /* OK, it's level 2, so we must convert to jpeg or tiff g4 */ if ((pixs = pixRead(filein)) == NULL) return ERROR_INT("image not read from file", procName, 1); d = pixGetDepth(pixs); if ((d == 2 || d == 4) && !pixGetColormap(pixs)) pix = pixConvertTo8(pixs, 0); else if (d == 16) pix = pixConvert16To8(pixs, 1); else pix = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); d = pixGetDepth(pix); tname = l_makeTempFilename(NULL); if (d == 1) { pixWrite(tname, pix, IFF_TIFF_G4); convertG4ToPSEmbed(tname, fileout); } else { pixWrite(tname, pix, IFF_JFIF_JPEG); convertJpegToPSEmbed(tname, fileout); } lept_rmfile(tname); LEPT_FREE(tname); pixDestroy(&pix); pixDestroy(&pixs); return 0; }