Commit e53aec2c authored by Adrian Johnson's avatar Adrian Johnson

Refactor ImageOutputDev to facilitate adding more output formats

- Move PPM/PBM code into a NetPBMWriter class so PNGWriter and
  TiffWritersupport be added.

- Create generic WriteRawIMage function for writing jpeg files so
  support for jpeg2000/jbig2 can be added.
parent 0ca0fcc9
......@@ -264,6 +264,7 @@ set(poppler_SRCS
goo/GooString.cc
goo/gmem.cc
goo/FixedPoint.cc
goo/NetPBMWriter.cc
goo/PNGWriter.cc
goo/TiffWriter.cc
goo/JpegWriter.cc
......
......@@ -13,6 +13,7 @@ poppler_goo_include_HEADERS = \
gmem.h \
gfile.h \
FixedPoint.h \
NetPBMWriter.h \
PNGWriter.h \
JpegWriter.h \
TiffWriter.h \
......@@ -55,6 +56,7 @@ libgoo_la_SOURCES = \
GooString.cc \
gmem.cc \
FixedPoint.cc \
NetPBMWriter.cc \
PNGWriter.cc \
JpegWriter.cc \
TiffWriter.cc \
......
//========================================================================
//
// NetPBMWriter.h
//
// Copyright 1998-2003 Glyph & Cog, LLC
//
//========================================================================
//
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2005, 2007, 2011 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2006 Rainer Keller <class321@gmx.de>
// Copyright (C) 2008 Timothy Lee <timothy.lee@siriushk.com>
// Copyright (C) 2008 Vasile Gaburici <gaburici@cs.umd.edu>
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
// Copyright (C) 2009 William Bader <williambader@hotmail.com>
// Copyright (C) 2010 Jakob Voss <jakob.voss@gbv.de>
// Copyright (C) 2012, 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2013 Thomas Fischer <fischer@unix-ag.uni-kl.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#include "poppler-config.h"
#include "NetPBMWriter.h"
// Writer for the NetPBM formats (PBM and PPM)
// This format is documented at:
// http://netpbm.sourceforge.net/doc/pbm.html
// http://netpbm.sourceforge.net/doc/ppm.html
NetPBMWriter::NetPBMWriter(Format formatA) : format(formatA)
{
}
bool NetPBMWriter::init(FILE *f, int widthA, int heightA, int hDPI, int vDPI)
{
file = f;
width = widthA;
if (format == MONOCHROME) {
fprintf(file, "P4\n");
fprintf(file, "%d %d\n", widthA, heightA);
} else {
fprintf(file, "P6\n");
fprintf(file, "%d %d\n", widthA, heightA);
fprintf(file, "255\n");
}
return true;
}
bool NetPBMWriter::writePointers(unsigned char **rowPointers, int rowCount)
{
for (int i = 0; i < rowCount; i++)
writeRow(&rowPointers[i]);
return true;
}
bool NetPBMWriter::writeRow(unsigned char **row)
{
if (format == MONOCHROME) {
// PBM uses 0 = white, 1 = black so we need to invert the colors
int size = (width + 7)/8;
for (int i = 0; i < size; i++)
fputc((*row)[i] ^ 0xff, file);
} else {
fwrite(*row, 1, width*3, file);
}
return true;
}
bool NetPBMWriter::close()
{
return true;
}
//========================================================================
//
// NetPBMWriter.h
//
// This file is licensed under the GPLv2 or later
//
// Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
// Copyright (C) 2009, 2011 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2010, 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2010 Brian Cameron <brian.cameron@oracle.com>
// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@alfa.de>
//
//========================================================================
#ifndef NETPBMWRITER_H
#define NETPBMWRITER_H
#include "poppler-config.h"
#include "ImgWriter.h"
// Writer for the NetPBM formats (PBM and PPM)
// This format is documented at:
// http://netpbm.sourceforge.net/doc/pbm.html
// http://netpbm.sourceforge.net/doc/ppm.html
class NetPBMWriter : public ImgWriter
{
public:
/* RGB - 3 bytes/pixel
* MONOCHROME - 8 pixels/byte
*/
enum Format { RGB, MONOCHROME };
NetPBMWriter(Format formatA = RGB);
~NetPBMWriter() {};
bool init(FILE *f, int width, int height, int hDPI, int vDPI);
bool writePointers(unsigned char **rowPointers, int rowCount);
bool writeRow(unsigned char **row);
bool close();
private:
FILE *file;
Format format;
int width;
};
#endif
......@@ -41,6 +41,7 @@
#include <ctype.h>
#include <math.h>
#include "goo/gmem.h"
#include "goo/NetPBMWriter.h"
#include "Error.h"
#include "GfxState.h"
#include "Object.h"
......@@ -280,177 +281,145 @@ void ImageOutputDev::listImage(GfxState *state, Object *ref, Stream *str,
++imgNum;
}
void ImageOutputDev::writeMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool interpolate, GBool inlineImg) {
void ImageOutputDev::writeRawImage(Stream *str, const char *ext) {
FILE *f;
int c;
int size, i;
// dump JPEG file
if (dumpJPEG && str->getKind() == strDCT && !inlineImg) {
// open the image file
setFilename(ext);
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
// open the image file
setFilename("jpg");
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
// initialize stream
str = str->getNextStream();
str->reset();
// initialize stream
str = str->getNextStream();
str->reset();
// copy the stream
while ((c = str->getChar()) != EOF)
fputc(c, f);
// copy the stream
while ((c = str->getChar()) != EOF)
fputc(c, f);
str->close();
fclose(f);
}
str->close();
fclose(f);
void ImageOutputDev::writeImageFile(ImgWriter *writer, ImageFormat format, const char *ext,
Stream *str, int width, int height, GfxImageColorMap *colorMap) {
FILE *f;
ImageStream *imgStr;
unsigned char *row;
unsigned char *rowp;
Guchar *p;
GfxRGB rgb;
GfxGray gray;
Guchar zero = 0;
int invert_bits = 0xff;
// dump PBM file
} else {
setFilename(ext);
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
// open the image file and write the PBM header
setFilename("pbm");
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
fprintf(f, "P4\n");
fprintf(f, "%d %d\n", width, height);
if (!writer->init(f, width, height, 72, 72)) {
error(errIO, -1, "Error writing '{0:s}'", fileName);
return;
}
if (format != imgMonochrome) {
// initialize stream
imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
colorMap->getBits());
imgStr->reset();
} else {
// initialize stream
str->reset();
}
row = (unsigned char *) gmallocn(width, sizeof(unsigned int));
// if 0 comes out as 0 in the color map, the we _flip_ stream bits
// otherwise we pass through stream bits unmolested
if (colorMap) {
colorMap->getGray(&zero, &gray);
if (colToByte(gray) == 0)
invert_bits = 0x00;
}
// copy the stream
size = height * ((width + 7) / 8);
for (i = 0; i < size; ++i) {
fputc(str->getChar(), f);
// for each line...
for (int y = 0; y < height; y++) {
switch (format) {
case imgRGB:
p = imgStr->getLine();
rowp = row;
for (int x = 0; x < width; ++x) {
if (p) {
colorMap->getRGB(p, &rgb);
*rowp++ = colToByte(rgb.r);
*rowp++ = colToByte(rgb.g);
*rowp++ = colToByte(rgb.b);
p += colorMap->getNumPixelComps();
} else {
*rowp++ = 0;
*rowp++ = 0;
*rowp++ = 0;
}
}
writer->writeRow(&row);
break;
case imgMonochrome:
int size = (width + 7)/8;
for (int x = 0; x < size; x++)
row[x] = str->getChar() ^ invert_bits;
writer->writeRow(&row);
break;
}
}
str->close();
fclose(f);
gfree(row);
if (format != imgMonochrome) {
imgStr->close();
delete imgStr;
}
str->close();
writer->close();
fclose(f);
}
void ImageOutputDev::writeImage(GfxState *state, Object *ref, Stream *str,
int width, int height,
GfxImageColorMap *colorMap,
GBool interpolate, int *maskColors, GBool inlineImg) {
FILE *f;
ImageStream *imgStr;
Guchar *p;
Guchar zero = 0;
GfxGray gray;
GfxRGB rgb;
int x, y;
int c;
int size, i;
int pbm_mask = 0xff;
GfxImageColorMap *colorMap, GBool inlineImg) {
ImageFormat format;
// dump JPEG file
if (dumpJPEG && str->getKind() == strDCT &&
(colorMap->getNumPixelComps() == 1 ||
colorMap->getNumPixelComps() == 3) &&
!inlineImg) {
// open the image file
setFilename("jpg");
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
// initialize stream
str = str->getNextStream();
str->reset();
// copy the stream
while ((c = str->getChar()) != EOF)
fputc(c, 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
setFilename("pbm");
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
}
fprintf(f, "P4\n");
fprintf(f, "%d %d\n", width, height);
// initialize stream
str->reset();
// if 0 comes out as 0 in the color map, the we _flip_ stream bits
// otherwise we pass through stream bits unmolested
colorMap->getGray(&zero, &gray);
if(colToByte(gray))
pbm_mask = 0;
// copy the stream
size = height * ((width + 7) / 8);
for (i = 0; i < size; ++i) {
fputc(str->getChar() ^ pbm_mask, f);
}
str->close();
fclose(f);
// dump JPEG file
writeRawImage(str, "jpg");
// dump PPM file
} else {
ImgWriter *writer;
// open the image file and write the PPM header
setFilename("ppm");
++imgNum;
if (!(f = fopen(fileName, "wb"))) {
error(errIO, -1, "Couldn't open image file '{0:s}'", fileName);
return;
// dump PBM file
if (!colorMap || (colorMap->getNumPixelComps() == 1 && colorMap->getBits() == 1)) {
writer = new NetPBMWriter(NetPBMWriter::MONOCHROME);
format = imgMonochrome;
} else {
writer = new NetPBMWriter(NetPBMWriter::RGB);
format = imgRGB;
}
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);
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;
writeImageFile(writer, format,
format == imgRGB ? "ppm" : "pbm",
str, width, height, colorMap);
fclose(f);
delete writer;
}
}
......@@ -469,7 +438,7 @@ void ImageOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
if (listImages)
listImage(state, ref, str, width, height, NULL, interpolate, inlineImg, imgStencil);
else
writeMask(state, ref, str, width, height, invert, interpolate, inlineImg);
writeImage(state, ref, str, width, height, NULL, inlineImg);
}
void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
......@@ -479,7 +448,7 @@ void ImageOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
if (listImages)
listImage(state, ref, str, width, height, colorMap, interpolate, inlineImg, imgImage);
else
writeImage(state, ref, str, width, height, colorMap, interpolate, maskColors, inlineImg);
writeImage(state, ref, str, width, height, colorMap, inlineImg);
}
void ImageOutputDev::drawMaskedImage(
......@@ -490,9 +459,8 @@ void ImageOutputDev::drawMaskedImage(
listImage(state, ref, str, width, height, colorMap, interpolate, gFalse, imgImage);
listImage(state, ref, str, maskWidth, maskHeight, NULL, maskInterpolate, gFalse, imgMask);
} else {
drawImage(state, ref, str, width, height, colorMap, interpolate, NULL, gFalse);
drawImageMask(state, ref, maskStr, maskWidth, maskHeight, maskInvert,
maskInterpolate, gFalse);
writeImage(state, ref, str, width, height, colorMap, gFalse);
writeImage(state, ref, maskStr, maskWidth, maskHeight, NULL, gFalse);
}
}
......@@ -505,8 +473,7 @@ void ImageOutputDev::drawSoftMaskedImage(
listImage(state, ref, str, width, height, colorMap, interpolate, gFalse, imgImage);
listImage(state, ref, maskStr, maskWidth, maskHeight, maskColorMap, maskInterpolate, gFalse, imgSmask);
} else {
drawImage(state, ref, str, width, height, colorMap, interpolate, NULL, gFalse);
drawImage(state, ref, maskStr, maskWidth, maskHeight,
maskColorMap, maskInterpolate, NULL, gFalse);
writeImage(state, ref, str, width, height, colorMap, gFalse);
writeImage(state, ref, maskStr, maskWidth, maskHeight, maskColorMap, gFalse);
}
}
......@@ -36,6 +36,7 @@
#include <stdio.h>
#include "goo/gtypes.h"
#include "goo/ImgWriter.h"
#include "OutputDev.h"
class GfxState;
......@@ -52,6 +53,10 @@ public:
imgMask,
imgSmask
};
enum ImageFormat {
imgRGB,
imgMonochrome
};
// Create an OutputDev which will write images to files named
// <fileRoot>-NNN.<type> or <fileRoot>-PPP-NNN.<type>, if
......@@ -128,13 +133,11 @@ private:
GfxImageColorMap *colorMap,
GBool interpolate, GBool inlineImg,
ImageType imageType);
void writeMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool interpolate, GBool inlineImg);
void writeImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap *colorMap,
GBool interpolate, int *maskColors, GBool inlineImg);
int width, int height, GfxImageColorMap *colorMap, GBool inlineImg);
void writeRawImage(Stream *str, const char *ext);
void writeImageFile(ImgWriter *writer, ImageFormat format, const char *ext,
Stream *str, int width, int height, GfxImageColorMap *colorMap);
char *fileRoot; // root of output file names
char *fileName; // buffer for output file names
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment