Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/leptonica/src/psio2.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /*====================================================================* | |
| 2 - Copyright (C) 2001 Leptonica. All rights reserved. | |
| 3 - | |
| 4 - Redistribution and use in source and binary forms, with or without | |
| 5 - modification, are permitted provided that the following conditions | |
| 6 - are met: | |
| 7 - 1. Redistributions of source code must retain the above copyright | |
| 8 - notice, this list of conditions and the following disclaimer. | |
| 9 - 2. Redistributions in binary form must reproduce the above | |
| 10 - copyright notice, this list of conditions and the following | |
| 11 - disclaimer in the documentation and/or other materials | |
| 12 - provided with the distribution. | |
| 13 - | |
| 14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY | |
| 18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 25 *====================================================================*/ | |
| 26 | |
| 27 /*! | |
| 28 * \file psio2.c | |
| 29 * <pre> | |
| 30 * | |
| 31 * |=============================================================| | |
| 32 * | Important note | | |
| 33 * |=============================================================| | |
| 34 * | Some of these functions require I/O libraries such as | | |
| 35 * | libtiff, libjpeg, and libz. If you do not have these | | |
| 36 * | libraries, some calls will fail. | | |
| 37 * | | | |
| 38 * | You can manually deactivate all PostScript writing by | | |
| 39 * | setting this in environ.h: | | |
| 40 * | \code | | |
| 41 * | #define USE_PSIO 0 | | |
| 42 * | \endcode | | |
| 43 * | in environ.h. This will link psio2stub.c | | |
| 44 * |=============================================================| | |
| 45 * | |
| 46 * These are lower-level functions that implement a PostScript | |
| 47 * "device driver" for wrapping images in PostScript. The images | |
| 48 * can be rendered by a PostScript interpreter for viewing, | |
| 49 * using evince or gv. They can also be rasterized for printing, | |
| 50 * using gs or an embedded interpreter in a PostScript printer. | |
| 51 * And they can be converted to a pdf using gs (ps2pdf). | |
| 52 * | |
| 53 * For uncompressed images | |
| 54 * l_int32 pixWritePSEmbed() | |
| 55 * l_int32 pixWriteStreamPS() | |
| 56 * char *pixWriteStringPS() | |
| 57 * char *generateUncompressedPS() | |
| 58 * static void getScaledParametersPS() | |
| 59 * static l_int32 convertByteToHexAscii() | |
| 60 * | |
| 61 * For jpeg compressed images (use dct compression) | |
| 62 * l_int32 convertJpegToPSEmbed() | |
| 63 * l_int32 convertJpegToPS() | |
| 64 * static l_int32 convertJpegToPSString() | |
| 65 * static char *generateJpegPS() | |
| 66 * | |
| 67 * For g4 fax compressed images (use ccitt g4 compression) | |
| 68 * l_int32 convertG4ToPSEmbed() | |
| 69 * l_int32 convertG4ToPS() | |
| 70 * static l_int32 convertG4ToPSString() | |
| 71 * static char *generateG4PS() | |
| 72 * | |
| 73 * For multipage tiff images | |
| 74 * l_int32 convertTiffMultipageToPS() | |
| 75 * | |
| 76 * For flate (gzip) compressed images (e.g., png) | |
| 77 * l_int32 convertFlateToPSEmbed() | |
| 78 * l_int32 convertFlateToPS() | |
| 79 * static l_int32 convertFlateToPSString() | |
| 80 * static char *generateFlatePS() | |
| 81 * | |
| 82 * Write to memory | |
| 83 * l_int32 pixWriteMemPS() | |
| 84 * | |
| 85 * Converting resolution | |
| 86 * l_int32 getResLetterPage() | |
| 87 * static l_int32 getResA4Page() | |
| 88 * | |
| 89 * Setting flag for writing bounding box hint | |
| 90 * void l_psWriteBoundingBox() | |
| 91 * | |
| 92 * See psio1.c for higher-level functions and their usage. | |
| 93 * </pre> | |
| 94 */ | |
| 95 | |
| 96 #ifdef HAVE_CONFIG_H | |
| 97 #include <config_auto.h> | |
| 98 #endif /* HAVE_CONFIG_H */ | |
| 99 | |
| 100 #include <string.h> | |
| 101 #include "allheaders.h" | |
| 102 | |
| 103 /* --------------------------------------------*/ | |
| 104 #if USE_PSIO /* defined in environ.h */ | |
| 105 /* --------------------------------------------*/ | |
| 106 | |
| 107 /* Set default for writing bounding box hint */ | |
| 108 static l_int32 var_PS_WRITE_BOUNDING_BOX = 1; | |
| 109 | |
| 110 #define Bufsize 512 | |
| 111 static const l_int32 DefaultInputRes = 300; /* typical scan res, ppi */ | |
| 112 static const l_int32 MinRes = 5; | |
| 113 static const l_int32 MaxRes = 3000; | |
| 114 | |
| 115 /* For computing resolution that fills page to desired amount */ | |
| 116 static const l_int32 LetterWidth = 612; /* points */ | |
| 117 static const l_int32 LetterHeight = 792; /* points */ | |
| 118 static const l_int32 A4Width = 595; /* points */ | |
| 119 static const l_int32 A4Height = 842; /* points */ | |
| 120 static const l_float32 DefaultFillFraction = 0.95f; | |
| 121 | |
| 122 #ifndef NO_CONSOLE_IO | |
| 123 #define DEBUG_JPEG 0 | |
| 124 #define DEBUG_G4 0 | |
| 125 #define DEBUG_FLATE 0 | |
| 126 #endif /* ~NO_CONSOLE_IO */ | |
| 127 | |
| 128 /* Note that the bounding box hint at the top of the generated PostScript | |
| 129 * file is required for the "*Embed" functions. These generate a | |
| 130 * PostScript file for an individual image that can be translated and | |
| 131 * scaled by an application that embeds the image in its output | |
| 132 * (e.g., in the PS output from a TeX file). | |
| 133 * However, bounding box hints should not be embedded in any | |
| 134 * PostScript image that will be composited with other images, | |
| 135 * where more than one image may be placed in an arbitrary location | |
| 136 * on a page. */ | |
| 137 | |
| 138 /* Static helper functions */ | |
| 139 static void getScaledParametersPS(BOX *box, l_int32 wpix, l_int32 hpix, | |
| 140 l_int32 res, l_float32 scale, | |
| 141 l_float32 *pxpt, l_float32 *pypt, | |
| 142 l_float32 *pwpt, l_float32 *phpt); | |
| 143 static void convertByteToHexAscii(l_uint8 byteval, char *pnib1, char *pnib2); | |
| 144 static l_ok convertJpegToPSString(const char *filein, char **poutstr, | |
| 145 l_int32 *pnbytes, l_int32 x, l_int32 y, | |
| 146 l_int32 res, l_float32 scale, | |
| 147 l_int32 pageno, l_int32 endpage); | |
| 148 static char *generateJpegPS(const char *filein, L_COMP_DATA *cid, | |
| 149 l_float32 xpt, l_float32 ypt, l_float32 wpt, | |
| 150 l_float32 hpt, l_int32 pageno, l_int32 endpage); | |
| 151 static l_ok convertG4ToPSString(const char *filein, char **poutstr, | |
| 152 l_int32 *pnbytes, l_int32 x, l_int32 y, | |
| 153 l_int32 res, l_float32 scale, l_int32 pageno, | |
| 154 l_int32 maskflag, l_int32 endpage); | |
| 155 static char *generateG4PS(const char *filein, L_COMP_DATA *cid, l_float32 xpt, | |
| 156 l_float32 ypt, l_float32 wpt, l_float32 hpt, | |
| 157 l_int32 maskflag, l_int32 pageno, l_int32 endpage); | |
| 158 static l_ok convertFlateToPSString(const char *filein, char **poutstr, | |
| 159 l_int32 *pnbytes, l_int32 x, l_int32 y, | |
| 160 l_int32 res, l_float32 scale, | |
| 161 l_int32 pageno, l_int32 endpage); | |
| 162 static char *generateFlatePS(const char *filein, L_COMP_DATA *cid, | |
| 163 l_float32 xpt, l_float32 ypt, l_float32 wpt, | |
| 164 l_float32 hpt, l_int32 pageno, l_int32 endpage); | |
| 165 | |
| 166 | |
| 167 /*-------------------------------------------------------------* | |
| 168 * For uncompressed images * | |
| 169 *-------------------------------------------------------------*/ | |
| 170 /*! | |
| 171 * \brief pixWritePSEmbed() | |
| 172 * | |
| 173 * \param[in] filein input file, all depths, colormap OK | |
| 174 * \param[in] fileout output ps file | |
| 175 * \return 0 if OK, 1 on error | |
| 176 * | |
| 177 * <pre> | |
| 178 * Notes: | |
| 179 * (1) This is a simple wrapper function that generates an | |
| 180 * uncompressed PS file, with a bounding box. | |
| 181 * (2) The bounding box is required when a program such as TeX | |
| 182 * (through epsf) places and rescales the image. | |
| 183 * (3) The bounding box is sized for fitting the image to an | |
| 184 * 8.5 x 11.0 inch page. | |
| 185 * </pre> | |
| 186 */ | |
| 187 l_ok | |
| 188 pixWritePSEmbed(const char *filein, | |
| 189 const char *fileout) | |
| 190 { | |
| 191 l_int32 w, h, ret; | |
| 192 l_float32 scale; | |
| 193 FILE *fp; | |
| 194 PIX *pix; | |
| 195 | |
| 196 if (!filein) | |
| 197 return ERROR_INT("filein not defined", __func__, 1); | |
| 198 if (!fileout) | |
| 199 return ERROR_INT("fileout not defined", __func__, 1); | |
| 200 | |
| 201 if ((pix = pixRead(filein)) == NULL) | |
| 202 return ERROR_INT("image not read from file", __func__, 1); | |
| 203 w = pixGetWidth(pix); | |
| 204 h = pixGetHeight(pix); | |
| 205 if (w * 11.0 > h * 8.5) | |
| 206 scale = 8.5f * 300.f / (l_float32)w; | |
| 207 else | |
| 208 scale = 11.0f * 300.f / (l_float32)h; | |
| 209 | |
| 210 if ((fp = fopenWriteStream(fileout, "wb")) == NULL) | |
| 211 return ERROR_INT_1("file not opened for write", fileout, __func__, 1); | |
| 212 ret = pixWriteStreamPS(fp, pix, NULL, 0, scale); | |
| 213 fclose(fp); | |
| 214 | |
| 215 pixDestroy(&pix); | |
| 216 return ret; | |
| 217 } | |
| 218 | |
| 219 | |
| 220 /*! | |
| 221 * \brief pixWriteStreamPS() | |
| 222 * | |
| 223 * \param[in] fp file stream | |
| 224 * \param[in] pix | |
| 225 * \param[in] box [optional] | |
| 226 * \param[in] res can use 0 for default of 300 ppi | |
| 227 * \param[in] scale to prevent scaling, use either 1.0 or 0.0 | |
| 228 * \return 0 if OK; 1 on error | |
| 229 * | |
| 230 * <pre> | |
| 231 * Notes: | |
| 232 * (1) This writes image in PS format, optionally scaled, | |
| 233 * adjusted for the printer resolution, and with | |
| 234 * a bounding box. | |
| 235 * (2) For details on use of parameters, see pixWriteStringPS(). | |
| 236 * </pre> | |
| 237 */ | |
| 238 l_ok | |
| 239 pixWriteStreamPS(FILE *fp, | |
| 240 PIX *pix, | |
| 241 BOX *box, | |
| 242 l_int32 res, | |
| 243 l_float32 scale) | |
| 244 { | |
| 245 char *outstr; | |
| 246 l_int32 length; | |
| 247 PIX *pixc; | |
| 248 | |
| 249 if (!fp) | |
| 250 return (l_int32)ERROR_INT("stream not open", __func__, 1); | |
| 251 if (!pix) | |
| 252 return (l_int32)ERROR_INT("pix not defined", __func__, 1); | |
| 253 | |
| 254 if ((pixc = pixConvertForPSWrap(pix)) == NULL) | |
| 255 return (l_int32)ERROR_INT("pixc not made", __func__, 1); | |
| 256 | |
| 257 if ((outstr = pixWriteStringPS(pixc, box, res, scale)) == NULL) { | |
| 258 pixDestroy(&pixc); | |
| 259 return (l_int32)ERROR_INT("outstr not made", __func__, 1); | |
| 260 } | |
| 261 length = strlen(outstr); | |
| 262 fwrite(outstr, 1, length, fp); | |
| 263 LEPT_FREE(outstr); | |
| 264 pixDestroy(&pixc); | |
| 265 return 0; | |
| 266 } | |
| 267 | |
| 268 | |
| 269 /*! | |
| 270 * \brief pixWriteStringPS() | |
| 271 * | |
| 272 * \param[in] pixs all depths, colormap OK | |
| 273 * \param[in] box bounding box; can be NULL | |
| 274 * \param[in] res resolution, in printer ppi. Use 0 for default 300 ppi. | |
| 275 * \param[in] scale scale factor. If no scaling is desired, use | |
| 276 * either 1.0 or 0.0. Scaling just resets the resolution | |
| 277 * parameter; the actual scaling is done in the | |
| 278 * interpreter at rendering time. This is important: | |
| 279 * it allows you to scale the image up without | |
| 280 * increasing the file size. | |
| 281 * \return ps string if OK, or NULL on error | |
| 282 * | |
| 283 * <pre> | |
| 284 * a) If %box == NULL, image is placed, optionally scaled, | |
| 285 * in a standard b.b. at the center of the page. | |
| 286 * This is to be used when another program like | |
| 287 * TeX through epsf places the image. | |
| 288 * b) If %box != NULL, image is placed without a | |
| 289 * b.b. at the specified page location and with | |
| 290 * optional scaling. This is to be used when | |
| 291 * you want to specify exactly where and optionally | |
| 292 * how big you want the image to be. | |
| 293 * Note that all coordinates are in PS convention, | |
| 294 * with 0,0 at LL corner of the page: | |
| 295 * x,y location of LL corner of image, in mils. | |
| 296 * w,h scaled size, in mils. Use 0 to | |
| 297 * scale with "scale" and "res" input. | |
| 298 * | |
| 299 * %scale: If no scaling is desired, use either 1.0 or 0.0. | |
| 300 * Scaling just resets the resolution parameter; the actual | |
| 301 * scaling is done in the interpreter at rendering time. | |
| 302 * This is important: * it allows you to scale the image up | |
| 303 * without increasing the file size. | |
| 304 * | |
| 305 * Notes: | |
| 306 * (1) OK, this seems a bit complicated, because there are various | |
| 307 * ways to scale and not to scale. Here's a summary: | |
| 308 * (2) If you don't want any scaling at all: | |
| 309 * * if you are using a box: | |
| 310 * set w = 0, h = 0, and use scale = 1.0; it will print | |
| 311 * each pixel unscaled at printer resolution | |
| 312 * * if you are not using a box: | |
| 313 * set scale = 1.0; it will print at printer resolution | |
| 314 * (3) If you want the image to be a certain size in inches: | |
| 315 * * you must use a box and set the box (w,h) in mils | |
| 316 * (4) If you want the image to be scaled by a scale factor != 1.0: | |
| 317 * * if you are using a box: | |
| 318 * set w = 0, h = 0, and use the desired scale factor; | |
| 319 * the higher the printer resolution, the smaller the | |
| 320 * image will actually appear. | |
| 321 * * if you are not using a box: | |
| 322 * set the desired scale factor; the higher the printer | |
| 323 * resolution, the smaller the image will actually appear. | |
| 324 * (5) Another complication is the proliferation of distance units: | |
| 325 * * The interface distances are in milli-inches. | |
| 326 * * Three different units are used internally: | |
| 327 * ~ pixels (units of 1/res inch) | |
| 328 * ~ printer pts (units of 1/72 inch) | |
| 329 * ~ inches | |
| 330 * * Here is a quiz on volume units from a reviewer: | |
| 331 * How many UK milli-cups in a US kilo-teaspoon? | |
| 332 * (Hint: 1.0 US cup = 0.75 UK cup + 0.2 US gill; | |
| 333 * 1.0 US gill = 24.0 US teaspoons) | |
| 334 * </pre> | |
| 335 */ | |
| 336 char * | |
| 337 pixWriteStringPS(PIX *pixs, | |
| 338 BOX *box, | |
| 339 l_int32 res, | |
| 340 l_float32 scale) | |
| 341 { | |
| 342 char nib1, nib2; | |
| 343 char *hexdata, *outstr; | |
| 344 l_uint8 byteval; | |
| 345 l_int32 i, j, k, w, h, d; | |
| 346 l_float32 wpt, hpt, xpt, ypt; | |
| 347 l_int32 wpl, psbpl, hexbytes, boxflag, bps; | |
| 348 l_uint32 *line, *data; | |
| 349 PIX *pix; | |
| 350 | |
| 351 if (!pixs) | |
| 352 return (char *)ERROR_PTR("pixs not defined", __func__, NULL); | |
| 353 | |
| 354 if ((pix = pixConvertForPSWrap(pixs)) == NULL) | |
| 355 return (char *)ERROR_PTR("pix not made", __func__, NULL); | |
| 356 pixGetDimensions(pix, &w, &h, &d); | |
| 357 | |
| 358 /* Get the factors by which PS scales and translates, in pts */ | |
| 359 if (!box) | |
| 360 boxflag = 0; /* no scaling; b.b. at center */ | |
| 361 else | |
| 362 boxflag = 1; /* no b.b., specify placement and optional scaling */ | |
| 363 getScaledParametersPS(box, w, h, res, scale, &xpt, &ypt, &wpt, &hpt); | |
| 364 | |
| 365 if (d == 1) | |
| 366 bps = 1; /* bits/sample */ | |
| 367 else /* d == 8 || d == 32 */ | |
| 368 bps = 8; | |
| 369 | |
| 370 /* Convert image data to hex string. psbpl is the number of | |
| 371 * bytes in each raster line when it is packed to the byte | |
| 372 * boundary (not the 32 bit word boundary, as with the pix). | |
| 373 * When converted to hex, the hex string has 2 bytes for | |
| 374 * every byte of raster data. */ | |
| 375 wpl = pixGetWpl(pix); | |
| 376 if (d == 1 || d == 8) | |
| 377 psbpl = (w * d + 7) / 8; | |
| 378 else /* d == 32 */ | |
| 379 psbpl = 3 * w; | |
| 380 data = pixGetData(pix); | |
| 381 hexbytes = 2 * psbpl * h; /* size of ps hex array */ | |
| 382 if ((hexdata = (char *)LEPT_CALLOC(hexbytes + 1, sizeof(char))) == NULL) | |
| 383 return (char *)ERROR_PTR("hexdata not made", __func__, NULL); | |
| 384 if (d == 1 || d == 8) { | |
| 385 for (i = 0, k = 0; i < h; i++) { | |
| 386 line = data + i * wpl; | |
| 387 for (j = 0; j < psbpl; j++) { | |
| 388 byteval = GET_DATA_BYTE(line, j); | |
| 389 convertByteToHexAscii(byteval, &nib1, &nib2); | |
| 390 hexdata[k++] = nib1; | |
| 391 hexdata[k++] = nib2; | |
| 392 } | |
| 393 } | |
| 394 } else { /* d == 32; hexdata bytes packed RGBRGB..., 2 per sample */ | |
| 395 for (i = 0, k = 0; i < h; i++) { | |
| 396 line = data + i * wpl; | |
| 397 for (j = 0; j < w; j++) { | |
| 398 byteval = GET_DATA_BYTE(line + j, 0); /* red */ | |
| 399 convertByteToHexAscii(byteval, &nib1, &nib2); | |
| 400 hexdata[k++] = nib1; | |
| 401 hexdata[k++] = nib2; | |
| 402 byteval = GET_DATA_BYTE(line + j, 1); /* green */ | |
| 403 convertByteToHexAscii(byteval, &nib1, &nib2); | |
| 404 hexdata[k++] = nib1; | |
| 405 hexdata[k++] = nib2; | |
| 406 byteval = GET_DATA_BYTE(line + j, 2); /* blue */ | |
| 407 convertByteToHexAscii(byteval, &nib1, &nib2); | |
| 408 hexdata[k++] = nib1; | |
| 409 hexdata[k++] = nib2; | |
| 410 } | |
| 411 } | |
| 412 } | |
| 413 hexdata[k] = '\0'; | |
| 414 | |
| 415 outstr = generateUncompressedPS(hexdata, w, h, d, psbpl, bps, | |
| 416 xpt, ypt, wpt, hpt, boxflag); | |
| 417 pixDestroy(&pix); | |
| 418 if (!outstr) | |
| 419 return (char *)ERROR_PTR("outstr not made", __func__, NULL); | |
| 420 return outstr; | |
| 421 } | |
| 422 | |
| 423 | |
| 424 /*! | |
| 425 * \brief generateUncompressedPS() | |
| 426 * | |
| 427 * \param[in] hexdata | |
| 428 * \param[in] w, h raster image size in pixels | |
| 429 * \param[in] d image depth in bpp; rgb is 32 | |
| 430 * \param[in] psbpl raster bytes/line, when packed to the byte boundary | |
| 431 * \param[in] bps bits/sample: either 1 or 8 | |
| 432 * \param[in] xpt, ypt location of LL corner of image, in pts, relative | |
| 433 * to the PostScript origin (0,0) at the LL corner | |
| 434 * of the page | |
| 435 * \param[in] wpt, hpt rendered image size in pts | |
| 436 * \param[in] boxflag 1 to print out bounding box hint; 0 to skip | |
| 437 * \return PS string, or NULL on error | |
| 438 * | |
| 439 * <pre> | |
| 440 * Notes: | |
| 441 * (1) Low-level function. | |
| 442 * </pre> | |
| 443 */ | |
| 444 char * | |
| 445 generateUncompressedPS(char *hexdata, | |
| 446 l_int32 w, | |
| 447 l_int32 h, | |
| 448 l_int32 d, | |
| 449 l_int32 psbpl, | |
| 450 l_int32 bps, | |
| 451 l_float32 xpt, | |
| 452 l_float32 ypt, | |
| 453 l_float32 wpt, | |
| 454 l_float32 hpt, | |
| 455 l_int32 boxflag) | |
| 456 { | |
| 457 char *outstr; | |
| 458 char bigbuf[Bufsize]; | |
| 459 SARRAY *sa; | |
| 460 | |
| 461 if (!hexdata) | |
| 462 return (char *)ERROR_PTR("hexdata not defined", __func__, NULL); | |
| 463 | |
| 464 sa = sarrayCreate(0); | |
| 465 sarrayAddString(sa, "%!Adobe-PS", L_COPY); | |
| 466 if (boxflag == 0) { | |
| 467 snprintf(bigbuf, sizeof(bigbuf), | |
| 468 "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f", | |
| 469 xpt, ypt, xpt + wpt, ypt + hpt); | |
| 470 sarrayAddString(sa, bigbuf, L_COPY); | |
| 471 } else { /* boxflag == 1 */ | |
| 472 sarrayAddString(sa, "gsave", L_COPY); | |
| 473 } | |
| 474 | |
| 475 if (d == 1) | |
| 476 sarrayAddString(sa, | |
| 477 "{1 exch sub} settransfer %invert binary", L_COPY); | |
| 478 | |
| 479 snprintf(bigbuf, sizeof(bigbuf), | |
| 480 "/bpl %d string def %%bpl as a string", psbpl); | |
| 481 sarrayAddString(sa, bigbuf, L_COPY); | |
| 482 snprintf(bigbuf, sizeof(bigbuf), | |
| 483 "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt); | |
| 484 sarrayAddString(sa, bigbuf, L_COPY); | |
| 485 snprintf(bigbuf, sizeof(bigbuf), | |
| 486 "%7.2f %7.2f scale %%set image size in pts", wpt, hpt); | |
| 487 sarrayAddString(sa, bigbuf, L_COPY); | |
| 488 snprintf(bigbuf, sizeof(bigbuf), | |
| 489 "%d %d %d %%image dimensions in pixels", w, h, bps); | |
| 490 sarrayAddString(sa, bigbuf, L_COPY); | |
| 491 snprintf(bigbuf, sizeof(bigbuf), | |
| 492 "[%d %d %d %d %d %d] %%mapping matrix: [w 0 0 -h 0 h]", | |
| 493 w, 0, 0, -h, 0, h); | |
| 494 sarrayAddString(sa, bigbuf, L_COPY); | |
| 495 | |
| 496 if (boxflag == 0) { | |
| 497 if (d == 1 || d == 8) | |
| 498 sarrayAddString(sa, | |
| 499 "{currentfile bpl readhexstring pop} image", L_COPY); | |
| 500 else /* d == 32 */ | |
| 501 sarrayAddString(sa, | |
| 502 "{currentfile bpl readhexstring pop} false 3 colorimage", | |
| 503 L_COPY); | |
| 504 } else { /* boxflag == 1 */ | |
| 505 if (d == 1 || d == 8) | |
| 506 sarrayAddString(sa, | |
| 507 "{currentfile bpl readhexstring pop} bind image", L_COPY); | |
| 508 else /* d == 32 */ | |
| 509 sarrayAddString(sa, | |
| 510 "{currentfile bpl readhexstring pop} bind false 3 colorimage", | |
| 511 L_COPY); | |
| 512 } | |
| 513 | |
| 514 sarrayAddString(sa, hexdata, L_INSERT); | |
| 515 | |
| 516 if (boxflag == 0) | |
| 517 sarrayAddString(sa, "\nshowpage", L_COPY); | |
| 518 else /* boxflag == 1 */ | |
| 519 sarrayAddString(sa, "\ngrestore", L_COPY); | |
| 520 | |
| 521 outstr = sarrayToString(sa, 1); | |
| 522 sarrayDestroy(&sa); | |
| 523 if (!outstr) L_ERROR("outstr not made\n", __func__); | |
| 524 return outstr; | |
| 525 } | |
| 526 | |
| 527 | |
| 528 /*! | |
| 529 * \brief getScaledParametersPS() | |
| 530 * | |
| 531 * \param[in] box [optional] location of image in mils; x,y is LL corner | |
| 532 * \param[in] wpix pix width in pixels | |
| 533 * \param[in] hpix pix height in pixels | |
| 534 * \param[in] res of printer; use 0 for default | |
| 535 * \param[in] scale use 1.0 or 0.0 for no scaling | |
| 536 * \param[out] pxpt location of llx in pts | |
| 537 * \param[out] pypt location of lly in pts | |
| 538 * \param[out] pwpt image width in pts | |
| 539 * \param[out] phpt image height in pts | |
| 540 * \return void no arg checking | |
| 541 * | |
| 542 * <pre> | |
| 543 * Notes: | |
| 544 * (1) The image is always scaled, depending on res and scale. | |
| 545 * (2) If no box, the image is centered on the page. | |
| 546 * (3) If there is a box, the image is placed within it. | |
| 547 * </pre> | |
| 548 */ | |
| 549 static void | |
| 550 getScaledParametersPS(BOX *box, | |
| 551 l_int32 wpix, | |
| 552 l_int32 hpix, | |
| 553 l_int32 res, | |
| 554 l_float32 scale, | |
| 555 l_float32 *pxpt, | |
| 556 l_float32 *pypt, | |
| 557 l_float32 *pwpt, | |
| 558 l_float32 *phpt) | |
| 559 { | |
| 560 l_int32 bx, by, bw, bh; | |
| 561 l_float32 winch, hinch, xinch, yinch, fres; | |
| 562 | |
| 563 if (res == 0) | |
| 564 res = DefaultInputRes; | |
| 565 fres = (l_float32)res; | |
| 566 | |
| 567 /* Allow the PS interpreter to scale the resolution */ | |
| 568 if (scale == 0.0) | |
| 569 scale = 1.0; | |
| 570 if (scale != 1.0) { | |
| 571 fres = (l_float32)res / scale; | |
| 572 res = (l_int32)fres; | |
| 573 } | |
| 574 | |
| 575 /* Limit valid resolution interval */ | |
| 576 if (res < MinRes || res > MaxRes) { | |
| 577 L_WARNING("res %d out of bounds; using default res; no scaling\n", | |
| 578 __func__, res); | |
| 579 res = DefaultInputRes; | |
| 580 fres = (l_float32)res; | |
| 581 } | |
| 582 | |
| 583 if (!box) { /* center on page */ | |
| 584 winch = (l_float32)wpix / fres; | |
| 585 hinch = (l_float32)hpix / fres; | |
| 586 xinch = (8.5f - winch) / 2.f; | |
| 587 yinch = (11.0f - hinch) / 2.f; | |
| 588 } else { | |
| 589 boxGetGeometry(box, &bx, &by, &bw, &bh); | |
| 590 if (bw == 0) | |
| 591 winch = (l_float32)wpix / fres; | |
| 592 else | |
| 593 winch = (l_float32)bw / 1000.f; | |
| 594 if (bh == 0) | |
| 595 hinch = (l_float32)hpix / fres; | |
| 596 else | |
| 597 hinch = (l_float32)bh / 1000.f; | |
| 598 xinch = (l_float32)bx / 1000.f; | |
| 599 yinch = (l_float32)by / 1000.f; | |
| 600 } | |
| 601 | |
| 602 if (xinch < 0) | |
| 603 L_WARNING("left edge < 0.0 inch\n", __func__); | |
| 604 if (xinch + winch > 8.5) | |
| 605 L_WARNING("right edge > 8.5 inch\n", __func__); | |
| 606 if (yinch < 0.0) | |
| 607 L_WARNING("bottom edge < 0.0 inch\n", __func__); | |
| 608 if (yinch + hinch > 11.0) | |
| 609 L_WARNING("top edge > 11.0 inch\n", __func__); | |
| 610 | |
| 611 *pwpt = 72.f * winch; | |
| 612 *phpt = 72.f * hinch; | |
| 613 *pxpt = 72.f * xinch; | |
| 614 *pypt = 72.f * yinch; | |
| 615 return; | |
| 616 } | |
| 617 | |
| 618 | |
| 619 /*! | |
| 620 * \brief convertByteToHexAscii() | |
| 621 * | |
| 622 * \param[in] byteval input byte | |
| 623 * \param[out] pnib1, pnib2 two hex ascii characters | |
| 624 * \return void | |
| 625 */ | |
| 626 static void | |
| 627 convertByteToHexAscii(l_uint8 byteval, | |
| 628 char *pnib1, | |
| 629 char *pnib2) | |
| 630 { | |
| 631 l_uint8 nib; | |
| 632 | |
| 633 nib = byteval >> 4; | |
| 634 if (nib < 10) | |
| 635 *pnib1 = '0' + nib; | |
| 636 else | |
| 637 *pnib1 = 'a' + (nib - 10); | |
| 638 nib = byteval & 0xf; | |
| 639 if (nib < 10) | |
| 640 *pnib2 = '0' + nib; | |
| 641 else | |
| 642 *pnib2 = 'a' + (nib - 10); | |
| 643 return; | |
| 644 } | |
| 645 | |
| 646 | |
| 647 /*-------------------------------------------------------------* | |
| 648 * For jpeg compressed images * | |
| 649 *-------------------------------------------------------------*/ | |
| 650 /*! | |
| 651 * \brief convertJpegToPSEmbed() | |
| 652 * | |
| 653 * \param[in] filein input jpeg file | |
| 654 * \param[in] fileout output ps file | |
| 655 * \return 0 if OK, 1 on error | |
| 656 * | |
| 657 * <pre> | |
| 658 * Notes: | |
| 659 * (1) This function takes a jpeg file as input and generates a DCT | |
| 660 * compressed, ascii85 encoded PS file, with a bounding box. | |
| 661 * (2) The bounding box is required when a program such as TeX | |
| 662 * (through epsf) places and rescales the image. | |
| 663 * (3) The bounding box is sized for fitting the image to an | |
| 664 * 8.5 x 11.0 inch page. | |
| 665 * </pre> | |
| 666 */ | |
| 667 l_ok | |
| 668 convertJpegToPSEmbed(const char *filein, | |
| 669 const char *fileout) | |
| 670 { | |
| 671 char *outstr; | |
| 672 l_int32 w, h, nbytes, ret; | |
| 673 l_float32 xpt, ypt, wpt, hpt; | |
| 674 L_COMP_DATA *cid; | |
| 675 | |
| 676 if (!filein) | |
| 677 return ERROR_INT("filein not defined", __func__, 1); | |
| 678 if (!fileout) | |
| 679 return ERROR_INT("fileout not defined", __func__, 1); | |
| 680 | |
| 681 /* Generate the ascii encoded jpeg data */ | |
| 682 if ((cid = l_generateJpegData(filein, 1)) == NULL) | |
| 683 return ERROR_INT("jpeg data not made", __func__, 1); | |
| 684 w = cid->w; | |
| 685 h = cid->h; | |
| 686 | |
| 687 /* Scale for 20 pt boundary and otherwise full filling | |
| 688 * in one direction on 8.5 x 11 inch device */ | |
| 689 xpt = 20.0; | |
| 690 ypt = 20.0; | |
| 691 if (w * 11.0 > h * 8.5) { | |
| 692 wpt = 572.0; /* 612 - 2 * 20 */ | |
| 693 hpt = wpt * (l_float32)h / (l_float32)w; | |
| 694 } else { | |
| 695 hpt = 752.0; /* 792 - 2 * 20 */ | |
| 696 wpt = hpt * (l_float32)w / (l_float32)h; | |
| 697 } | |
| 698 | |
| 699 /* Generate the PS. | |
| 700 * The bounding box information should be inserted (default). */ | |
| 701 outstr = generateJpegPS(NULL, cid, xpt, ypt, wpt, hpt, 1, 1); | |
| 702 l_CIDataDestroy(&cid); | |
| 703 if (!outstr) | |
| 704 return ERROR_INT("outstr not made", __func__, 1); | |
| 705 nbytes = strlen(outstr); | |
| 706 | |
| 707 ret = l_binaryWrite(fileout, "w", outstr, nbytes); | |
| 708 LEPT_FREE(outstr); | |
| 709 if (ret) L_ERROR("ps string not written to file\n", __func__); | |
| 710 return ret; | |
| 711 } | |
| 712 | |
| 713 | |
| 714 /*! | |
| 715 * \brief convertJpegToPS() | |
| 716 * | |
| 717 * \param[in] filein input jpeg file | |
| 718 * \param[in] fileout output ps file | |
| 719 * \param[in] operation "w" for write; "a" for append | |
| 720 * \param[in] x, y location of LL corner of image, in pixels, relative | |
| 721 * to the PostScript origin (0,0) at the LL corner | |
| 722 * of the page | |
| 723 * \param[in] res resolution of the input image, in ppi; | |
| 724 * use 0 for default | |
| 725 * \param[in] scale scaling by printer; use 0.0 or 1.0 for no scaling | |
| 726 * \param[in] pageno page number; must start with 1; you can use 0 | |
| 727 * if there is only one page | |
| 728 * \param[in] endpage boolean: use TRUE if this is the last image to be | |
| 729 * added to the page; FALSE otherwise | |
| 730 * \return 0 if OK, 1 on error | |
| 731 * | |
| 732 * <pre> | |
| 733 * Notes: | |
| 734 * (1) This is simpler to use than pixWriteStringPS(), and | |
| 735 * it outputs in level 2 PS as compressed DCT (overlaid | |
| 736 * with ascii85 encoding). | |
| 737 * (2) An output file can contain multiple pages, each with | |
| 738 * multiple images. The arguments to convertJpegToPS() | |
| 739 * allow you to control placement of jpeg images on multiple | |
| 740 * pages within a PostScript file. | |
| 741 * (3) For the first image written to a file, use "w", which | |
| 742 * opens for write and clears the file. For all subsequent | |
| 743 * images written to that file, use "a". | |
| 744 * (4) The (x, y) parameters give the LL corner of the image | |
| 745 * relative to the LL corner of the page. They are in | |
| 746 * units of pixels if scale = 1.0. If you use (e.g.) | |
| 747 * scale = 2.0, the image is placed at (2x, 2y) on the page, | |
| 748 * and the image dimensions are also doubled. | |
| 749 * (5) Display vs printed resolution: | |
| 750 * * If your display is 75 ppi and your image was created | |
| 751 * at a resolution of 300 ppi, you can get the image | |
| 752 * to print at the same size as it appears on your display | |
| 753 * by either setting scale = 4.0 or by setting res = 75. | |
| 754 * Both tell the printer to make a 4x enlarged image. | |
| 755 * * If your image is generated at 150 ppi and you use scale = 1, | |
| 756 * it will be rendered such that 150 pixels correspond | |
| 757 * to 72 pts (1 inch on the printer). This function does | |
| 758 * the conversion from pixels (with or without scaling) to | |
| 759 * pts, which are the units that the printer uses. | |
| 760 * * The printer will choose its own resolution to use | |
| 761 * in rendering the image, which will not affect the size | |
| 762 * of the rendered image. That is because the output | |
| 763 * PostScript file describes the geometry in terms of pts, | |
| 764 * which are defined to be 1/72 inch. The printer will | |
| 765 * only see the size of the image in pts, through the | |
| 766 * scale and translate parameters and the affine | |
| 767 * transform (the ImageMatrix) of the image. | |
| 768 * (6) To render multiple images on the same page, set | |
| 769 * endpage = FALSE for each image until you get to the | |
| 770 * last, for which you set endpage = TRUE. This causes the | |
| 771 * "showpage" command to be invoked. Showpage outputs | |
| 772 * the entire page and clears the raster buffer for the | |
| 773 * next page to be added. Without a "showpage", | |
| 774 * subsequent images from the next page will overlay those | |
| 775 * previously put down. | |
| 776 * (7) For multiple pages, increment the page number, starting | |
| 777 * with page 1. This allows PostScript (and PDF) to build | |
| 778 * a page directory, which viewers use for navigation. | |
| 779 * </pre> | |
| 780 */ | |
| 781 l_ok | |
| 782 convertJpegToPS(const char *filein, | |
| 783 const char *fileout, | |
| 784 const char *operation, | |
| 785 l_int32 x, | |
| 786 l_int32 y, | |
| 787 l_int32 res, | |
| 788 l_float32 scale, | |
| 789 l_int32 pageno, | |
| 790 l_int32 endpage) | |
| 791 { | |
| 792 char *outstr; | |
| 793 l_int32 nbytes; | |
| 794 | |
| 795 if (!filein) | |
| 796 return ERROR_INT("filein not defined", __func__, 1); | |
| 797 if (!fileout) | |
| 798 return ERROR_INT("fileout not defined", __func__, 1); | |
| 799 if (strcmp(operation, "w") && strcmp(operation, "a")) | |
| 800 return ERROR_INT("operation must be \"w\" or \"a\"", __func__, 1); | |
| 801 | |
| 802 if (convertJpegToPSString(filein, &outstr, &nbytes, x, y, res, scale, | |
| 803 pageno, endpage)) | |
| 804 return ERROR_INT("ps string not made", __func__, 1); | |
| 805 | |
| 806 if (l_binaryWrite(fileout, operation, outstr, nbytes)) { | |
| 807 LEPT_FREE(outstr); | |
| 808 return ERROR_INT("ps string not written to file", __func__, 1); | |
| 809 } | |
| 810 | |
| 811 LEPT_FREE(outstr); | |
| 812 return 0; | |
| 813 } | |
| 814 | |
| 815 | |
| 816 /*! | |
| 817 * \brief convertJpegToPSString() | |
| 818 * | |
| 819 * Generates PS string in jpeg format from jpeg file | |
| 820 * | |
| 821 * \param[in] filein input jpeg file | |
| 822 * \param[out] poutstr PS string | |
| 823 * \param[out] pnbytes number of bytes in PS string | |
| 824 * \param[in] x, y location of LL corner of image, in pixels, relative | |
| 825 * to the PostScript origin (0,0) at the LL corner | |
| 826 * of the page | |
| 827 * \param[in] res resolution of the input image, in ppi; | |
| 828 * use 0 for default | |
| 829 * \param[in] scale scaling by printer; use 0.0 or 1.0 for no scaling | |
| 830 * \param[in] pageno page number; must start with 1; you can use 0 | |
| 831 * if there is only one page | |
| 832 * \param[in] endpage boolean: use TRUE if this is the last image to be | |
| 833 * added to the page; FALSE otherwise | |
| 834 * \return 0 if OK, 1 on error | |
| 835 * | |
| 836 * <pre> | |
| 837 * Notes: | |
| 838 * (1) For usage, see convertJpegToPS() | |
| 839 * </pre> | |
| 840 */ | |
| 841 static l_ok | |
| 842 convertJpegToPSString(const char *filein, | |
| 843 char **poutstr, | |
| 844 l_int32 *pnbytes, | |
| 845 l_int32 x, | |
| 846 l_int32 y, | |
| 847 l_int32 res, | |
| 848 l_float32 scale, | |
| 849 l_int32 pageno, | |
| 850 l_int32 endpage) | |
| 851 { | |
| 852 char *outstr; | |
| 853 l_float32 xpt, ypt, wpt, hpt; | |
| 854 L_COMP_DATA *cid; | |
| 855 | |
| 856 if (!poutstr) | |
| 857 return ERROR_INT("&outstr not defined", __func__, 1); | |
| 858 if (!pnbytes) | |
| 859 return ERROR_INT("&nbytes not defined", __func__, 1); | |
| 860 *poutstr = NULL; | |
| 861 *pnbytes = 0; | |
| 862 if (!filein) | |
| 863 return ERROR_INT("filein not defined", __func__, 1); | |
| 864 | |
| 865 /* Generate the ascii encoded jpeg data */ | |
| 866 if ((cid = l_generateJpegData(filein, 1)) == NULL) | |
| 867 return ERROR_INT("jpeg data not made", __func__, 1); | |
| 868 | |
| 869 /* Get scaled location in pts. Guess the input scan resolution | |
| 870 * based on the input parameter %res, the resolution data in | |
| 871 * the pix, and the size of the image. */ | |
| 872 if (scale == 0.0) | |
| 873 scale = 1.0; | |
| 874 if (res <= 0) { | |
| 875 if (cid->res > 0) | |
| 876 res = cid->res; | |
| 877 else | |
| 878 res = DefaultInputRes; | |
| 879 } | |
| 880 | |
| 881 /* Get scaled location in pts */ | |
| 882 if (scale == 0.0) | |
| 883 scale = 1.0; | |
| 884 xpt = scale * x * 72.f / res; | |
| 885 ypt = scale * y * 72.f / res; | |
| 886 wpt = scale * cid->w * 72.f / res; | |
| 887 hpt = scale * cid->h * 72.f / res; | |
| 888 | |
| 889 if (pageno == 0) | |
| 890 pageno = 1; | |
| 891 | |
| 892 #if DEBUG_JPEG | |
| 893 lept_stderr("w = %d, h = %d, bps = %d, spp = %d\n", | |
| 894 cid->w, cid->h, cid->bps, cid->spp); | |
| 895 lept_stderr("comp bytes = %ld, nbytes85 = %ld, ratio = %5.3f\n", | |
| 896 (unsigned long)cid->nbytescomp, (unsigned long)cid->nbytes85, | |
| 897 (l_float32)cid->nbytes85 / (l_float32)cid->nbytescomp); | |
| 898 lept_stderr("xpt = %7.2f, ypt = %7.2f, wpt = %7.2f, hpt = %7.2f\n", | |
| 899 xpt, ypt, wpt, hpt); | |
| 900 #endif /* DEBUG_JPEG */ | |
| 901 | |
| 902 /* Generate the PS */ | |
| 903 outstr = generateJpegPS(NULL, cid, xpt, ypt, wpt, hpt, pageno, endpage); | |
| 904 l_CIDataDestroy(&cid); | |
| 905 if (!outstr) | |
| 906 return ERROR_INT("outstr not made", __func__, 1); | |
| 907 *poutstr = outstr; | |
| 908 *pnbytes = strlen(outstr); | |
| 909 return 0; | |
| 910 } | |
| 911 | |
| 912 | |
| 913 /*! | |
| 914 * \brief generateJpegPS() | |
| 915 * | |
| 916 * \param[in] filein [optional] input jpeg filename; can be null | |
| 917 * \param[in] cid jpeg compressed image data | |
| 918 * \param[in] xpt, ypt location of LL corner of image, in pts, relative | |
| 919 * to the PostScript origin (0,0) at the LL corner | |
| 920 * of the page | |
| 921 * \param[in] wpt, hpt rendered image size in pts | |
| 922 * \param[in] pageno page number; must start with 1; you can use 0 | |
| 923 * if there is only one page. | |
| 924 * \param[in] endpage boolean: use TRUE if this is the last image to be | |
| 925 * added to the page; FALSE otherwise | |
| 926 * \return PS string, or NULL on error | |
| 927 * | |
| 928 * <pre> | |
| 929 * Notes: | |
| 930 * (1) Low-level function. | |
| 931 * </pre> | |
| 932 */ | |
| 933 static char * | |
| 934 generateJpegPS(const char *filein, | |
| 935 L_COMP_DATA *cid, | |
| 936 l_float32 xpt, | |
| 937 l_float32 ypt, | |
| 938 l_float32 wpt, | |
| 939 l_float32 hpt, | |
| 940 l_int32 pageno, | |
| 941 l_int32 endpage) | |
| 942 { | |
| 943 l_int32 w, h, bps, spp; | |
| 944 char *outstr; | |
| 945 char bigbuf[Bufsize]; | |
| 946 SARRAY *sa; | |
| 947 | |
| 948 if (!cid) | |
| 949 return (char *)ERROR_PTR("jpeg data not defined", __func__, NULL); | |
| 950 w = cid->w; | |
| 951 h = cid->h; | |
| 952 bps = cid->bps; | |
| 953 spp = cid->spp; | |
| 954 | |
| 955 sa = sarrayCreate(50); | |
| 956 sarrayAddString(sa, "%!PS-Adobe-3.0", L_COPY); | |
| 957 sarrayAddString(sa, "%%Creator: leptonica", L_COPY); | |
| 958 if (filein) | |
| 959 snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: %s", filein); | |
| 960 else | |
| 961 snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: Jpeg compressed PS"); | |
| 962 sarrayAddString(sa, bigbuf, L_COPY); | |
| 963 sarrayAddString(sa, "%%DocumentData: Clean7Bit", L_COPY); | |
| 964 | |
| 965 if (var_PS_WRITE_BOUNDING_BOX == 1) { | |
| 966 snprintf(bigbuf, sizeof(bigbuf), | |
| 967 "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f", | |
| 968 xpt, ypt, xpt + wpt, ypt + hpt); | |
| 969 sarrayAddString(sa, bigbuf, L_COPY); | |
| 970 } | |
| 971 | |
| 972 sarrayAddString(sa, "%%LanguageLevel: 2", L_COPY); | |
| 973 sarrayAddString(sa, "%%EndComments", L_COPY); | |
| 974 snprintf(bigbuf, sizeof(bigbuf), "%%%%Page: %d %d", pageno, pageno); | |
| 975 sarrayAddString(sa, bigbuf, L_COPY); | |
| 976 | |
| 977 sarrayAddString(sa, "save", L_COPY); | |
| 978 sarrayAddString(sa, | |
| 979 "/RawData currentfile /ASCII85Decode filter def", L_COPY); | |
| 980 sarrayAddString(sa, "/Data RawData << >> /DCTDecode filter def", L_COPY); | |
| 981 | |
| 982 snprintf(bigbuf, sizeof(bigbuf), | |
| 983 "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt); | |
| 984 sarrayAddString(sa, bigbuf, L_COPY); | |
| 985 | |
| 986 snprintf(bigbuf, sizeof(bigbuf), | |
| 987 "%7.2f %7.2f scale %%set image size in pts", wpt, hpt); | |
| 988 sarrayAddString(sa, bigbuf, L_COPY); | |
| 989 | |
| 990 if (spp == 1) | |
| 991 sarrayAddString(sa, "/DeviceGray setcolorspace", L_COPY); | |
| 992 else if (spp == 3) | |
| 993 sarrayAddString(sa, "/DeviceRGB setcolorspace", L_COPY); | |
| 994 else /*spp == 4 */ | |
| 995 sarrayAddString(sa, "/DeviceCMYK setcolorspace", L_COPY); | |
| 996 | |
| 997 sarrayAddString(sa, "{ << /ImageType 1", L_COPY); | |
| 998 snprintf(bigbuf, sizeof(bigbuf), " /Width %d", w); | |
| 999 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1000 snprintf(bigbuf, sizeof(bigbuf), " /Height %d", h); | |
| 1001 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1002 snprintf(bigbuf, sizeof(bigbuf), | |
| 1003 " /ImageMatrix [ %d 0 0 %d 0 %d ]", w, -h, h); | |
| 1004 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1005 sarrayAddString(sa, " /DataSource Data", L_COPY); | |
| 1006 snprintf(bigbuf, sizeof(bigbuf), " /BitsPerComponent %d", bps); | |
| 1007 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1008 | |
| 1009 if (spp == 1) | |
| 1010 sarrayAddString(sa, " /Decode [0 1]", L_COPY); | |
| 1011 else if (spp == 3) | |
| 1012 sarrayAddString(sa, " /Decode [0 1 0 1 0 1]", L_COPY); | |
| 1013 else /* spp == 4 */ | |
| 1014 sarrayAddString(sa, " /Decode [0 1 0 1 0 1 0 1]", L_COPY); | |
| 1015 | |
| 1016 sarrayAddString(sa, " >> image", L_COPY); | |
| 1017 sarrayAddString(sa, " Data closefile", L_COPY); | |
| 1018 sarrayAddString(sa, " RawData flushfile", L_COPY); | |
| 1019 if (endpage == TRUE) | |
| 1020 sarrayAddString(sa, " showpage", L_COPY); | |
| 1021 sarrayAddString(sa, " restore", L_COPY); | |
| 1022 sarrayAddString(sa, "} exec", L_COPY); | |
| 1023 | |
| 1024 /* Insert the ascii85 jpeg data; this is now owned by sa */ | |
| 1025 sarrayAddString(sa, cid->data85, L_INSERT); | |
| 1026 cid->data85 = NULL; /* it has been transferred and destroyed */ | |
| 1027 | |
| 1028 /* Generate and return the output string */ | |
| 1029 outstr = sarrayToString(sa, 1); | |
| 1030 sarrayDestroy(&sa); | |
| 1031 return outstr; | |
| 1032 } | |
| 1033 | |
| 1034 | |
| 1035 /*-------------------------------------------------------------* | |
| 1036 * For ccitt g4 compressed images * | |
| 1037 *-------------------------------------------------------------*/ | |
| 1038 /*! | |
| 1039 * \brief convertG4ToPSEmbed() | |
| 1040 * | |
| 1041 * \param[in] filein input tiff file | |
| 1042 * \param[in] fileout output ps file | |
| 1043 * \return 0 if OK, 1 on error | |
| 1044 * | |
| 1045 * <pre> | |
| 1046 * Notes: | |
| 1047 * (1) This function takes a g4 compressed tif file as input and | |
| 1048 * generates a g4 compressed, ascii85 encoded PS file, with | |
| 1049 * a bounding box. | |
| 1050 * (2) The bounding box is required when a program such as TeX | |
| 1051 * (through epsf) places and rescales the image. | |
| 1052 * (3) The bounding box is sized for fitting the image to an | |
| 1053 * 8.5 x 11.0 inch page. | |
| 1054 * (4) We paint this through a mask, over whatever is below. | |
| 1055 * </pre> | |
| 1056 */ | |
| 1057 l_ok | |
| 1058 convertG4ToPSEmbed(const char *filein, | |
| 1059 const char *fileout) | |
| 1060 { | |
| 1061 char *outstr; | |
| 1062 l_int32 w, h, nbytes, ret; | |
| 1063 l_float32 xpt, ypt, wpt, hpt; | |
| 1064 L_COMP_DATA *cid; | |
| 1065 | |
| 1066 if (!filein) | |
| 1067 return ERROR_INT("filein not defined", __func__, 1); | |
| 1068 if (!fileout) | |
| 1069 return ERROR_INT("fileout not defined", __func__, 1); | |
| 1070 | |
| 1071 if ((cid = l_generateG4Data(filein, 1)) == NULL) | |
| 1072 return ERROR_INT("g4 data not made", __func__, 1); | |
| 1073 w = cid->w; | |
| 1074 h = cid->h; | |
| 1075 | |
| 1076 /* Scale for 20 pt boundary and otherwise full filling | |
| 1077 * in one direction on 8.5 x 11 inch device */ | |
| 1078 xpt = 20.0; | |
| 1079 ypt = 20.0; | |
| 1080 if (w * 11.0 > h * 8.5) { | |
| 1081 wpt = 572.0; /* 612 - 2 * 20 */ | |
| 1082 hpt = wpt * (l_float32)h / (l_float32)w; | |
| 1083 } else { | |
| 1084 hpt = 752.0; /* 792 - 2 * 20 */ | |
| 1085 wpt = hpt * (l_float32)w / (l_float32)h; | |
| 1086 } | |
| 1087 | |
| 1088 /* Generate the PS, painting through the image mask. | |
| 1089 * The bounding box information should be inserted (default). */ | |
| 1090 outstr = generateG4PS(NULL, cid, xpt, ypt, wpt, hpt, 1, 1, 1); | |
| 1091 l_CIDataDestroy(&cid); | |
| 1092 if (!outstr) | |
| 1093 return ERROR_INT("outstr not made", __func__, 1); | |
| 1094 nbytes = strlen(outstr); | |
| 1095 | |
| 1096 ret = l_binaryWrite(fileout, "w", outstr, nbytes); | |
| 1097 LEPT_FREE(outstr); | |
| 1098 if (ret) L_ERROR("ps string not written to file\n", __func__); | |
| 1099 return ret; | |
| 1100 } | |
| 1101 | |
| 1102 | |
| 1103 /*! | |
| 1104 * \brief convertG4ToPS() | |
| 1105 * | |
| 1106 * \param[in] filein input tiff g4 file | |
| 1107 * \param[in] fileout output ps file | |
| 1108 * \param[in] operation "w" for write; "a" for append | |
| 1109 * \param[in] x, y location of LL corner of image, in pixels, relative | |
| 1110 * to the PostScript origin (0,0) at the LL corner | |
| 1111 * of the page | |
| 1112 * \param[in] res resolution of the input image, in ppi; typ. values | |
| 1113 * are 300 and 600; use 0 for automatic determination | |
| 1114 * based on image size | |
| 1115 * \param[in] scale scaling by printer; use 0.0 or 1.0 for no scaling | |
| 1116 * \param[in] pageno page number; must start with 1; you can use 0 | |
| 1117 * if there is only one page. | |
| 1118 * \param[in] maskflag boolean: use TRUE if just painting through fg; | |
| 1119 * FALSE if painting both fg and bg. | |
| 1120 * \param[in] endpage boolean: use TRUE if this is the last image to be | |
| 1121 * added to the page; FALSE otherwise | |
| 1122 * \return 0 if OK, 1 on error | |
| 1123 * | |
| 1124 * <pre> | |
| 1125 * Notes: | |
| 1126 * (1) See the usage comments in convertJpegToPS(), some of | |
| 1127 * which are repeated here. | |
| 1128 * (2) This is a wrapper for tiff g4. The PostScript that | |
| 1129 * is generated is expanded by about 5/4 (due to the | |
| 1130 * ascii85 encoding. If you convert to pdf (ps2pdf), the | |
| 1131 * ascii85 decoder is automatically invoked, so that the | |
| 1132 * pdf wrapped g4 file is essentially the same size as | |
| 1133 * the original g4 file. It's useful to have the PS | |
| 1134 * file ascii85 encoded, because many printers will not | |
| 1135 * print binary PS files. | |
| 1136 * (3) For the first image written to a file, use "w", which | |
| 1137 * opens for write and clears the file. For all subsequent | |
| 1138 * images written to that file, use "a". | |
| 1139 * (4) To render multiple images on the same page, set | |
| 1140 * endpage = FALSE for each image until you get to the | |
| 1141 * last, for which you set endpage = TRUE. This causes the | |
| 1142 * "showpage" command to be invoked. Showpage outputs | |
| 1143 * the entire page and clears the raster buffer for the | |
| 1144 * next page to be added. Without a "showpage", | |
| 1145 * subsequent images from the next page will overlay those | |
| 1146 * previously put down. | |
| 1147 * (5) For multiple images to the same page, where you are writing | |
| 1148 * both jpeg and tiff-g4, you have two options: | |
| 1149 * (a) write the g4 first, as either image (maskflag == FALSE) | |
| 1150 * or imagemask (maskflag == TRUE), and then write the | |
| 1151 * jpeg over it. | |
| 1152 * (b) write the jpeg first and as the last item, write | |
| 1153 * the g4 as an imagemask (maskflag == TRUE), to paint | |
| 1154 * through the foreground only. | |
| 1155 * We have this flexibility with the tiff-g4 because it is 1 bpp. | |
| 1156 * (6) For multiple pages, increment the page number, starting | |
| 1157 * with page 1. This allows PostScript (and PDF) to build | |
| 1158 * a page directory, which viewers use for navigation. | |
| 1159 * </pre> | |
| 1160 */ | |
| 1161 l_ok | |
| 1162 convertG4ToPS(const char *filein, | |
| 1163 const char *fileout, | |
| 1164 const char *operation, | |
| 1165 l_int32 x, | |
| 1166 l_int32 y, | |
| 1167 l_int32 res, | |
| 1168 l_float32 scale, | |
| 1169 l_int32 pageno, | |
| 1170 l_int32 maskflag, | |
| 1171 l_int32 endpage) | |
| 1172 { | |
| 1173 char *outstr; | |
| 1174 l_int32 nbytes, ret; | |
| 1175 | |
| 1176 if (!filein) | |
| 1177 return ERROR_INT("filein not defined", __func__, 1); | |
| 1178 if (!fileout) | |
| 1179 return ERROR_INT("fileout not defined", __func__, 1); | |
| 1180 if (strcmp(operation, "w") && strcmp(operation, "a")) | |
| 1181 return ERROR_INT("operation must be \"w\" or \"a\"", __func__, 1); | |
| 1182 | |
| 1183 if (convertG4ToPSString(filein, &outstr, &nbytes, x, y, res, scale, | |
| 1184 pageno, maskflag, endpage)) | |
| 1185 return ERROR_INT("ps string not made", __func__, 1); | |
| 1186 | |
| 1187 ret = l_binaryWrite(fileout, operation, outstr, nbytes); | |
| 1188 LEPT_FREE(outstr); | |
| 1189 if (ret) | |
| 1190 return ERROR_INT("ps string not written to file", __func__, 1); | |
| 1191 return 0; | |
| 1192 } | |
| 1193 | |
| 1194 | |
| 1195 /*! | |
| 1196 * \brief convertG4ToPSString() | |
| 1197 * | |
| 1198 * \param[in] filein input tiff g4 file | |
| 1199 * \param[out] poutstr PS string | |
| 1200 * \param[out] pnbytes number of bytes in PS string | |
| 1201 * \param[in] x, y location of LL corner of image, in pixels, relative | |
| 1202 * to the PostScript origin (0,0) at the LL corner | |
| 1203 * of the page | |
| 1204 * \param[in] res resolution of the input image, in ppi; typ. values | |
| 1205 * are 300 and 600; use 0 for automatic determination | |
| 1206 * based on image size | |
| 1207 * \param[in] scale scaling by printer; use 0.0 or 1.0 for no scaling | |
| 1208 * \param[in] pageno page number; must start with 1; you can use 0 | |
| 1209 * if there is only one page. | |
| 1210 * \param[in] maskflag boolean: use TRUE if just painting through fg; | |
| 1211 * FALSE if painting both fg and bg. | |
| 1212 * \param[in] endpage boolean: use TRUE if this is the last image to be | |
| 1213 * added to the page; FALSE otherwise | |
| 1214 * \return 0 if OK, 1 on error | |
| 1215 * | |
| 1216 * <pre> | |
| 1217 * Notes: | |
| 1218 * (1) Generates PS string in G4 compressed tiff format from G4 tiff file. | |
| 1219 * (2) For usage, see convertG4ToPS(). | |
| 1220 * </pre> | |
| 1221 */ | |
| 1222 static l_ok | |
| 1223 convertG4ToPSString(const char *filein, | |
| 1224 char **poutstr, | |
| 1225 l_int32 *pnbytes, | |
| 1226 l_int32 x, | |
| 1227 l_int32 y, | |
| 1228 l_int32 res, | |
| 1229 l_float32 scale, | |
| 1230 l_int32 pageno, | |
| 1231 l_int32 maskflag, | |
| 1232 l_int32 endpage) | |
| 1233 { | |
| 1234 char *outstr; | |
| 1235 l_float32 xpt, ypt, wpt, hpt; | |
| 1236 L_COMP_DATA *cid; | |
| 1237 | |
| 1238 if (!poutstr) | |
| 1239 return ERROR_INT("&outstr not defined", __func__, 1); | |
| 1240 if (!pnbytes) | |
| 1241 return ERROR_INT("&nbytes not defined", __func__, 1); | |
| 1242 *poutstr = NULL; | |
| 1243 *pnbytes = 0; | |
| 1244 if (!filein) | |
| 1245 return ERROR_INT("filein not defined", __func__, 1); | |
| 1246 | |
| 1247 if ((cid = l_generateG4Data(filein, 1)) == NULL) | |
| 1248 return ERROR_INT("g4 data not made", __func__, 1); | |
| 1249 | |
| 1250 /* Get scaled location in pts. Guess the input scan resolution | |
| 1251 * based on the input parameter %res, the resolution data in | |
| 1252 * the pix, and the size of the image. */ | |
| 1253 if (scale == 0.0) | |
| 1254 scale = 1.0; | |
| 1255 if (res <= 0) { | |
| 1256 if (cid->res > 0) { | |
| 1257 res = cid->res; | |
| 1258 } else { | |
| 1259 if (cid->h <= 3509) /* A4 height at 300 ppi */ | |
| 1260 res = 300; | |
| 1261 else | |
| 1262 res = 600; | |
| 1263 } | |
| 1264 } | |
| 1265 xpt = scale * x * 72.f / res; | |
| 1266 ypt = scale * y * 72.f / res; | |
| 1267 wpt = scale * cid->w * 72.f / res; | |
| 1268 hpt = scale * cid->h * 72.f / res; | |
| 1269 | |
| 1270 if (pageno == 0) | |
| 1271 pageno = 1; | |
| 1272 | |
| 1273 #if DEBUG_G4 | |
| 1274 lept_stderr("w = %d, h = %d, minisblack = %d\n", | |
| 1275 cid->w, cid->h, cid->minisblack); | |
| 1276 lept_stderr("comp bytes = %ld, nbytes85 = %ld\n", | |
| 1277 (unsigned long)cid->nbytescomp, (unsigned long)cid->nbytes85); | |
| 1278 lept_stderr("xpt = %7.2f, ypt = %7.2f, wpt = %7.2f, hpt = %7.2f\n", | |
| 1279 xpt, ypt, wpt, hpt); | |
| 1280 #endif /* DEBUG_G4 */ | |
| 1281 | |
| 1282 /* Generate the PS */ | |
| 1283 outstr = generateG4PS(NULL, cid, xpt, ypt, wpt, hpt, | |
| 1284 maskflag, pageno, endpage); | |
| 1285 l_CIDataDestroy(&cid); | |
| 1286 if (!outstr) | |
| 1287 return ERROR_INT("outstr not made", __func__, 1); | |
| 1288 *poutstr = outstr; | |
| 1289 *pnbytes = strlen(outstr); | |
| 1290 return 0; | |
| 1291 } | |
| 1292 | |
| 1293 | |
| 1294 /*! | |
| 1295 * \brief generateG4PS() | |
| 1296 * | |
| 1297 * \param[in] filein [optional] input tiff g4 file; can be null | |
| 1298 * \param[in] cid g4 compressed image data | |
| 1299 * \param[in] xpt, ypt location of LL corner of image, in pts, relative | |
| 1300 * to the PostScript origin (0,0) at the LL corner | |
| 1301 * of the page | |
| 1302 * \param[in] wpt, hpt rendered image size in pts | |
| 1303 * \param[in] maskflag boolean: use TRUE if just painting through fg; | |
| 1304 * FALSE if painting both fg and bg. | |
| 1305 * \param[in] pageno page number; must start with 1; you can use 0 | |
| 1306 * if there is only one page. | |
| 1307 * \param[in] endpage boolean: use TRUE if this is the last image to be | |
| 1308 * added to the page; FALSE otherwise | |
| 1309 * \return PS string, or NULL on error | |
| 1310 * | |
| 1311 * <pre> | |
| 1312 * Notes: | |
| 1313 * (1) Low-level function. | |
| 1314 * </pre> | |
| 1315 */ | |
| 1316 static char * | |
| 1317 generateG4PS(const char *filein, | |
| 1318 L_COMP_DATA *cid, | |
| 1319 l_float32 xpt, | |
| 1320 l_float32 ypt, | |
| 1321 l_float32 wpt, | |
| 1322 l_float32 hpt, | |
| 1323 l_int32 maskflag, | |
| 1324 l_int32 pageno, | |
| 1325 l_int32 endpage) | |
| 1326 { | |
| 1327 l_int32 w, h; | |
| 1328 char *outstr; | |
| 1329 char bigbuf[Bufsize]; | |
| 1330 SARRAY *sa; | |
| 1331 | |
| 1332 if (!cid) | |
| 1333 return (char *)ERROR_PTR("g4 data not defined", __func__, NULL); | |
| 1334 w = cid->w; | |
| 1335 h = cid->h; | |
| 1336 | |
| 1337 sa = sarrayCreate(50); | |
| 1338 sarrayAddString(sa, "%!PS-Adobe-3.0", L_COPY); | |
| 1339 sarrayAddString(sa, "%%Creator: leptonica", L_COPY); | |
| 1340 if (filein) | |
| 1341 snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: %s", filein); | |
| 1342 else | |
| 1343 snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: G4 compressed PS"); | |
| 1344 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1345 sarrayAddString(sa, "%%DocumentData: Clean7Bit", L_COPY); | |
| 1346 | |
| 1347 if (var_PS_WRITE_BOUNDING_BOX == 1) { | |
| 1348 snprintf(bigbuf, sizeof(bigbuf), | |
| 1349 "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f", | |
| 1350 xpt, ypt, xpt + wpt, ypt + hpt); | |
| 1351 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1352 } | |
| 1353 | |
| 1354 sarrayAddString(sa, "%%LanguageLevel: 2", L_COPY); | |
| 1355 sarrayAddString(sa, "%%EndComments", L_COPY); | |
| 1356 snprintf(bigbuf, sizeof(bigbuf), "%%%%Page: %d %d", pageno, pageno); | |
| 1357 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1358 | |
| 1359 sarrayAddString(sa, "save", L_COPY); | |
| 1360 sarrayAddString(sa, "100 dict begin", L_COPY); | |
| 1361 | |
| 1362 snprintf(bigbuf, sizeof(bigbuf), | |
| 1363 "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt); | |
| 1364 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1365 | |
| 1366 snprintf(bigbuf, sizeof(bigbuf), | |
| 1367 "%7.2f %7.2f scale %%set image size in pts", wpt, hpt); | |
| 1368 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1369 | |
| 1370 sarrayAddString(sa, "/DeviceGray setcolorspace", L_COPY); | |
| 1371 | |
| 1372 sarrayAddString(sa, "{", L_COPY); | |
| 1373 sarrayAddString(sa, | |
| 1374 " /RawData currentfile /ASCII85Decode filter def", L_COPY); | |
| 1375 sarrayAddString(sa, " << ", L_COPY); | |
| 1376 sarrayAddString(sa, " /ImageType 1", L_COPY); | |
| 1377 snprintf(bigbuf, sizeof(bigbuf), " /Width %d", w); | |
| 1378 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1379 snprintf(bigbuf, sizeof(bigbuf), " /Height %d", h); | |
| 1380 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1381 snprintf(bigbuf, sizeof(bigbuf), | |
| 1382 " /ImageMatrix [ %d 0 0 %d 0 %d ]", w, -h, h); | |
| 1383 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1384 sarrayAddString(sa, " /BitsPerComponent 1", L_COPY); | |
| 1385 sarrayAddString(sa, " /Interpolate true", L_COPY); | |
| 1386 if (cid->minisblack) | |
| 1387 sarrayAddString(sa, " /Decode [1 0]", L_COPY); | |
| 1388 else /* miniswhite; typical for 1 bpp */ | |
| 1389 sarrayAddString(sa, " /Decode [0 1]", L_COPY); | |
| 1390 sarrayAddString(sa, " /DataSource RawData", L_COPY); | |
| 1391 sarrayAddString(sa, " <<", L_COPY); | |
| 1392 sarrayAddString(sa, " /K -1", L_COPY); | |
| 1393 snprintf(bigbuf, sizeof(bigbuf), " /Columns %d", w); | |
| 1394 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1395 snprintf(bigbuf, sizeof(bigbuf), " /Rows %d", h); | |
| 1396 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1397 sarrayAddString(sa, " >> /CCITTFaxDecode filter", L_COPY); | |
| 1398 if (maskflag == TRUE) /* just paint through the fg */ | |
| 1399 sarrayAddString(sa, " >> imagemask", L_COPY); | |
| 1400 else /* Paint full image */ | |
| 1401 sarrayAddString(sa, " >> image", L_COPY); | |
| 1402 sarrayAddString(sa, " RawData flushfile", L_COPY); | |
| 1403 if (endpage == TRUE) | |
| 1404 sarrayAddString(sa, " showpage", L_COPY); | |
| 1405 sarrayAddString(sa, "}", L_COPY); | |
| 1406 | |
| 1407 sarrayAddString(sa, "%%BeginData:", L_COPY); | |
| 1408 sarrayAddString(sa, "exec", L_COPY); | |
| 1409 | |
| 1410 /* Insert the ascii85 ccittg4 data; this is now owned by sa */ | |
| 1411 sarrayAddString(sa, cid->data85, L_INSERT); | |
| 1412 | |
| 1413 /* Concat the trailing data */ | |
| 1414 sarrayAddString(sa, "%%EndData", L_COPY); | |
| 1415 sarrayAddString(sa, "end", L_COPY); | |
| 1416 sarrayAddString(sa, "restore", L_COPY); | |
| 1417 | |
| 1418 outstr = sarrayToString(sa, 1); | |
| 1419 sarrayDestroy(&sa); | |
| 1420 cid->data85 = NULL; /* it has been transferred and destroyed */ | |
| 1421 return outstr; | |
| 1422 } | |
| 1423 | |
| 1424 | |
| 1425 /*-------------------------------------------------------------* | |
| 1426 * For tiff multipage files * | |
| 1427 *-------------------------------------------------------------*/ | |
| 1428 /*! | |
| 1429 * \brief convertTiffMultipageToPS() | |
| 1430 * | |
| 1431 * \param[in] filein input tiff multipage file | |
| 1432 * \param[in] fileout output ps file | |
| 1433 * \param[in] fillfract factor for filling 8.5 x 11 inch page; | |
| 1434 * use 0.0 for DefaultFillFraction | |
| 1435 * \return 0 if OK, 1 on error | |
| 1436 * | |
| 1437 * <pre> | |
| 1438 * Notes: | |
| 1439 * (1) This converts a multipage tiff file of binary page images | |
| 1440 * into a ccitt g4 compressed PS file. | |
| 1441 * (2) If the images are generated from a standard resolution fax, | |
| 1442 * the vertical resolution is doubled to give a normal-looking | |
| 1443 * aspect ratio. | |
| 1444 * </pre> | |
| 1445 */ | |
| 1446 l_ok | |
| 1447 convertTiffMultipageToPS(const char *filein, | |
| 1448 const char *fileout, | |
| 1449 l_float32 fillfract) | |
| 1450 { | |
| 1451 char *tempfile; | |
| 1452 l_int32 i, npages, w, h, istiff; | |
| 1453 l_float32 scale; | |
| 1454 PIX *pix, *pixs; | |
| 1455 FILE *fp; | |
| 1456 | |
| 1457 if (!filein) | |
| 1458 return ERROR_INT("filein not defined", __func__, 1); | |
| 1459 if (!fileout) | |
| 1460 return ERROR_INT("fileout not defined", __func__, 1); | |
| 1461 | |
| 1462 if ((fp = fopenReadStream(filein)) == NULL) | |
| 1463 return ERROR_INT_1("file not found", filein, __func__, 1); | |
| 1464 istiff = fileFormatIsTiff(fp); | |
| 1465 if (!istiff) { | |
| 1466 fclose(fp); | |
| 1467 return ERROR_INT_1("file not tiff format", filein, __func__, 1); | |
| 1468 } | |
| 1469 tiffGetCount(fp, &npages); | |
| 1470 fclose(fp); | |
| 1471 | |
| 1472 if (fillfract == 0.0) | |
| 1473 fillfract = DefaultFillFraction; | |
| 1474 | |
| 1475 for (i = 0; i < npages; i++) { | |
| 1476 if ((pix = pixReadTiff(filein, i)) == NULL) | |
| 1477 return ERROR_INT_1("pix not made", filein, __func__, 1); | |
| 1478 | |
| 1479 pixGetDimensions(pix, &w, &h, NULL); | |
| 1480 if (w == 1728 && h < w) /* it's a std res fax */ | |
| 1481 pixs = pixScale(pix, 1.0, 2.0); | |
| 1482 else | |
| 1483 pixs = pixClone(pix); | |
| 1484 | |
| 1485 tempfile = l_makeTempFilename(); | |
| 1486 pixWrite(tempfile, pixs, IFF_TIFF_G4); | |
| 1487 scale = L_MIN(fillfract * 2550 / w, fillfract * 3300 / h); | |
| 1488 if (i == 0) | |
| 1489 convertG4ToPS(tempfile, fileout, "w", 0, 0, 300, scale, | |
| 1490 i + 1, FALSE, TRUE); | |
| 1491 else | |
| 1492 convertG4ToPS(tempfile, fileout, "a", 0, 0, 300, scale, | |
| 1493 i + 1, FALSE, TRUE); | |
| 1494 lept_rmfile(tempfile); | |
| 1495 LEPT_FREE(tempfile); | |
| 1496 pixDestroy(&pix); | |
| 1497 pixDestroy(&pixs); | |
| 1498 } | |
| 1499 | |
| 1500 return 0; | |
| 1501 } | |
| 1502 | |
| 1503 | |
| 1504 /*---------------------------------------------------------------------* | |
| 1505 * For flate (gzip) compressed images (e.g., png) * | |
| 1506 *---------------------------------------------------------------------*/ | |
| 1507 /*! | |
| 1508 * \brief convertFlateToPSEmbed() | |
| 1509 * | |
| 1510 * \param[in] filein input file -- any format | |
| 1511 * \param[in] fileout output ps file | |
| 1512 * \return 0 if OK, 1 on error | |
| 1513 * | |
| 1514 * <pre> | |
| 1515 * Notes: | |
| 1516 * (1) This function takes any image file as input and generates a | |
| 1517 * flate-compressed, ascii85 encoded PS file, with a bounding box. | |
| 1518 * (2) The bounding box is required when a program such as TeX | |
| 1519 * (through epsf) places and rescales the image. | |
| 1520 * (3) The bounding box is sized for fitting the image to an | |
| 1521 * 8.5 x 11.0 inch page. | |
| 1522 * </pre> | |
| 1523 */ | |
| 1524 l_ok | |
| 1525 convertFlateToPSEmbed(const char *filein, | |
| 1526 const char *fileout) | |
| 1527 { | |
| 1528 char *outstr; | |
| 1529 l_int32 w, h, nbytes, ret; | |
| 1530 l_float32 xpt, ypt, wpt, hpt; | |
| 1531 L_COMP_DATA *cid; | |
| 1532 | |
| 1533 if (!filein) | |
| 1534 return ERROR_INT("filein not defined", __func__, 1); | |
| 1535 if (!fileout) | |
| 1536 return ERROR_INT("fileout not defined", __func__, 1); | |
| 1537 | |
| 1538 if ((cid = l_generateFlateData(filein, 1)) == NULL) | |
| 1539 return ERROR_INT("flate data not made", __func__, 1); | |
| 1540 w = cid->w; | |
| 1541 h = cid->h; | |
| 1542 | |
| 1543 /* Scale for 20 pt boundary and otherwise full filling | |
| 1544 * in one direction on 8.5 x 11 inch device */ | |
| 1545 xpt = 20.0; | |
| 1546 ypt = 20.0; | |
| 1547 if (w * 11.0 > h * 8.5) { | |
| 1548 wpt = 572.0; /* 612 - 2 * 20 */ | |
| 1549 hpt = wpt * (l_float32)h / (l_float32)w; | |
| 1550 } else { | |
| 1551 hpt = 752.0; /* 792 - 2 * 20 */ | |
| 1552 wpt = hpt * (l_float32)w / (l_float32)h; | |
| 1553 } | |
| 1554 | |
| 1555 /* Generate the PS. | |
| 1556 * The bounding box information should be inserted (default). */ | |
| 1557 outstr = generateFlatePS(NULL, cid, xpt, ypt, wpt, hpt, 1, 1); | |
| 1558 l_CIDataDestroy(&cid); | |
| 1559 if (!outstr) | |
| 1560 return ERROR_INT("outstr not made", __func__, 1); | |
| 1561 nbytes = strlen(outstr); | |
| 1562 | |
| 1563 ret = l_binaryWrite(fileout, "w", outstr, nbytes); | |
| 1564 LEPT_FREE(outstr); | |
| 1565 if (ret) L_ERROR("ps string not written to file\n", __func__); | |
| 1566 return ret; | |
| 1567 } | |
| 1568 | |
| 1569 | |
| 1570 /*! | |
| 1571 * \brief convertFlateToPS() | |
| 1572 * | |
| 1573 * \param[in] filein input file -- any format | |
| 1574 * \param[in] fileout output ps file | |
| 1575 * \param[in] operation "w" for write; "a" for append | |
| 1576 * \param[in] x, y location of LL corner of image, in pixels, relative | |
| 1577 * to the PostScript origin (0,0) at the LL corner | |
| 1578 * of the page | |
| 1579 * \param[in] res resolution of the input image, in ppi; | |
| 1580 * use 0 for default | |
| 1581 * \param[in] scale scaling by printer; use 0.0 or 1.0 for no scaling | |
| 1582 * \param[in] pageno page number; must start with 1; you can use 0 | |
| 1583 * if there is only one page. | |
| 1584 * \param[in] endpage boolean: use TRUE if this is the last image to be | |
| 1585 * added to the page; FALSE otherwise | |
| 1586 * \return 0 if OK, 1 on error | |
| 1587 * | |
| 1588 * <pre> | |
| 1589 * Notes: | |
| 1590 * (1) This outputs level 3 PS as flate compressed (overlaid | |
| 1591 * with ascii85 encoding). | |
| 1592 * (2) An output file can contain multiple pages, each with | |
| 1593 * multiple images. The arguments to convertFlateToPS() | |
| 1594 * allow you to control placement of png images on multiple | |
| 1595 * pages within a PostScript file. | |
| 1596 * (3) For the first image written to a file, use "w", which | |
| 1597 * opens for write and clears the file. For all subsequent | |
| 1598 * images written to that file, use "a". | |
| 1599 * (4) The (x, y) parameters give the LL corner of the image | |
| 1600 * relative to the LL corner of the page. They are in | |
| 1601 * units of pixels if scale = 1.0. If you use (e.g.) | |
| 1602 * scale = 2.0, the image is placed at (2x, 2y) on the page, | |
| 1603 * and the image dimensions are also doubled. | |
| 1604 * (5) Display vs printed resolution: | |
| 1605 * * If your display is 75 ppi and your image was created | |
| 1606 * at a resolution of 300 ppi, you can get the image | |
| 1607 * to print at the same size as it appears on your display | |
| 1608 * by either setting scale = 4.0 or by setting res = 75. | |
| 1609 * Both tell the printer to make a 4x enlarged image. | |
| 1610 * * If your image is generated at 150 ppi and you use scale = 1, | |
| 1611 * it will be rendered such that 150 pixels correspond | |
| 1612 * to 72 pts (1 inch on the printer). This function does | |
| 1613 * the conversion from pixels (with or without scaling) to | |
| 1614 * pts, which are the units that the printer uses. | |
| 1615 * * The printer will choose its own resolution to use | |
| 1616 * in rendering the image, which will not affect the size | |
| 1617 * of the rendered image. That is because the output | |
| 1618 * PostScript file describes the geometry in terms of pts, | |
| 1619 * which are defined to be 1/72 inch. The printer will | |
| 1620 * only see the size of the image in pts, through the | |
| 1621 * scale and translate parameters and the affine | |
| 1622 * transform (the ImageMatrix) of the image. | |
| 1623 * (6) To render multiple images on the same page, set | |
| 1624 * endpage = FALSE for each image until you get to the | |
| 1625 * last, for which you set endpage = TRUE. This causes the | |
| 1626 * "showpage" command to be invoked. Showpage outputs | |
| 1627 * the entire page and clears the raster buffer for the | |
| 1628 * next page to be added. Without a "showpage", | |
| 1629 * subsequent images from the next page will overlay those | |
| 1630 * previously put down. | |
| 1631 * (7) For multiple pages, increment the page number, starting | |
| 1632 * with page 1. This allows PostScript (and PDF) to build | |
| 1633 * a page directory, which viewers use for navigation. | |
| 1634 * </pre> | |
| 1635 */ | |
| 1636 l_ok | |
| 1637 convertFlateToPS(const char *filein, | |
| 1638 const char *fileout, | |
| 1639 const char *operation, | |
| 1640 l_int32 x, | |
| 1641 l_int32 y, | |
| 1642 l_int32 res, | |
| 1643 l_float32 scale, | |
| 1644 l_int32 pageno, | |
| 1645 l_int32 endpage) | |
| 1646 { | |
| 1647 char *outstr; | |
| 1648 l_int32 nbytes, ret; | |
| 1649 | |
| 1650 if (!filein) | |
| 1651 return ERROR_INT("filein not defined", __func__, 1); | |
| 1652 if (!fileout) | |
| 1653 return ERROR_INT("fileout not defined", __func__, 1); | |
| 1654 if (strcmp(operation, "w") && strcmp(operation, "a")) | |
| 1655 return ERROR_INT("operation must be \"w\" or \"a\"", __func__, 1); | |
| 1656 | |
| 1657 if (convertFlateToPSString(filein, &outstr, &nbytes, x, y, res, scale, | |
| 1658 pageno, endpage)) | |
| 1659 return ERROR_INT("ps string not made", __func__, 1); | |
| 1660 | |
| 1661 ret = l_binaryWrite(fileout, operation, outstr, nbytes); | |
| 1662 LEPT_FREE(outstr); | |
| 1663 if (ret) L_ERROR("ps string not written to file\n", __func__); | |
| 1664 return ret; | |
| 1665 } | |
| 1666 | |
| 1667 | |
| 1668 /*! | |
| 1669 * \brief convertFlateToPSString() | |
| 1670 * | |
| 1671 * Generates level 3 PS string in flate compressed format. | |
| 1672 * | |
| 1673 * \param[in] filein input image file | |
| 1674 * \param[out] poutstr PS string | |
| 1675 * \param[out] pnbytes number of bytes in PS string | |
| 1676 * \param[in] x, y location of LL corner of image, in pixels, relative | |
| 1677 * to the PostScript origin (0,0) at the LL corner | |
| 1678 * of the page | |
| 1679 * \param[in] res resolution of the input image, in ppi; | |
| 1680 * use 0 for default | |
| 1681 * \param[in] scale scaling by printer; use 0.0 or 1.0 for no scaling | |
| 1682 * \param[in] pageno page number; must start with 1; you can use 0 | |
| 1683 * if there is only one page. | |
| 1684 * \param[in] endpage boolean: use TRUE if this is the last image to be | |
| 1685 * added to the page; FALSE otherwise | |
| 1686 * \return 0 if OK, 1 on error | |
| 1687 * | |
| 1688 * <pre> | |
| 1689 * Notes: | |
| 1690 * (1) The returned PS character array is a null-terminated | |
| 1691 * ascii string. All the raster data is ascii85 encoded, so | |
| 1692 * there are no null bytes embedded in it. | |
| 1693 * (2) The raster encoding is made with gzip, the same as that | |
| 1694 * in a png file that is compressed without prediction. | |
| 1695 * The raster data itself is 25% larger than that in the | |
| 1696 * binary form, due to the ascii85 encoding. | |
| 1697 * | |
| 1698 * Usage: See convertFlateToPS() | |
| 1699 * </pre> | |
| 1700 */ | |
| 1701 static l_ok | |
| 1702 convertFlateToPSString(const char *filein, | |
| 1703 char **poutstr, | |
| 1704 l_int32 *pnbytes, | |
| 1705 l_int32 x, | |
| 1706 l_int32 y, | |
| 1707 l_int32 res, | |
| 1708 l_float32 scale, | |
| 1709 l_int32 pageno, | |
| 1710 l_int32 endpage) | |
| 1711 { | |
| 1712 char *outstr; | |
| 1713 l_float32 xpt, ypt, wpt, hpt; | |
| 1714 L_COMP_DATA *cid; | |
| 1715 | |
| 1716 if (!poutstr) | |
| 1717 return ERROR_INT("&outstr not defined", __func__, 1); | |
| 1718 if (!pnbytes) | |
| 1719 return ERROR_INT("&nbytes not defined", __func__, 1); | |
| 1720 *pnbytes = 0; | |
| 1721 *poutstr = NULL; | |
| 1722 if (!filein) | |
| 1723 return ERROR_INT("filein not defined", __func__, 1); | |
| 1724 | |
| 1725 if ((cid = l_generateFlateData(filein, 1)) == NULL) | |
| 1726 return ERROR_INT("flate data not made", __func__, 1); | |
| 1727 | |
| 1728 /* Get scaled location in pts. Guess the input scan resolution | |
| 1729 * based on the input parameter %res, the resolution data in | |
| 1730 * the pix, and the size of the image. */ | |
| 1731 if (scale == 0.0) | |
| 1732 scale = 1.0; | |
| 1733 if (res <= 0) { | |
| 1734 if (cid->res > 0) | |
| 1735 res = cid->res; | |
| 1736 else | |
| 1737 res = DefaultInputRes; | |
| 1738 } | |
| 1739 xpt = scale * x * 72.f / res; | |
| 1740 ypt = scale * y * 72.f / res; | |
| 1741 wpt = scale * cid->w * 72.f / res; | |
| 1742 hpt = scale * cid->h * 72.f / res; | |
| 1743 | |
| 1744 if (pageno == 0) | |
| 1745 pageno = 1; | |
| 1746 | |
| 1747 #if DEBUG_FLATE | |
| 1748 lept_stderr("w = %d, h = %d, bps = %d, spp = %d\n", | |
| 1749 cid->w, cid->h, cid->bps, cid->spp); | |
| 1750 lept_stderr("uncomp bytes = %ld, comp bytes = %ld, nbytes85 = %ld\n", | |
| 1751 (unsigned long)cid->nbytes, (unsigned long)cid->nbytescomp, | |
| 1752 (unsigned long)cid->nbytes85); | |
| 1753 lept_stderr("xpt = %7.2f, ypt = %7.2f, wpt = %7.2f, hpt = %7.2f\n", | |
| 1754 xpt, ypt, wpt, hpt); | |
| 1755 #endif /* DEBUG_FLATE */ | |
| 1756 | |
| 1757 /* Generate the PS */ | |
| 1758 outstr = generateFlatePS(NULL, cid, xpt, ypt, wpt, hpt, pageno, endpage); | |
| 1759 l_CIDataDestroy(&cid); | |
| 1760 if (!outstr) | |
| 1761 return ERROR_INT("outstr not made", __func__, 1); | |
| 1762 *poutstr = outstr; | |
| 1763 *pnbytes = strlen(outstr); | |
| 1764 return 0; | |
| 1765 } | |
| 1766 | |
| 1767 | |
| 1768 /*! | |
| 1769 * \brief generateFlatePS() | |
| 1770 * | |
| 1771 * \param[in] filein [optional] input filename; can be null | |
| 1772 * \param[in] cid flate compressed image data | |
| 1773 * \param[in] xpt, ypt location of LL corner of image, in pts, relative | |
| 1774 * to the PostScript origin (0,0) at the LL corner | |
| 1775 * of the page | |
| 1776 * \param[in] wpt, hpt rendered image size in pts | |
| 1777 * \param[in] pageno page number; must start with 1; you can use 0 | |
| 1778 * if there is only one page | |
| 1779 * \param[in] endpage boolean: use TRUE if this is the last image to be | |
| 1780 * added to the page; FALSE otherwise | |
| 1781 * \return PS string, or NULL on error | |
| 1782 */ | |
| 1783 static char * | |
| 1784 generateFlatePS(const char *filein, | |
| 1785 L_COMP_DATA *cid, | |
| 1786 l_float32 xpt, | |
| 1787 l_float32 ypt, | |
| 1788 l_float32 wpt, | |
| 1789 l_float32 hpt, | |
| 1790 l_int32 pageno, | |
| 1791 l_int32 endpage) | |
| 1792 { | |
| 1793 l_int32 w, h, bps, spp; | |
| 1794 char *outstr; | |
| 1795 char bigbuf[Bufsize]; | |
| 1796 SARRAY *sa; | |
| 1797 | |
| 1798 if (!cid) | |
| 1799 return (char *)ERROR_PTR("flate data not defined", __func__, NULL); | |
| 1800 w = cid->w; | |
| 1801 h = cid->h; | |
| 1802 bps = cid->bps; | |
| 1803 spp = cid->spp; | |
| 1804 | |
| 1805 sa = sarrayCreate(50); | |
| 1806 sarrayAddString(sa, "%!PS-Adobe-3.0 EPSF-3.0", L_COPY); | |
| 1807 sarrayAddString(sa, "%%Creator: leptonica", L_COPY); | |
| 1808 if (filein) | |
| 1809 snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: %s", filein); | |
| 1810 else | |
| 1811 snprintf(bigbuf, sizeof(bigbuf), "%%%%Title: Flate compressed PS"); | |
| 1812 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1813 sarrayAddString(sa, "%%DocumentData: Clean7Bit", L_COPY); | |
| 1814 | |
| 1815 if (var_PS_WRITE_BOUNDING_BOX == 1) { | |
| 1816 snprintf(bigbuf, sizeof(bigbuf), | |
| 1817 "%%%%BoundingBox: %7.2f %7.2f %7.2f %7.2f", | |
| 1818 xpt, ypt, xpt + wpt, ypt + hpt); | |
| 1819 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1820 } | |
| 1821 | |
| 1822 sarrayAddString(sa, "%%LanguageLevel: 3", L_COPY); | |
| 1823 sarrayAddString(sa, "%%EndComments", L_COPY); | |
| 1824 snprintf(bigbuf, sizeof(bigbuf), "%%%%Page: %d %d", pageno, pageno); | |
| 1825 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1826 | |
| 1827 sarrayAddString(sa, "save", L_COPY); | |
| 1828 snprintf(bigbuf, sizeof(bigbuf), | |
| 1829 "%7.2f %7.2f translate %%set image origin in pts", xpt, ypt); | |
| 1830 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1831 | |
| 1832 snprintf(bigbuf, sizeof(bigbuf), | |
| 1833 "%7.2f %7.2f scale %%set image size in pts", wpt, hpt); | |
| 1834 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1835 | |
| 1836 /* If there is a colormap, add the data; it is now owned by sa */ | |
| 1837 if (cid->cmapdata85) { | |
| 1838 snprintf(bigbuf, sizeof(bigbuf), | |
| 1839 "[ /Indexed /DeviceRGB %d %%set colormap type/size", | |
| 1840 cid->ncolors - 1); | |
| 1841 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1842 sarrayAddString(sa, " <~", L_COPY); | |
| 1843 sarrayAddString(sa, cid->cmapdata85, L_INSERT); | |
| 1844 sarrayAddString(sa, " ] setcolorspace", L_COPY); | |
| 1845 } else if (spp == 1) { | |
| 1846 sarrayAddString(sa, "/DeviceGray setcolorspace", L_COPY); | |
| 1847 } else { /* spp == 3 */ | |
| 1848 sarrayAddString(sa, "/DeviceRGB setcolorspace", L_COPY); | |
| 1849 } | |
| 1850 | |
| 1851 sarrayAddString(sa, | |
| 1852 "/RawData currentfile /ASCII85Decode filter def", L_COPY); | |
| 1853 sarrayAddString(sa, | |
| 1854 "/Data RawData << >> /FlateDecode filter def", L_COPY); | |
| 1855 | |
| 1856 sarrayAddString(sa, "{ << /ImageType 1", L_COPY); | |
| 1857 snprintf(bigbuf, sizeof(bigbuf), " /Width %d", w); | |
| 1858 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1859 snprintf(bigbuf, sizeof(bigbuf), " /Height %d", h); | |
| 1860 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1861 snprintf(bigbuf, sizeof(bigbuf), " /BitsPerComponent %d", bps); | |
| 1862 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1863 snprintf(bigbuf, sizeof(bigbuf), | |
| 1864 " /ImageMatrix [ %d 0 0 %d 0 %d ]", w, -h, h); | |
| 1865 sarrayAddString(sa, bigbuf, L_COPY); | |
| 1866 | |
| 1867 if (cid->cmapdata85) { | |
| 1868 sarrayAddString(sa, " /Decode [0 255]", L_COPY); | |
| 1869 } else if (spp == 1) { | |
| 1870 if (bps == 1) /* miniswhite photometry */ | |
| 1871 sarrayAddString(sa, " /Decode [1 0]", L_COPY); | |
| 1872 else /* bps > 1 */ | |
| 1873 sarrayAddString(sa, " /Decode [0 1]", L_COPY); | |
| 1874 } else { /* spp == 3 */ | |
| 1875 sarrayAddString(sa, " /Decode [0 1 0 1 0 1]", L_COPY); | |
| 1876 } | |
| 1877 | |
| 1878 sarrayAddString(sa, " /DataSource Data", L_COPY); | |
| 1879 sarrayAddString(sa, " >> image", L_COPY); | |
| 1880 sarrayAddString(sa, " Data closefile", L_COPY); | |
| 1881 sarrayAddString(sa, " RawData flushfile", L_COPY); | |
| 1882 if (endpage == TRUE) | |
| 1883 sarrayAddString(sa, " showpage", L_COPY); | |
| 1884 sarrayAddString(sa, " restore", L_COPY); | |
| 1885 sarrayAddString(sa, "} exec", L_COPY); | |
| 1886 | |
| 1887 /* Insert the ascii85 gzipped data; this is now owned by sa */ | |
| 1888 sarrayAddString(sa, cid->data85, L_INSERT); | |
| 1889 | |
| 1890 /* Generate and return the output string */ | |
| 1891 outstr = sarrayToString(sa, 1); | |
| 1892 sarrayDestroy(&sa); | |
| 1893 cid->cmapdata85 = NULL; /* it has been transferred to sa and destroyed */ | |
| 1894 cid->data85 = NULL; /* it has been transferred to sa and destroyed */ | |
| 1895 return outstr; | |
| 1896 } | |
| 1897 | |
| 1898 | |
| 1899 /*---------------------------------------------------------------------* | |
| 1900 * Write to memory * | |
| 1901 *---------------------------------------------------------------------*/ | |
| 1902 /*! | |
| 1903 * \brief pixWriteMemPS() | |
| 1904 * | |
| 1905 * \param[out] pdata data of tiff compressed image | |
| 1906 * \param[out] psize size of returned data | |
| 1907 * \param[in] pix | |
| 1908 * \param[in] box [optional] | |
| 1909 * \param[in] res can use 0 for default of 300 ppi | |
| 1910 * \param[in] scale to prevent scaling, use either 1.0 or 0.0 | |
| 1911 * \return 0 if OK, 1 on error | |
| 1912 * | |
| 1913 * <pre> | |
| 1914 * Notes: | |
| 1915 * (1) See pixWriteStringPS() for usage. | |
| 1916 * (2) This is just a wrapper for pixWriteStringPS(), which | |
| 1917 * writes uncompressed image data to memory. | |
| 1918 * </pre> | |
| 1919 */ | |
| 1920 l_ok | |
| 1921 pixWriteMemPS(l_uint8 **pdata, | |
| 1922 size_t *psize, | |
| 1923 PIX *pix, | |
| 1924 BOX *box, | |
| 1925 l_int32 res, | |
| 1926 l_float32 scale) | |
| 1927 { | |
| 1928 if (!pdata) | |
| 1929 return ERROR_INT("&data not defined", __func__, 1 ); | |
| 1930 if (!psize) | |
| 1931 return ERROR_INT("&size not defined", __func__, 1 ); | |
| 1932 if (!pix) | |
| 1933 return ERROR_INT("&pix not defined", __func__, 1 ); | |
| 1934 | |
| 1935 *pdata = (l_uint8 *)pixWriteStringPS(pix, box, res, scale); | |
| 1936 *psize = strlen((char *)(*pdata)); | |
| 1937 return 0; | |
| 1938 } | |
| 1939 | |
| 1940 | |
| 1941 /*-------------------------------------------------------------* | |
| 1942 * Converting resolution * | |
| 1943 *-------------------------------------------------------------*/ | |
| 1944 /*! | |
| 1945 * \brief getResLetterPage() | |
| 1946 * | |
| 1947 * \param[in] w image width, pixels | |
| 1948 * \param[in] h image height, pixels | |
| 1949 * \param[in] fillfract fraction in linear dimension of full page, | |
| 1950 * not to be exceeded; use 0 for default | |
| 1951 * \return resolution | |
| 1952 */ | |
| 1953 l_int32 | |
| 1954 getResLetterPage(l_int32 w, | |
| 1955 l_int32 h, | |
| 1956 l_float32 fillfract) | |
| 1957 { | |
| 1958 l_int32 resw, resh, res; | |
| 1959 | |
| 1960 if (fillfract == 0.0) | |
| 1961 fillfract = DefaultFillFraction; | |
| 1962 resw = (l_int32)((w * 72.) / (LetterWidth * fillfract)); | |
| 1963 resh = (l_int32)((h * 72.) / (LetterHeight * fillfract)); | |
| 1964 res = L_MAX(resw, resh); | |
| 1965 return res; | |
| 1966 } | |
| 1967 | |
| 1968 | |
| 1969 /*! | |
| 1970 * \brief getResA4Page() | |
| 1971 * | |
| 1972 * \param[in] w image width, pixels | |
| 1973 * \param[in] h image height, pixels | |
| 1974 * \param[in] fillfract fraction in linear dimension of full page, | |
| 1975 * not to be exceeded; use 0 for default | |
| 1976 * \return resolution | |
| 1977 */ | |
| 1978 l_int32 | |
| 1979 getResA4Page(l_int32 w, | |
| 1980 l_int32 h, | |
| 1981 l_float32 fillfract) | |
| 1982 { | |
| 1983 l_int32 resw, resh, res; | |
| 1984 | |
| 1985 if (fillfract == 0.0) | |
| 1986 fillfract = DefaultFillFraction; | |
| 1987 resw = (l_int32)((w * 72.) / (A4Width * fillfract)); | |
| 1988 resh = (l_int32)((h * 72.) / (A4Height * fillfract)); | |
| 1989 res = L_MAX(resw, resh); | |
| 1990 return res; | |
| 1991 } | |
| 1992 | |
| 1993 | |
| 1994 /*-------------------------------------------------------------* | |
| 1995 * Setting flag for writing bounding box hint * | |
| 1996 *-------------------------------------------------------------*/ | |
| 1997 void | |
| 1998 l_psWriteBoundingBox(l_int32 flag) | |
| 1999 { | |
| 2000 var_PS_WRITE_BOUNDING_BOX = flag; | |
| 2001 } | |
| 2002 | |
| 2003 | |
| 2004 /* --------------------------------------------*/ | |
| 2005 #endif /* USE_PSIO */ | |
| 2006 /* --------------------------------------------*/ |
