Files
DocumentServer-v-9.2.0/core/PdfFile/lib/xpdf/ImageOutputDev.cc
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

454 lines
11 KiB
C++

//========================================================================
//
// ImageOutputDev.cc
//
// Copyright 1998-2003 Glyph & Cog, LLC
//
//========================================================================
#include <aconf.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <math.h>
#include "gmem.h"
#include "gmempp.h"
#include "config.h"
#include "Error.h"
#include "GfxState.h"
#include "Object.h"
#include "Stream.h"
#include "ImageOutputDev.h"
ImageOutputDev::ImageOutputDev(char *fileRootA, GBool dumpJPEGA,
GBool dumpRawA, GBool listA) {
fileRoot = copyString(fileRootA);
dumpJPEG = dumpJPEGA;
dumpRaw = dumpRawA;
list = listA;
imgNum = 0;
curPageNum = 0;
ok = gTrue;
}
ImageOutputDev::~ImageOutputDev() {
gfree(fileRoot);
}
void ImageOutputDev::startPage(int pageNum, GfxState *state) {
curPageNum = pageNum;
}
void ImageOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx,
Object *strRef,
int paintType, int tilingType,
Dict *resDict,
double *mat, double *bbox,
int x0, int y0, int x1, int y1,
double xStep, double yStep) {
// do nothing -- this avoids the potentially slow loop in Gfx.cc
}
void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg, GBool interpolate) {
GString *fileName;
FILE *f;
char buf[4096];
int size, n, i;
// dump raw file
if (dumpRaw && !inlineImg) {
// open the image file
fileName = GString::format("{0:s}-{1:04d}.{2:s}",
fileRoot, imgNum, getRawFileExtension(str));
++imgNum;
if (!(f = openFile(fileName->getCString(), "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:t}'", fileName);
delete fileName;
return;
}
// initialize stream
str = getRawStream(str);
str->reset();
// copy the stream
while ((n = str->getBlock(buf, sizeof(buf))) > 0) {
fwrite(buf, 1, n, f);
}
str->close();
fclose(f);
// dump JPEG file
} else if (dumpJPEG && str->getKind() == strDCT && !inlineImg) {
// open the image file
fileName = GString::format("{0:s}-{1:04d}.jpg", fileRoot, imgNum);
++imgNum;
if (!(f = openFile(fileName->getCString(), "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:t}'", fileName);
delete fileName;
return;
}
// initialize stream
str = ((DCTStream *)str)->getRawStream();
str->reset();
// copy the stream
while ((n = str->getBlock(buf, sizeof(buf))) > 0) {
fwrite(buf, 1, n, f);
}
str->close();
fclose(f);
// dump PBM file
} else {
// open the image file and write the PBM header
fileName = GString::format("{0:s}-{1:04d}.pbm", fileRoot, imgNum);
++imgNum;
if (!(f = openFile(fileName->getCString(), "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:t}'", fileName);
delete fileName;
return;
}
fprintf(f, "P4\n");
fprintf(f, "%d %d\n", width, height);
// initialize stream
str->reset();
// copy the stream
size = height * ((width + 7) / 8);
while (size > 0) {
i = size < (int)sizeof(buf) ? size : (int)sizeof(buf);
n = str->getBlock(buf, i);
fwrite(buf, 1, n, f);
if (n < i) {
break;
}
size -= n;
}
str->close();
fclose(f);
}
if (list) {
writeImageInfo(fileName, width, height, state, NULL);
}
delete fileName;
}
void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
int width, int height,
GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg,
GBool interpolate) {
GfxColorSpaceMode csMode;
GString *fileName;
FILE *f;
ImageStream *imgStr;
Guchar *p;
GfxRGB rgb;
GfxGray gray;
int x, y;
char buf[4096];
int size, n, i, j;
csMode = colorMap->getColorSpace()->getMode();
if (csMode == csIndexed) {
csMode = ((GfxIndexedColorSpace *)colorMap->getColorSpace())
->getBase()->getMode();
}
// dump raw file
if (dumpRaw && !inlineImg) {
// open the image file
fileName = GString::format("{0:s}-{1:04d}.{2:s}",
fileRoot, imgNum, getRawFileExtension(str));
++imgNum;
if (!(f = openFile(fileName->getCString(), "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:t}'", fileName);
delete fileName;
return;
}
// initialize stream
str = getRawStream(str);
str->reset();
// copy the stream
while ((n = str->getBlock(buf, sizeof(buf))) > 0) {
fwrite(buf, 1, n, f);
}
str->close();
fclose(f);
// dump JPEG file
} else if (dumpJPEG && str->getKind() == strDCT &&
(colorMap->getNumPixelComps() == 1 ||
colorMap->getNumPixelComps() == 3) &&
!inlineImg) {
// open the image file
fileName = GString::format("{0:s}-{1:04d}.jpg", fileRoot, imgNum);
++imgNum;
if (!(f = openFile(fileName->getCString(), "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:t}'", fileName);
delete fileName;
return;
}
// initialize stream
str = ((DCTStream *)str)->getRawStream();
str->reset();
// copy the stream
while ((n = str->getBlock(buf, sizeof(buf))) > 0) {
fwrite(buf, 1, n, f);
}
str->close();
fclose(f);
// dump PBM file
} else if (colorMap->getNumPixelComps() == 1 &&
colorMap->getBits() == 1) {
// open the image file and write the PBM header
fileName = GString::format("{0:s}-{1:04d}.pbm", fileRoot, imgNum);
++imgNum;
if (!(f = openFile(fileName->getCString(), "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:t}'", fileName);
delete fileName;
return;
}
fprintf(f, "P4\n");
fprintf(f, "%d %d\n", width, height);
// initialize stream
str->reset();
// copy the stream
size = height * ((width + 7) / 8);
while (size > 0) {
i = size < (int)sizeof(buf) ? size : (int)sizeof(buf);
n = str->getBlock(buf, i);
for (j = 0; j < n; ++j) {
buf[j] = (char)(buf[j] ^ 0xff);
}
fwrite(buf, 1, n, f);
if (n < i) {
break;
}
size -= n;
}
str->close();
fclose(f);
// dump PGM file
} else if (colorMap->getNumPixelComps() == 1 &&
(csMode == csDeviceGray || csMode == csCalGray)) {
// open the image file and write the PGM header
fileName = GString::format("{0:s}-{1:04d}.pgm", fileRoot, imgNum);
++imgNum;
if (!(f = openFile(fileName->getCString(), "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:t}'", fileName);
delete fileName;
return;
}
fprintf(f, "P5\n");
fprintf(f, "%d %d\n", width, height);
fprintf(f, "255\n");
// initialize stream
imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
colorMap->getBits());
imgStr->reset();
// for each line...
for (y = 0; y < height; ++y) {
// write the line
if ((p = imgStr->getLine())) {
for (x = 0; x < width; ++x) {
colorMap->getGray(p, &gray, state->getRenderingIntent());
fputc(colToByte(gray), f);
++p;
}
} else {
for (x = 0; x < width; ++x) {
fputc(0, f);
}
}
}
imgStr->close();
delete imgStr;
fclose(f);
// dump PPM file
} else {
// open the image file and write the PPM header
fileName = GString::format("{0:s}-{1:04d}.ppm", fileRoot, imgNum);
++imgNum;
if (!(f = openFile(fileName->getCString(), "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:t}'", fileName);
delete fileName;
return;
}
fprintf(f, "P6\n");
fprintf(f, "%d %d\n", width, height);
fprintf(f, "255\n");
// initialize stream
imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
colorMap->getBits());
imgStr->reset();
// for each line...
for (y = 0; y < height; ++y) {
// write the line
if ((p = imgStr->getLine())) {
for (x = 0; x < width; ++x) {
colorMap->getRGB(p, &rgb, state->getRenderingIntent());
fputc(colToByte(rgb.r), f);
fputc(colToByte(rgb.g), f);
fputc(colToByte(rgb.b), f);
p += colorMap->getNumPixelComps();
}
} else {
for (x = 0; x < width; ++x) {
fputc(0, f);
fputc(0, f);
fputc(0, f);
}
}
}
imgStr->close();
delete imgStr;
fclose(f);
}
if (list) {
writeImageInfo(fileName, width, height, state, colorMap);
}
delete fileName;
}
void ImageOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
int width, int height,
GfxImageColorMap *colorMap,
Object *maskRef, Stream *maskStr,
int maskWidth, int maskHeight,
GBool maskInvert, GBool interpolate) {
drawImage(state, ref, str, width, height, colorMap,
NULL, gFalse, interpolate);
drawImageMask(state, maskRef, maskStr, maskWidth, maskHeight, maskInvert,
gFalse, interpolate);
}
void ImageOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
Stream *str,
int width, int height,
GfxImageColorMap *colorMap,
Object *maskRef, Stream *maskStr,
int maskWidth, int maskHeight,
GfxImageColorMap *maskColorMap,
double *matte, GBool interpolate) {
drawImage(state, ref, str, width, height, colorMap,
NULL, gFalse, interpolate);
drawImage(state, maskRef, maskStr, maskWidth, maskHeight, maskColorMap,
NULL, gFalse, interpolate);
}
Stream *ImageOutputDev::getRawStream(Stream *str) {
switch (str->getKind()) {
case strLZW:
case strRunLength:
case strCCITTFax:
case strDCT:
case strFlate:
case strJBIG2:
case strJPX:
return ((FilterStream *)str)->getNextStream();
default:
return str;
}
}
const char *ImageOutputDev::getRawFileExtension(Stream *str) {
switch (str->getKind()) {
case strLZW: return "lzw";
case strRunLength: return "rle";
case strCCITTFax: return "fax";
case strDCT: return "jpg";
case strFlate: return "flate";
case strJBIG2: return "jb2";
case strJPX: return "jpx";
default: return "unknown";
}
}
void ImageOutputDev::writeImageInfo(GString *fileName,
int width, int height, GfxState *state,
GfxImageColorMap *colorMap) {
const char *mode;
double hdpi, vdpi, x0, y0, x1, y1;
int bpc;
// this works for 0/90/180/270-degree rotations, along with
// horizontal/vertical flips
state->transformDelta(1, 0, &x0, &y0);
state->transformDelta(0, 1, &x1, &y1);
x0 = fabs(x0);
y0 = fabs(y0);
x1 = fabs(x1);
y1 = fabs(y1);
if (x0 > y0) {
hdpi = (72 * width) / x0;
vdpi = (72 * height) / y1;
} else {
hdpi = (72 * height) / x1;
vdpi = (72 * width) / y0;
}
if (colorMap) {
mode = GfxColorSpace::getColorSpaceModeName(
colorMap->getColorSpace()->getMode());
bpc = colorMap->getBits();
} else {
mode = NULL;
bpc = 1;
}
printf("%s: page=%d width=%d height=%d hdpi=%.2f vdpi=%.2f %s%s bpc=%d\n",
fileName->getCString(), curPageNum, width, height, hdpi, vdpi,
mode ? "colorspace=" : "mask",
mode ? mode : "",
bpc);
}