mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2025-06-11 07:44:22 +02:00
Compare commits
5 Commits
aeee24b856
...
f09105dd3f
Author | SHA1 | Date | |
---|---|---|---|
|
f09105dd3f | ||
|
5be5552b2b | ||
|
492a4f51b2 | ||
|
44827bac1a | ||
|
3fad0d6f15 |
@ -10,6 +10,7 @@ v1.5.0 - YYYY-MM-DD
|
|||||||
(Issue #10)
|
(Issue #10)
|
||||||
- Added `pdfioFileGetModDate()` API (Issue #88)
|
- Added `pdfioFileGetModDate()` API (Issue #88)
|
||||||
- Added support for using libpng to embed PNG images in PDF output (Issue #90)
|
- Added support for using libpng to embed PNG images in PDF output (Issue #90)
|
||||||
|
- Added support for writing the PCLm subset of PDF (Issue #99)
|
||||||
- Now support opening damaged PDF files (Issue #45)
|
- Now support opening damaged PDF files (Issue #45)
|
||||||
- Updated the pdf2txt example to support font encodings.
|
- Updated the pdf2txt example to support font encodings.
|
||||||
|
|
||||||
|
22
doc/pdfio.3
22
doc/pdfio.3
@ -1,4 +1,4 @@
|
|||||||
.TH pdfio 3 "pdf read/write library" "2025-02-13" "pdf read/write library"
|
.TH pdfio 3 "pdf read/write library" "2025-02-20" "pdf read/write library"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
pdfio \- pdf read/write library
|
pdfio \- pdf read/write library
|
||||||
.SH Introduction
|
.SH Introduction
|
||||||
@ -3561,7 +3561,8 @@ This function creates a new PDF file. The "filename" argument specifies the
|
|||||||
name of the PDF file to create.
|
name of the PDF file to create.
|
||||||
.PP
|
.PP
|
||||||
The "version" argument specifies the PDF version number for the file or
|
The "version" argument specifies the PDF version number for the file or
|
||||||
\fBNULL\fR for the default ("2.0").
|
\fBNULL\fR for the default ("2.0"). The value "PCLm-1.0" can be specified to
|
||||||
|
produce the PCLm subset of PDF.
|
||||||
.PP
|
.PP
|
||||||
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
||||||
CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" size
|
CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" size
|
||||||
@ -3643,8 +3644,19 @@ This function embeds a TrueType/OpenType font into a PDF file. The
|
|||||||
characters (potentially full Unicode, but more typically a subset)
|
characters (potentially full Unicode, but more typically a subset)
|
||||||
or to only support the Windows CP1252 (ISO-8859-1 with additional
|
or to only support the Windows CP1252 (ISO-8859-1 with additional
|
||||||
characters such as the Euro symbol) subset of Unicode.
|
characters such as the Euro symbol) subset of Unicode.
|
||||||
|
.SS pdfioFileCreateICCObjFromData
|
||||||
|
Add ICC profile data to a PDF file.
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
pdfio_obj_t * pdfioFileCreateICCObjFromData (
|
||||||
|
pdfio_file_t *pdf,
|
||||||
|
const unsigned char *data,
|
||||||
|
size_t datalen,
|
||||||
|
size_t num_colors
|
||||||
|
);
|
||||||
|
.fi
|
||||||
.SS pdfioFileCreateICCObjFromFile
|
.SS pdfioFileCreateICCObjFromFile
|
||||||
Add an ICC profile object to a PDF file.
|
Add an ICC profile file to a PDF file.
|
||||||
.PP
|
.PP
|
||||||
.nf
|
.nf
|
||||||
pdfio_obj_t * pdfioFileCreateICCObjFromFile (
|
pdfio_obj_t * pdfioFileCreateICCObjFromFile (
|
||||||
@ -3767,7 +3779,9 @@ written:
|
|||||||
.fi
|
.fi
|
||||||
|
|
||||||
The "version" argument specifies the PDF version number for the file or
|
The "version" argument specifies the PDF version number for the file or
|
||||||
\fBNULL\fR for the default ("2.0").
|
\fBNULL\fR for the default ("2.0"). Unlike \fIpdfioFileCreate\fR and
|
||||||
|
\fIpdfioFileCreateTemporary\fR, it is generally not safe to pass the
|
||||||
|
"PCLm-1.0" version string.
|
||||||
.PP
|
.PP
|
||||||
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
||||||
CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" size
|
CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" size
|
||||||
|
@ -400,6 +400,7 @@ span.string {
|
|||||||
<li><a href="#pdfioFileCreateArrayObj">pdfioFileCreateArrayObj</a></li>
|
<li><a href="#pdfioFileCreateArrayObj">pdfioFileCreateArrayObj</a></li>
|
||||||
<li><a href="#pdfioFileCreateFontObjFromBase">pdfioFileCreateFontObjFromBase</a></li>
|
<li><a href="#pdfioFileCreateFontObjFromBase">pdfioFileCreateFontObjFromBase</a></li>
|
||||||
<li><a href="#pdfioFileCreateFontObjFromFile">pdfioFileCreateFontObjFromFile</a></li>
|
<li><a href="#pdfioFileCreateFontObjFromFile">pdfioFileCreateFontObjFromFile</a></li>
|
||||||
|
<li><a href="#pdfioFileCreateICCObjFromData">pdfioFileCreateICCObjFromData</a></li>
|
||||||
<li><a href="#pdfioFileCreateICCObjFromFile">pdfioFileCreateICCObjFromFile</a></li>
|
<li><a href="#pdfioFileCreateICCObjFromFile">pdfioFileCreateICCObjFromFile</a></li>
|
||||||
<li><a href="#pdfioFileCreateImageObjFromData">pdfioFileCreateImageObjFromData</a></li>
|
<li><a href="#pdfioFileCreateImageObjFromData">pdfioFileCreateImageObjFromData</a></li>
|
||||||
<li><a href="#pdfioFileCreateImageObjFromFile">pdfioFileCreateImageObjFromFile</a></li>
|
<li><a href="#pdfioFileCreateImageObjFromFile">pdfioFileCreateImageObjFromFile</a></li>
|
||||||
@ -3814,7 +3815,8 @@ have been iterated.</p>
|
|||||||
name of the PDF file to create.<br>
|
name of the PDF file to create.<br>
|
||||||
<br>
|
<br>
|
||||||
The "version" argument specifies the PDF version number for the file or
|
The "version" argument specifies the PDF version number for the file or
|
||||||
<code>NULL</code> for the default ("2.0").<br>
|
<code>NULL</code> for the default ("2.0"). The value "PCLm-1.0" can be specified to
|
||||||
|
produce the PCLm subset of PDF.<br>
|
||||||
<br>
|
<br>
|
||||||
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
||||||
CropBox for pages in the PDF file - if <code>NULL</code> then a default "Universal" size
|
CropBox for pages in the PDF file - if <code>NULL</code> then a default "Universal" size
|
||||||
@ -3909,8 +3911,25 @@ Unicode.</p>
|
|||||||
characters (potentially full Unicode, but more typically a subset)
|
characters (potentially full Unicode, but more typically a subset)
|
||||||
or to only support the Windows CP1252 (ISO-8859-1 with additional
|
or to only support the Windows CP1252 (ISO-8859-1 with additional
|
||||||
characters such as the Euro symbol) subset of Unicode.</p>
|
characters such as the Euro symbol) subset of Unicode.</p>
|
||||||
|
<h3 class="function"><a id="pdfioFileCreateICCObjFromData">pdfioFileCreateICCObjFromData</a></h3>
|
||||||
|
<p class="description">Add ICC profile data to a PDF file.</p>
|
||||||
|
<p class="code">
|
||||||
|
<a href="#pdfio_obj_t">pdfio_obj_t</a> *pdfioFileCreateICCObjFromData(<a href="#pdfio_file_t">pdfio_file_t</a> *pdf, <span class="reserved">const</span> <span class="reserved">unsigned</span> <span class="reserved">char</span> *data, size_t datalen, size_t num_colors);</p>
|
||||||
|
<h4 class="parameters">Parameters</h4>
|
||||||
|
<table class="list"><tbody>
|
||||||
|
<tr><th>pdf</th>
|
||||||
|
<td class="description">PDF file</td></tr>
|
||||||
|
<tr><th>data</th>
|
||||||
|
<td class="description">ICC profile buffer</td></tr>
|
||||||
|
<tr><th>datalen</th>
|
||||||
|
<td class="description">Length of ICC profile</td></tr>
|
||||||
|
<tr><th>num_colors</th>
|
||||||
|
<td class="description">Number of color components (1, 3, or 4)</td></tr>
|
||||||
|
</tbody></table>
|
||||||
|
<h4 class="returnvalue">Return Value</h4>
|
||||||
|
<p class="description">Object</p>
|
||||||
<h3 class="function"><a id="pdfioFileCreateICCObjFromFile">pdfioFileCreateICCObjFromFile</a></h3>
|
<h3 class="function"><a id="pdfioFileCreateICCObjFromFile">pdfioFileCreateICCObjFromFile</a></h3>
|
||||||
<p class="description">Add an ICC profile object to a PDF file.</p>
|
<p class="description">Add an ICC profile file to a PDF file.</p>
|
||||||
<p class="code">
|
<p class="code">
|
||||||
<a href="#pdfio_obj_t">pdfio_obj_t</a> *pdfioFileCreateICCObjFromFile(<a href="#pdfio_file_t">pdfio_file_t</a> *pdf, <span class="reserved">const</span> <span class="reserved">char</span> *filename, size_t num_colors);</p>
|
<a href="#pdfio_obj_t">pdfio_obj_t</a> *pdfioFileCreateICCObjFromFile(<a href="#pdfio_file_t">pdfio_file_t</a> *pdf, <span class="reserved">const</span> <span class="reserved">char</span> *filename, size_t num_colors);</p>
|
||||||
<h4 class="parameters">Parameters</h4>
|
<h4 class="parameters">Parameters</h4>
|
||||||
@ -4071,7 +4090,9 @@ output_cb(void *output_cbdata, const void *buffer, size_t bytes)
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
The "version" argument specifies the PDF version number for the file or
|
The "version" argument specifies the PDF version number for the file or
|
||||||
<code>NULL</code> for the default ("2.0").<br>
|
<code>NULL</code> for the default ("2.0"). Unlike <a href="#pdfioFileCreate"><code>pdfioFileCreate</code></a> and
|
||||||
|
<a href="#pdfioFileCreateTemporary"><code>pdfioFileCreateTemporary</code></a>, it is generally not safe to pass the
|
||||||
|
"PCLm-1.0" version string.<br>
|
||||||
<br>
|
<br>
|
||||||
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
||||||
CropBox for pages in the PDF file - if <code>NULL</code> then a default "Universal" size
|
CropBox for pages in the PDF file - if <code>NULL</code> then a default "Universal" size
|
||||||
@ -4139,8 +4160,19 @@ You must call <a href="#pdfioObjClose"><code>pdfioObjClose</code></a> to write t
|
|||||||
<p class="description">Create a temporary PDF file.</p>
|
<p class="description">Create a temporary PDF file.</p>
|
||||||
<p class="discussion">This function creates a PDF file with a unique filename in the current
|
<p class="discussion">This function creates a PDF file with a unique filename in the current
|
||||||
temporary directory. The temporary file is stored in the string "buffer" an
|
temporary directory. The temporary file is stored in the string "buffer" an
|
||||||
will have a ".pdf" extension. Otherwise, this function works the same as
|
will have a ".pdf" extension.<br>
|
||||||
the <a href="#pdfioFileCreate"><code>pdfioFileCreate</code></a> function.
|
<br>
|
||||||
|
The "version" argument specifies the PDF version number for the file or
|
||||||
|
<code>NULL</code> for the default ("2.0"). The value "PCLm-1.0" can be specified to
|
||||||
|
produce the PCLm subset of PDF.<br>
|
||||||
|
<br>
|
||||||
|
The "media_box" and "crop_box" arguments specify the default MediaBox and
|
||||||
|
CropBox for pages in the PDF file - if <code>NULL</code> then a default "Universal" size
|
||||||
|
of 8.27x11in (the intersection of US Letter and ISO A4) is used.<br>
|
||||||
|
<br>
|
||||||
|
The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||||
|
and its data pointer - if <code>NULL</code> the default error handler is used that
|
||||||
|
writes error messages to <code>stderr</code>.
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
<h3 class="function"><a id="pdfioFileFindObj">pdfioFileFindObj</a></h3>
|
<h3 class="function"><a id="pdfioFileFindObj">pdfioFileFindObj</a></h3>
|
||||||
|
48
pdfio-file.c
48
pdfio-file.c
@ -165,7 +165,8 @@ pdfioFileClose(pdfio_file_t *pdf) // I - PDF file
|
|||||||
// name of the PDF file to create.
|
// name of the PDF file to create.
|
||||||
//
|
//
|
||||||
// The "version" argument specifies the PDF version number for the file or
|
// The "version" argument specifies the PDF version number for the file or
|
||||||
// `NULL` for the default ("2.0").
|
// `NULL` for the default ("2.0"). The value "PCLm-1.0" can be specified to
|
||||||
|
// produce the PCLm subset of PDF.
|
||||||
//
|
//
|
||||||
// The "media_box" and "crop_box" arguments specify the default MediaBox and
|
// The "media_box" and "crop_box" arguments specify the default MediaBox and
|
||||||
// CropBox for pages in the PDF file - if `NULL` then a default "Universal" size
|
// CropBox for pages in the PDF file - if `NULL` then a default "Universal" size
|
||||||
@ -397,7 +398,9 @@ _pdfioFileCreateObj(
|
|||||||
// ```
|
// ```
|
||||||
//
|
//
|
||||||
// The "version" argument specifies the PDF version number for the file or
|
// The "version" argument specifies the PDF version number for the file or
|
||||||
// `NULL` for the default ("2.0").
|
// `NULL` for the default ("2.0"). Unlike @link pdfioFileCreate@ and
|
||||||
|
// @link pdfioFileCreateTemporary@, it is generally not safe to pass the
|
||||||
|
// "PCLm-1.0" version string.
|
||||||
//
|
//
|
||||||
// The "media_box" and "crop_box" arguments specify the default MediaBox and
|
// The "media_box" and "crop_box" arguments specify the default MediaBox and
|
||||||
// CropBox for pages in the PDF file - if `NULL` then a default "Universal" size
|
// CropBox for pages in the PDF file - if `NULL` then a default "Universal" size
|
||||||
@ -532,8 +535,19 @@ pdfioFileCreateStringObj(
|
|||||||
//
|
//
|
||||||
// This function creates a PDF file with a unique filename in the current
|
// This function creates a PDF file with a unique filename in the current
|
||||||
// temporary directory. The temporary file is stored in the string "buffer" an
|
// temporary directory. The temporary file is stored in the string "buffer" an
|
||||||
// will have a ".pdf" extension. Otherwise, this function works the same as
|
// will have a ".pdf" extension.
|
||||||
// the @link pdfioFileCreate@ function.
|
//
|
||||||
|
// The "version" argument specifies the PDF version number for the file or
|
||||||
|
// `NULL` for the default ("2.0"). The value "PCLm-1.0" can be specified to
|
||||||
|
// produce the PCLm subset of PDF.
|
||||||
|
//
|
||||||
|
// The "media_box" and "crop_box" arguments specify the default MediaBox and
|
||||||
|
// CropBox for pages in the PDF file - if `NULL` then a default "Universal" size
|
||||||
|
// of 8.27x11in (the intersection of US Letter and ISO A4) is used.
|
||||||
|
//
|
||||||
|
// The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||||
|
// and its data pointer - if `NULL` the default error handler is used that
|
||||||
|
// writes error messages to `stderr`.
|
||||||
//
|
//
|
||||||
// @since PDFio v1.1@
|
// @since PDFio v1.1@
|
||||||
//
|
//
|
||||||
@ -1396,7 +1410,7 @@ create_common(
|
|||||||
pdf->output_cb = output_cb;
|
pdf->output_cb = output_cb;
|
||||||
pdf->output_ctx = output_cbdata;
|
pdf->output_ctx = output_cbdata;
|
||||||
pdf->filename = strdup(filename);
|
pdf->filename = strdup(filename);
|
||||||
pdf->version = strdup(version);
|
pdf->version = strdup(!strncmp(version, "PCLm-", 5) ? "1.4" : version);
|
||||||
pdf->mode = _PDFIO_MODE_WRITE;
|
pdf->mode = _PDFIO_MODE_WRITE;
|
||||||
pdf->error_cb = error_cb;
|
pdf->error_cb = error_cb;
|
||||||
pdf->error_data = error_cbdata;
|
pdf->error_data = error_cbdata;
|
||||||
@ -1427,8 +1441,15 @@ create_common(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write a standard PDF header...
|
// Write a standard PDF header...
|
||||||
if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%\342\343\317\323\n", version))
|
if (!strncmp(version, "PCLm-", 5))
|
||||||
|
{
|
||||||
|
if (!_pdfioFilePrintf(pdf, "%%PDF-1.4\n%%%s\n", version))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
else if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%\342\343\317\323\n", version))
|
||||||
|
{
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the pages object...
|
// Create the pages object...
|
||||||
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
||||||
@ -2364,8 +2385,7 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
|
|||||||
// Write the xref table...
|
// Write the xref table...
|
||||||
xref_offset = _pdfioFileTell(pdf);
|
xref_offset = _pdfioFileTell(pdf);
|
||||||
|
|
||||||
// TODO: Figure out how to do xref streams with encrypted output
|
if (strcmp(pdf->version, "1.5") >= 0 && !pdf->output_cb)
|
||||||
if (strcmp(pdf->version, "1.5") >= 0 && !pdf->output_cb && !pdf->encrypt_obj)
|
|
||||||
{
|
{
|
||||||
// Write a cross-reference stream...
|
// Write a cross-reference stream...
|
||||||
pdfio_dict_t *xref_dict; // Object dictionary
|
pdfio_dict_t *xref_dict; // Object dictionary
|
||||||
@ -2374,6 +2394,11 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
|
|||||||
pdfio_stream_t *xref_st; // Stream
|
pdfio_stream_t *xref_st; // Stream
|
||||||
int offsize; // Size of object offsets
|
int offsize; // Size of object offsets
|
||||||
unsigned char buffer[10]; // Buffer entry
|
unsigned char buffer[10]; // Buffer entry
|
||||||
|
pdfio_encryption_t encryption; // PDF encryption mode
|
||||||
|
|
||||||
|
// Disable encryption while we write the xref stream...
|
||||||
|
encryption = pdf->encryption;
|
||||||
|
pdf->encryption = PDFIO_ENCRYPTION_NONE;
|
||||||
|
|
||||||
// Figure out how many bytes are needed for the object numbers
|
// Figure out how many bytes are needed for the object numbers
|
||||||
if (xref_offset < 0xff)
|
if (xref_offset < 0xff)
|
||||||
@ -2416,13 +2441,14 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
|
|||||||
pdfioDictSetNumber(xref_dict, "Size", pdf->num_objs + 2);
|
pdfioDictSetNumber(xref_dict, "Size", pdf->num_objs + 2);
|
||||||
pdfioDictSetArray(xref_dict, "W", w_array);
|
pdfioDictSetArray(xref_dict, "W", w_array);
|
||||||
pdfioDictSetName(xref_dict, "Filter", "FlateDecode");
|
pdfioDictSetName(xref_dict, "Filter", "FlateDecode");
|
||||||
|
pdfioDictSetObj(xref_dict, "Info", pdf->info_obj);
|
||||||
|
pdfioDictSetObj(xref_dict, "Root", pdf->root_obj);
|
||||||
|
|
||||||
if (pdf->encrypt_obj)
|
if (pdf->encrypt_obj)
|
||||||
pdfioDictSetObj(xref_dict, "Encrypt", pdf->encrypt_obj);
|
pdfioDictSetObj(xref_dict, "Encrypt", pdf->encrypt_obj);
|
||||||
|
|
||||||
if (pdf->id_array)
|
if (pdf->id_array)
|
||||||
pdfioDictSetArray(xref_dict, "ID", pdf->id_array);
|
pdfioDictSetArray(xref_dict, "ID", pdf->id_array);
|
||||||
pdfioDictSetObj(xref_dict, "Info", pdf->info_obj);
|
|
||||||
pdfioDictSetObj(xref_dict, "Root", pdf->root_obj);
|
|
||||||
|
|
||||||
if ((xref_obj = pdfioFileCreateObj(pdf, xref_dict)) == NULL)
|
if ((xref_obj = pdfioFileCreateObj(pdf, xref_dict)) == NULL)
|
||||||
{
|
{
|
||||||
@ -2514,6 +2540,8 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file
|
|||||||
}
|
}
|
||||||
|
|
||||||
pdfioStreamClose(xref_st);
|
pdfioStreamClose(xref_st);
|
||||||
|
|
||||||
|
pdf->encryption = encryption;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// PDF object functions for PDFio.
|
// PDF object functions for PDFio.
|
||||||
//
|
//
|
||||||
// Copyright © 2021-2024 by Michael R Sweet.
|
// Copyright © 2021-2025 by Michael R Sweet.
|
||||||
//
|
//
|
||||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||||
// information.
|
// information.
|
||||||
@ -10,13 +10,6 @@
|
|||||||
#include "pdfio-private.h"
|
#include "pdfio-private.h"
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Local functions...
|
|
||||||
//
|
|
||||||
|
|
||||||
static bool write_obj_header(pdfio_obj_t *obj);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// 'pdfioObjClose()' - Close an object, writing any data as needed to the PDF
|
// 'pdfioObjClose()' - Close an object, writing any data as needed to the PDF
|
||||||
// file.
|
// file.
|
||||||
@ -42,7 +35,7 @@ pdfioObjClose(pdfio_obj_t *obj) // I - Object
|
|||||||
if (!obj->offset)
|
if (!obj->offset)
|
||||||
{
|
{
|
||||||
// Write the object value
|
// Write the object value
|
||||||
if (!write_obj_header(obj))
|
if (!_pdfioObjWriteHeader(obj))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
// Write the "endobj" line...
|
// Write the "endobj" line...
|
||||||
@ -195,7 +188,7 @@ pdfioObjCreateStream(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!write_obj_header(obj))
|
if (!_pdfioObjWriteHeader(obj))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
if (!_pdfioFilePuts(obj->pdf, "stream\n"))
|
if (!_pdfioFilePuts(obj->pdf, "stream\n"))
|
||||||
@ -205,7 +198,7 @@ pdfioObjCreateStream(
|
|||||||
obj->pdf->current_obj = obj;
|
obj->pdf->current_obj = obj;
|
||||||
|
|
||||||
// Return the new stream...
|
// Return the new stream...
|
||||||
return (_pdfioStreamCreate(obj, length_obj, filter));
|
return (_pdfioStreamCreate(obj, length_obj, 0, filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -582,11 +575,11 @@ _pdfioObjSetExtension(
|
|||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// 'write_obj_header()' - Write the object header...
|
// '_pdfioObjWriteHeader()' - Write the object header...
|
||||||
//
|
//
|
||||||
|
|
||||||
static bool // O - `true` on success, `false` on failure
|
bool // O - `true` on success, `false` on failure
|
||||||
write_obj_header(pdfio_obj_t *obj) // I - Object
|
_pdfioObjWriteHeader(pdfio_obj_t *obj) // I - Object
|
||||||
{
|
{
|
||||||
obj->offset = _pdfioFileTell(obj->pdf);
|
obj->offset = _pdfioFileTell(obj->pdf);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// Private header file for PDFio.
|
// Private header file for PDFio.
|
||||||
//
|
//
|
||||||
// Copyright © 2021-2024 by Michael R Sweet.
|
// Copyright © 2021-2025 by Michael R Sweet.
|
||||||
//
|
//
|
||||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||||
// information.
|
// information.
|
||||||
@ -107,7 +107,7 @@ typedef enum _pdfio_mode_e // Read/write mode
|
|||||||
typedef enum _pdfio_predictor_e // PNG predictor constants
|
typedef enum _pdfio_predictor_e // PNG predictor constants
|
||||||
{
|
{
|
||||||
_PDFIO_PREDICTOR_NONE = 1, // No predictor (default)
|
_PDFIO_PREDICTOR_NONE = 1, // No predictor (default)
|
||||||
_PDFIO_PREDICTOR_TIFF2 = 2, // TIFF2 predictor (???)
|
_PDFIO_PREDICTOR_TIFF2 = 2, // TIFF predictor 2 (difference from left neighbor)
|
||||||
_PDFIO_PREDICTOR_PNG_NONE = 10, // PNG None predictor (same as `_PDFIO_PREDICTOR_NONE`)
|
_PDFIO_PREDICTOR_PNG_NONE = 10, // PNG None predictor (same as `_PDFIO_PREDICTOR_NONE`)
|
||||||
_PDFIO_PREDICTOR_PNG_SUB = 11, // PNG Sub predictor
|
_PDFIO_PREDICTOR_PNG_SUB = 11, // PNG Sub predictor
|
||||||
_PDFIO_PREDICTOR_PNG_UP = 12, // PNG Up predictor
|
_PDFIO_PREDICTOR_PNG_UP = 12, // PNG Up predictor
|
||||||
@ -313,8 +313,9 @@ struct _pdfio_stream_s // Stream
|
|||||||
z_stream flate; // Flate filter state
|
z_stream flate; // Flate filter state
|
||||||
_pdfio_predictor_t predictor; // Predictor function, if any
|
_pdfio_predictor_t predictor; // Predictor function, if any
|
||||||
size_t pbpixel, // Size of a pixel in bytes
|
size_t pbpixel, // Size of a pixel in bytes
|
||||||
pbsize; // Predictor buffer size, if any
|
pbsize, // Predictor buffer size, if any
|
||||||
unsigned char cbuffer[4096], // Compressed data buffer
|
cbsize; // Compressed data buffer size
|
||||||
|
unsigned char *cbuffer, // Compressed data buffer
|
||||||
*prbuffer, // Raw buffer (previous line), as needed
|
*prbuffer, // Raw buffer (previous line), as needed
|
||||||
*psbuffer; // PNG filter buffer, as needed
|
*psbuffer; // PNG filter buffer, as needed
|
||||||
_pdfio_crypto_cb_t crypto_cb; // Encryption/descryption callback, if any
|
_pdfio_crypto_cb_t crypto_cb; // Encryption/descryption callback, if any
|
||||||
@ -383,8 +384,9 @@ extern void _pdfioObjDelete(pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
|||||||
extern void *_pdfioObjGetExtension(pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
extern void *_pdfioObjGetExtension(pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
||||||
extern bool _pdfioObjLoad(pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
extern bool _pdfioObjLoad(pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
||||||
extern void _pdfioObjSetExtension(pdfio_obj_t *obj, void *data, _pdfio_extfree_t datafree) _PDFIO_INTERNAL;
|
extern void _pdfioObjSetExtension(pdfio_obj_t *obj, void *data, _pdfio_extfree_t datafree) _PDFIO_INTERNAL;
|
||||||
|
extern bool _pdfioObjWriteHeader(pdfio_obj_t *obj) _PDFIO_INTERNAL;
|
||||||
|
|
||||||
extern pdfio_stream_t *_pdfioStreamCreate(pdfio_obj_t *obj, pdfio_obj_t *length_obj, pdfio_filter_t compression) _PDFIO_INTERNAL;
|
extern pdfio_stream_t *_pdfioStreamCreate(pdfio_obj_t *obj, pdfio_obj_t *length_obj, size_t cbsize, pdfio_filter_t compression) _PDFIO_INTERNAL;
|
||||||
extern pdfio_stream_t *_pdfioStreamOpen(pdfio_obj_t *obj, bool decode) _PDFIO_INTERNAL;
|
extern pdfio_stream_t *_pdfioStreamOpen(pdfio_obj_t *obj, bool decode) _PDFIO_INTERNAL;
|
||||||
|
|
||||||
extern bool _pdfioStringIsAllocated(pdfio_file_t *pdf, const char *s) _PDFIO_INTERNAL;
|
extern bool _pdfioStringIsAllocated(pdfio_file_t *pdf, const char *s) _PDFIO_INTERNAL;
|
||||||
|
@ -50,7 +50,7 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream
|
|||||||
|
|
||||||
while ((status = deflate(&st->flate, Z_FINISH)) != Z_STREAM_END)
|
while ((status = deflate(&st->flate, Z_FINISH)) != Z_STREAM_END)
|
||||||
{
|
{
|
||||||
size_t bytes = sizeof(st->cbuffer) - st->flate.avail_out,
|
size_t bytes = st->cbsize - st->flate.avail_out,
|
||||||
// Bytes to write
|
// Bytes to write
|
||||||
outbytes; // Actual bytes written
|
outbytes; // Actual bytes written
|
||||||
|
|
||||||
@ -89,13 +89,13 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream
|
|||||||
}
|
}
|
||||||
|
|
||||||
st->flate.next_out = (Bytef *)st->cbuffer + bytes;
|
st->flate.next_out = (Bytef *)st->cbuffer + bytes;
|
||||||
st->flate.avail_out = (uInt)(sizeof(st->cbuffer) - bytes);
|
st->flate.avail_out = (uInt)(st->cbsize - bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st->flate.avail_out < (uInt)sizeof(st->cbuffer))
|
if (st->flate.avail_out < (uInt)st->cbsize)
|
||||||
{
|
{
|
||||||
// Write any residuals...
|
// Write any residuals...
|
||||||
size_t bytes = sizeof(st->cbuffer) - st->flate.avail_out;
|
size_t bytes = st->cbsize - st->flate.avail_out;
|
||||||
// Bytes to write
|
// Bytes to write
|
||||||
|
|
||||||
if (st->crypto_cb)
|
if (st->crypto_cb)
|
||||||
@ -172,6 +172,7 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream
|
|||||||
|
|
||||||
st->pdf->current_obj = NULL;
|
st->pdf->current_obj = NULL;
|
||||||
|
|
||||||
|
free(st->cbuffer);
|
||||||
free(st->prbuffer);
|
free(st->prbuffer);
|
||||||
free(st->psbuffer);
|
free(st->psbuffer);
|
||||||
free(st);
|
free(st);
|
||||||
@ -190,6 +191,7 @@ pdfio_stream_t * // O - Stream or `NULL` on error
|
|||||||
_pdfioStreamCreate(
|
_pdfioStreamCreate(
|
||||||
pdfio_obj_t *obj, // I - Object
|
pdfio_obj_t *obj, // I - Object
|
||||||
pdfio_obj_t *length_obj, // I - Length object, if any
|
pdfio_obj_t *length_obj, // I - Length object, if any
|
||||||
|
size_t cbsize, // I - Size of compression buffer
|
||||||
pdfio_filter_t compression) // I - Compression to apply
|
pdfio_filter_t compression) // I - Compression to apply
|
||||||
{
|
{
|
||||||
pdfio_stream_t *st; // Stream
|
pdfio_stream_t *st; // Stream
|
||||||
@ -302,8 +304,21 @@ _pdfioStreamCreate(
|
|||||||
else
|
else
|
||||||
st->predictor = _PDFIO_PREDICTOR_NONE;
|
st->predictor = _PDFIO_PREDICTOR_NONE;
|
||||||
|
|
||||||
|
if (cbsize == 0)
|
||||||
|
cbsize = 4096;
|
||||||
|
|
||||||
|
st->cbsize = cbsize;
|
||||||
|
if ((st->cbuffer = malloc(cbsize)) == NULL)
|
||||||
|
{
|
||||||
|
_pdfioFileError(st->pdf, "Unable to allocate %lu bytes for Flate output buffer: %s", (unsigned long)cbsize, strerror(errno));
|
||||||
|
free(st->prbuffer);
|
||||||
|
free(st->psbuffer);
|
||||||
|
free(st);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
st->flate.next_out = (Bytef *)st->cbuffer;
|
st->flate.next_out = (Bytef *)st->cbuffer;
|
||||||
st->flate.avail_out = (uInt)sizeof(st->cbuffer);
|
st->flate.avail_out = (uInt)cbsize;
|
||||||
|
|
||||||
if ((status = deflateInit(&(st->flate), 9)) != Z_OK)
|
if ((status = deflateInit(&(st->flate), 9)) != Z_OK)
|
||||||
{
|
{
|
||||||
@ -567,11 +582,21 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
|||||||
else
|
else
|
||||||
st->predictor = _PDFIO_PREDICTOR_NONE;
|
st->predictor = _PDFIO_PREDICTOR_NONE;
|
||||||
|
|
||||||
|
st->cbsize = 4096;
|
||||||
|
if ((st->cbuffer = malloc(st->cbsize)) == NULL)
|
||||||
|
{
|
||||||
|
_pdfioFileError(st->pdf, "Unable to allocate %lu bytes for Flate compression buffer.", (unsigned long)st->cbsize);
|
||||||
|
free(st->prbuffer);
|
||||||
|
free(st->psbuffer);
|
||||||
|
free(st);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
PDFIO_DEBUG("_pdfioStreamOpen: pos=%ld\n", (long)_pdfioFileTell(st->pdf));
|
PDFIO_DEBUG("_pdfioStreamOpen: pos=%ld\n", (long)_pdfioFileTell(st->pdf));
|
||||||
if (sizeof(st->cbuffer) > st->remaining)
|
if (st->cbsize > st->remaining)
|
||||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
||||||
else
|
else
|
||||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, sizeof(st->cbuffer));
|
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
|
||||||
|
|
||||||
if (rbytes <= 0)
|
if (rbytes <= 0)
|
||||||
{
|
{
|
||||||
@ -1045,10 +1070,10 @@ stream_read(pdfio_stream_t *st, // I - Stream
|
|||||||
if (st->flate.avail_in == 0)
|
if (st->flate.avail_in == 0)
|
||||||
{
|
{
|
||||||
// Read more from the file...
|
// Read more from the file...
|
||||||
if (sizeof(st->cbuffer) > st->remaining)
|
if (st->cbsize > st->remaining)
|
||||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
||||||
else
|
else
|
||||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, sizeof(st->cbuffer));
|
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
|
||||||
|
|
||||||
if (rbytes <= 0)
|
if (rbytes <= 0)
|
||||||
return (-1); // End of file...
|
return (-1); // End of file...
|
||||||
@ -1101,10 +1126,10 @@ stream_read(pdfio_stream_t *st, // I - Stream
|
|||||||
if (st->flate.avail_in == 0)
|
if (st->flate.avail_in == 0)
|
||||||
{
|
{
|
||||||
// Read more from the file...
|
// Read more from the file...
|
||||||
if (sizeof(st->cbuffer) > st->remaining)
|
if (st->cbsize > st->remaining)
|
||||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
||||||
else
|
else
|
||||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, sizeof(st->cbuffer));
|
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
|
||||||
|
|
||||||
if (rbytes <= 0)
|
if (rbytes <= 0)
|
||||||
return (-1); // End of file...
|
return (-1); // End of file...
|
||||||
@ -1171,10 +1196,10 @@ stream_read(pdfio_stream_t *st, // I - Stream
|
|||||||
if (st->flate.avail_in == 0)
|
if (st->flate.avail_in == 0)
|
||||||
{
|
{
|
||||||
// Read more from the file...
|
// Read more from the file...
|
||||||
if (sizeof(st->cbuffer) > st->remaining)
|
if (st->cbsize > st->remaining)
|
||||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->remaining);
|
||||||
else
|
else
|
||||||
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, sizeof(st->cbuffer));
|
rbytes = _pdfioFileRead(st->pdf, st->cbuffer, st->cbsize);
|
||||||
|
|
||||||
if (rbytes <= 0)
|
if (rbytes <= 0)
|
||||||
return (-1); // End of file...
|
return (-1); // End of file...
|
||||||
@ -1278,10 +1303,10 @@ stream_write(pdfio_stream_t *st, // I - Stream
|
|||||||
|
|
||||||
while (st->flate.avail_in > 0)
|
while (st->flate.avail_in > 0)
|
||||||
{
|
{
|
||||||
if (st->flate.avail_out < (sizeof(st->cbuffer) / 8))
|
if (st->flate.avail_out < (st->cbsize / 8))
|
||||||
{
|
{
|
||||||
// Flush the compression buffer...
|
// Flush the compression buffer...
|
||||||
size_t cbytes = sizeof(st->cbuffer) - st->flate.avail_out,
|
size_t cbytes = st->cbsize - st->flate.avail_out,
|
||||||
outbytes;
|
outbytes;
|
||||||
|
|
||||||
if (st->crypto_cb)
|
if (st->crypto_cb)
|
||||||
@ -1310,7 +1335,7 @@ stream_write(pdfio_stream_t *st, // I - Stream
|
|||||||
}
|
}
|
||||||
|
|
||||||
st->flate.next_out = (Bytef *)st->cbuffer + cbytes;
|
st->flate.next_out = (Bytef *)st->cbuffer + cbytes;
|
||||||
st->flate.avail_out = (uInt)(sizeof(st->cbuffer) - cbytes);
|
st->flate.avail_out = (uInt)(st->cbsize - cbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deflate what we can this time...
|
// Deflate what we can this time...
|
||||||
|
Loading…
x
Reference in New Issue
Block a user