mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2024-12-27 05:48:20 +01:00
Implement JPEG image object support.
This commit is contained in:
parent
eb4477ce9b
commit
128d5f0d42
239
pdfio-content.c
239
pdfio-content.c
@ -12,13 +12,24 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "pdfio-content.h"
|
#include "pdfio-content.h"
|
||||||
|
#include "pdfio-private.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Local types...
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef pdfio_obj_t *(*image_func_t)(pdfio_dict_t *dict, int fd);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Local functions...
|
// Local functions...
|
||||||
//
|
//
|
||||||
|
|
||||||
|
static pdfio_obj_t *copy_gif(pdfio_dict_t *dict, int fd);
|
||||||
|
static pdfio_obj_t *copy_jpeg(pdfio_dict_t *dict, int fd);
|
||||||
|
static pdfio_obj_t *copy_png(pdfio_dict_t *dict, int fd);
|
||||||
static bool write_string(pdfio_stream_t *st, const char *s);
|
static bool write_string(pdfio_stream_t *st, const char *s);
|
||||||
|
|
||||||
|
|
||||||
@ -859,6 +870,8 @@ pdfioFileCreateICCProfileObject(
|
|||||||
//
|
//
|
||||||
// 'pdfioFileCreateImageObject()' - Add an image object to a PDF file.
|
// 'pdfioFileCreateImageObject()' - Add an image object to a PDF file.
|
||||||
//
|
//
|
||||||
|
// Currently only GIF, JPEG, and PNG files are supported.
|
||||||
|
//
|
||||||
|
|
||||||
pdfio_obj_t * // O - Object
|
pdfio_obj_t * // O - Object
|
||||||
pdfioFileCreateImageObject(
|
pdfioFileCreateImageObject(
|
||||||
@ -866,10 +879,230 @@ pdfioFileCreateImageObject(
|
|||||||
const char *filename, // I - Filename
|
const char *filename, // I - Filename
|
||||||
bool interpolate) // I - Interpolate image data?
|
bool interpolate) // I - Interpolate image data?
|
||||||
{
|
{
|
||||||
(void)pdf;
|
pdfio_dict_t *dict; // Image dictionary
|
||||||
(void)filename;
|
pdfio_obj_t *obj; // Image object
|
||||||
(void)interpolate;
|
int fd; // File
|
||||||
|
unsigned char buffer[32]; // Read buffer
|
||||||
|
image_func_t copy_func = NULL; // Image copy function
|
||||||
|
|
||||||
|
|
||||||
|
// Range check input...
|
||||||
|
if (!pdf || !filename)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
// Try opening the file...
|
||||||
|
if ((fd = open(filename, O_RDONLY | O_BINARY)) < 0)
|
||||||
|
{
|
||||||
|
_pdfioFileError(pdf, "Unable to open image file '%s': %s", filename, strerror(errno));
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the file header to determine the file format...
|
||||||
|
if (read(fd, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer))
|
||||||
|
{
|
||||||
|
_pdfioFileError(pdf, "Unable to read header from image file '%s'.", filename);
|
||||||
|
close(fd);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (!memcmp(buffer, "\211PNG\015\012\032\012\000\000\000\015IHDR", 16))
|
||||||
|
{
|
||||||
|
// PNG image...
|
||||||
|
copy_func = copy_png;
|
||||||
|
}
|
||||||
|
else if (!memcmp(buffer, "GIF87a", 6) || !memcmp(buffer, "GIF89a", 6))
|
||||||
|
{
|
||||||
|
// GIF image...
|
||||||
|
copy_func = copy_gif;
|
||||||
|
}
|
||||||
|
else if (!memcmp(buffer, "\377\330\377", 3))
|
||||||
|
{
|
||||||
|
// JPEG image...
|
||||||
|
copy_func = copy_jpeg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Something else that isn't supported...
|
||||||
|
_pdfioFileError(pdf, "Unsupported image file '%s'.", filename);
|
||||||
|
close(fd);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the base image dictionary the copy the file into an object...
|
||||||
|
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pdfioDictSetName(dict, "Type", "XObject");
|
||||||
|
pdfioDictSetName(dict, "SubType", "Image");
|
||||||
|
pdfioDictSetBoolean(dict, "Interpolate", interpolate);
|
||||||
|
|
||||||
|
obj = (copy_func)(dict, fd);
|
||||||
|
|
||||||
|
// Close the file and return the object...
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'copy_gif()' - Copy a GIF image.
|
||||||
|
//
|
||||||
|
|
||||||
|
static pdfio_obj_t * // O - Object or `NULL` on error
|
||||||
|
copy_gif(pdfio_dict_t *dict, // I - Dictionary
|
||||||
|
int fd) // I - File descriptor
|
||||||
|
{
|
||||||
|
// TODO: Implement copy_gif
|
||||||
|
(void)dict;
|
||||||
|
(void)fd;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'copy_jpeg()' - Copy a JPEG image.
|
||||||
|
//
|
||||||
|
|
||||||
|
static pdfio_obj_t * // O - Object or `NULL` on error
|
||||||
|
copy_jpeg(pdfio_dict_t *dict, // I - Dictionary
|
||||||
|
int fd) // I - File descriptor
|
||||||
|
{
|
||||||
|
pdfio_obj_t *obj; // Object
|
||||||
|
pdfio_stream_t *st; // Stream for JPEG data
|
||||||
|
ssize_t bytes; // Bytes read
|
||||||
|
unsigned char buffer[16384], // Read buffer
|
||||||
|
*bufptr, // Pointer into buffer
|
||||||
|
*bufend; // End of buffer
|
||||||
|
size_t length; // Length of chunk
|
||||||
|
unsigned width = 0, // Width in columns
|
||||||
|
height = 0, // Height in lines
|
||||||
|
num_colors = 0; // Number of colors
|
||||||
|
|
||||||
|
|
||||||
|
// Scan the file for a SOFn marker, then we can get the dimensions...
|
||||||
|
bytes = read(fd, buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
for (bufptr = buffer + 2, bufend = buffer + bytes; bufptr < bufend;)
|
||||||
|
{
|
||||||
|
if (*bufptr == 0xff)
|
||||||
|
{
|
||||||
|
bufptr ++;
|
||||||
|
|
||||||
|
if (bufptr >= bufend)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If we are at the end of the current buffer, re-fill and continue...
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((bytes = read(fd, buffer, sizeof(buffer))) <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bufptr = buffer;
|
||||||
|
bufend = buffer + bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*bufptr == 0xff)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((bufptr + 16) >= bufend)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Read more of the marker...
|
||||||
|
*/
|
||||||
|
|
||||||
|
bytes = bufend - bufptr;
|
||||||
|
|
||||||
|
memmove(buffer, bufptr, (size_t)bytes);
|
||||||
|
bufptr = buffer;
|
||||||
|
bufend = buffer + bytes;
|
||||||
|
|
||||||
|
if ((bytes = read(fd, bufend, sizeof(buffer) - (size_t)bytes)) <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bufend += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
length = (size_t)((bufptr[1] << 8) | bufptr[2]);
|
||||||
|
|
||||||
|
PDFIO_DEBUG("copy_jpeg: JPEG X'FF%02X' (length %u)\n", *bufptr, (unsigned)length);
|
||||||
|
|
||||||
|
if ((*bufptr >= 0xc0 && *bufptr <= 0xc3) || (*bufptr >= 0xc5 && *bufptr <= 0xc7) || (*bufptr >= 0xc9 && *bufptr <= 0xcb) || (*bufptr >= 0xcd && *bufptr <= 0xcf))
|
||||||
|
{
|
||||||
|
// SOFn marker, look for dimensions...
|
||||||
|
width = (unsigned)((bufptr[6] << 8) | bufptr[7]);
|
||||||
|
height = (unsigned)((bufptr[4] << 8) | bufptr[5]);
|
||||||
|
num_colors = bufptr[8];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip past this marker...
|
||||||
|
bufptr ++;
|
||||||
|
bytes = bufend - bufptr;
|
||||||
|
|
||||||
|
while (length >= (size_t)bytes)
|
||||||
|
{
|
||||||
|
length -= (size_t)bytes;
|
||||||
|
|
||||||
|
if ((bytes = read(fd, buffer, sizeof(buffer))) <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bufptr = buffer;
|
||||||
|
bufend = buffer + bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length > (size_t)bytes)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bufptr += length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width == 0 || height == 0 || (num_colors != 1 && num_colors != 3))
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
// Create the image object...
|
||||||
|
pdfioDictSetNumber(dict, "Width", width);
|
||||||
|
pdfioDictSetNumber(dict, "Height", height);
|
||||||
|
pdfioDictSetNumber(dict, "BitsPerComponent", 8);
|
||||||
|
pdfioDictSetName(dict, "ColorSpace", num_colors == 3 ? "CalRGB" : "CalGray");
|
||||||
|
pdfioDictSetName(dict, "Filter", "DCTDecode");
|
||||||
|
|
||||||
|
obj = pdfioFileCreateObject(dict->pdf, dict);
|
||||||
|
st = pdfioObjCreateStream(obj, PDFIO_FILTER_NONE);
|
||||||
|
|
||||||
|
// Copy the file to a stream...
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
|
||||||
|
{
|
||||||
|
if (!pdfioStreamWrite(st, buffer, (size_t)bytes))
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pdfioStreamClose(st))
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
return (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'copy_png()' - Copy a PNG image.
|
||||||
|
//
|
||||||
|
|
||||||
|
static pdfio_obj_t * // O - Object or `NULL` on error
|
||||||
|
copy_png(pdfio_dict_t *dict, // I - Dictionary
|
||||||
|
int fd) // I - File descriptor
|
||||||
|
{
|
||||||
|
// TODO: Implement copy_png
|
||||||
|
(void)dict;
|
||||||
|
(void)fd;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,51 @@
|
|||||||
# include <stdarg.h>
|
# include <stdarg.h>
|
||||||
# include <errno.h>
|
# include <errno.h>
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
|
# ifdef _WIN32
|
||||||
|
# include <io.h>
|
||||||
|
# include <direct.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Microsoft renames the POSIX functions to _name, and introduces
|
||||||
|
* a broken compatibility layer using the original names. As a result,
|
||||||
|
* random crashes can occur when, for example, strdup() allocates memory
|
||||||
|
* from a different heap than used by malloc() and free().
|
||||||
|
*
|
||||||
|
* To avoid moronic problems like this, we #define the POSIX function
|
||||||
|
* names to the corresponding non-standard Microsoft names.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# define access _access
|
||||||
|
# define close _close
|
||||||
|
# define fileno _fileno
|
||||||
|
# define lseek _lseek
|
||||||
|
# define mkdir(d,p) _mkdir(d)
|
||||||
|
# define open _open
|
||||||
|
# define read _read
|
||||||
|
# define rmdir _rmdir
|
||||||
|
# define snprintf _snprintf
|
||||||
|
# define strdup _strdup
|
||||||
|
# define unlink _unlink
|
||||||
|
# define vsnprintf _vsnprintf
|
||||||
|
# define write _write
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map various parameters for POSIX...
|
||||||
|
*/
|
||||||
|
|
||||||
|
# define F_OK 00
|
||||||
|
# define W_OK 02
|
||||||
|
# define R_OK 04
|
||||||
|
# define O_RDONLY _O_RDONLY
|
||||||
|
# define O_WRONLY _O_WRONLY
|
||||||
|
# define O_CREAT _O_CREAT
|
||||||
|
# define O_TRUNC _O_TRUNC
|
||||||
|
# define O_BINARY _O_BINARY
|
||||||
|
# else // !_WIN32
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
|
# define O_BINARY 0
|
||||||
|
# endif // _WIN32
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
# include <zlib.h>
|
# include <zlib.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user