add double-page-size example

git-svn-id: svn+q:///qpdf/trunk@996 71b93d88-0707-0410-a8cf-f5a4172ac649
This commit is contained in:
Jay Berkenbilt 2010-08-05 21:51:19 +00:00
parent 2dbc1006fb
commit 9ba5b27ce4
7 changed files with 276 additions and 6 deletions

View File

@ -1,5 +1,9 @@
2010-08-05 Jay Berkenbilt <ejb@ql.org>
* Add QPDFObjectHandle::addPageContents, a convenience routine for
appending or prepending new streams to a page's content streams.
The "double-page-size" example illustrates its use.
* Add new methods to QPDFObjectHandle: replaceStreamData and
newStream. These methods allow users of the qpdf library to add
new streams and to replace data of existing streams. Examples are

8
TODO
View File

@ -7,9 +7,9 @@ Next
in August, 2009. He seems to like to send encrypted mail (key
01FCC336). Tell him about newStream and replaceStreamData.
* Tell stronghorse@tom.com about QPDFObjectHandle::addPageContents.
See message from stronghorse@tom.com ("Suggestion for qpdf") from
2010-06-09 and my response.
* Tell stronghorse@tom.com about QPDFObjectHandle::addPageContents
and double-page-size example. See message from stronghorse@tom.com
("Suggestion for qpdf") from 2010-06-09 and my response.
2.2
===
@ -18,8 +18,6 @@ Next
image. Use QPDF::getAllPages and QPDFObjectHandle::getPageImages
along with new stream data and dictionary manipulation.
* Add example program for addPageContents using suggestion from
stronghorse@tom.com's message above.
General
=======

View File

@ -1,4 +1,4 @@
BINS_examples = pdf-bookmarks pdf-mod-info pdf-npages
BINS_examples = pdf-bookmarks pdf-mod-info pdf-npages double-page-size
CBINS_examples = pdf-linearize
TARGETS_examples = $(foreach B,$(BINS_examples) $(CBINS_examples),examples/$(OUTPUT_DIR)/$(call binname,$(B)))

View File

@ -0,0 +1,113 @@
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <qpdf/QPDF.hh>
#include <qpdf/QUtil.hh>
#include <qpdf/Buffer.hh>
#include <qpdf/QPDFWriter.hh>
static char const* whoami = 0;
void usage()
{
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]"
<< std::endl
<< "Double size of all pages in infile.pdf;"
<< " write output to outfile.pdf" << std::endl;
exit(2);
}
static void doubleBoxSize(QPDFObjectHandle& page, char const* box_name)
{
QPDFObjectHandle box = page.getKey(box_name);
if (box.isNull())
{
return;
}
if (! (box.isArray() && (box.getArrayNItems() == 4)))
{
throw std::runtime_error(std::string("box ") + box_name +
" is not an array of four elements");
}
std::vector<QPDFObjectHandle> doubled;
for (unsigned int i = 0; i < 4; ++i)
{
doubled.push_back(
QPDFObjectHandle::newReal(
QUtil::double_to_string(
box.getArrayItem(i).getNumericValue() * 2.0, 2)));
}
page.replaceKey(box_name, QPDFObjectHandle::newArray(doubled));
}
int main(int argc, char* argv[])
{
whoami = QUtil::getWhoami(argv[0]);
// For libtool's sake....
if (strncmp(whoami, "lt-", 3) == 0)
{
whoami += 3;
}
if (! ((argc == 3) || (argc == 4)))
{
usage();
}
char const* infilename = argv[1];
char const* outfilename = argv[2];
char const* password = (argc == 4) ? argv[3] : "";
// Text to prepend to each page's contents
char const* content = "2 0 0 2 0 0 cm\n";
// Copy text into a buffer without the null terminator
PointerHolder<Buffer> b = new Buffer(strlen(content));
unsigned char* bp = b.getPointer()->getBuffer();
memcpy(bp, (unsigned char*)content, strlen(content));
try
{
QPDF qpdf;
qpdf.processFile(infilename, password);
std::vector<QPDFObjectHandle> pages = qpdf.getAllPages();
for (std::vector<QPDFObjectHandle>::iterator iter = pages.begin();
iter != pages.end(); ++iter)
{
QPDFObjectHandle& page = *iter;
// Prepend the buffer to the page's contents
page.addPageContents(QPDFObjectHandle::newStream(&qpdf, b), true);
// Double the size of each of the content boxes
doubleBoxSize(page, "/MediaBox");
doubleBoxSize(page, "/CropBox");
doubleBoxSize(page, "/BleedBox");
doubleBoxSize(page, "/TrimBox");
doubleBoxSize(page, "/ArtBox");
}
// Write out a new file
QPDFWriter w(qpdf, outfilename);
if (QUtil::get_env("IN_TESTSUITE"))
{
// For the test suite, uncompress streams and use static
// IDs.
w.setStaticID(true);
w.setStreamDataMode(qpdf_s_uncompress);
}
w.write();
std::cout << whoami << ": new file written to " << outfilename
<< std::endl;
}
catch (std::exception &e)
{
std::cerr << whoami << " processing file " << infilename << ": "
<< e.what() << std::endl;
exit(2);
}
return 0;
}

View File

@ -0,0 +1,31 @@
#!/usr/bin/env perl
require 5.008;
BEGIN { $^W = 1; }
use strict;
chdir("double-page-size") or die "chdir testdir failed: $!\n";
require TestDriver;
my $td = new TestDriver('double-page-size');
cleanup();
$td->runtest("double page size",
{$td->COMMAND => "double-page-size in.pdf a.pdf"},
{$td->STRING => "double-page-size: new file written to a.pdf\n",
$td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->runtest("check output",
{$td->FILE => "a.pdf"},
{$td->FILE => "out.pdf"});
cleanup();
$td->report(2);
sub cleanup
{
unlink 'a.pdf';
}

View File

@ -0,0 +1,55 @@
%PDF-1.3
%¿÷¢þ
1 0 obj
<< /Pages 2 0 R /Type /Catalog >>
endobj
2 0 obj
<< /Count 2 /Kids [ 3 0 R 4 0 R ] /Type /Pages >>
endobj
3 0 obj
<< /Contents 5 0 R /MediaBox [ 0 0 612 792 ] /Parent 2 0 R /Resources << /Font << /F1 6 0 R >> /ProcSet 7 0 R >> /Type /Page >>
endobj
4 0 obj
<< /Contents 8 0 R /MediaBox [ 0 0 612 792 ] /Parent 2 0 R /Resources << /Font << /F1 6 0 R >> /ProcSet 7 0 R >> /Type /Page >>
endobj
5 0 obj
<< /Length 44 >>
stream
BT
/F1 24 Tf
72 720 Td
(Potato) Tj
ET
endstream
endobj
6 0 obj
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
endobj
7 0 obj
[ /PDF /Text ]
endobj
8 0 obj
<< /Length 43 >>
stream
BT
/F1 24 Tf
72 720 Td
(Salad) Tj
ET
endstream
endobj
xref
0 9
0000000000 65535 f
0000000015 00000 n
0000000064 00000 n
0000000129 00000 n
0000000272 00000 n
0000000415 00000 n
0000000508 00000 n
0000000615 00000 n
0000000645 00000 n
trailer << /Root 1 0 R /Size 9 /ID [<071a6499182be9cfc990b11d0c4e5bc0><90dbb2f2f000af76d1107187b0e00349>] >>
startxref
737
%%EOF

View File

@ -0,0 +1,69 @@
%PDF-1.3
%¿÷¢þ
1 0 obj
<< /Pages 2 0 R /Type /Catalog >>
endobj
2 0 obj
<< /Count 2 /Kids [ 3 0 R 4 0 R ] /Type /Pages >>
endobj
3 0 obj
<< /Contents [ 5 0 R 6 0 R ] /MediaBox [ 0.00 0.00 1224.00 1584.00 ] /Parent 2 0 R /Resources << /Font << /F1 7 0 R >> /ProcSet 8 0 R >> /Type /Page >>
endobj
4 0 obj
<< /Contents [ 9 0 R 10 0 R ] /MediaBox [ 0.00 0.00 1224.00 1584.00 ] /Parent 2 0 R /Resources << /Font << /F1 7 0 R >> /ProcSet 8 0 R >> /Type /Page >>
endobj
5 0 obj
<< /Length 15 >>
stream
2 0 0 2 0 0 cm
endstream
endobj
6 0 obj
<< /Length 44 >>
stream
BT
/F1 24 Tf
72 720 Td
(Potato) Tj
ET
endstream
endobj
7 0 obj
<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
endobj
8 0 obj
[ /PDF /Text ]
endobj
9 0 obj
<< /Length 15 >>
stream
2 0 0 2 0 0 cm
endstream
endobj
10 0 obj
<< /Length 43 >>
stream
BT
/F1 24 Tf
72 720 Td
(Salad) Tj
ET
endstream
endobj
xref
0 11
0000000000 65535 f
0000000015 00000 n
0000000064 00000 n
0000000129 00000 n
0000000296 00000 n
0000000464 00000 n
0000000528 00000 n
0000000621 00000 n
0000000728 00000 n
0000000758 00000 n
0000000822 00000 n
trailer << /Root 1 0 R /Size 11 /ID [<071a6499182be9cfc990b11d0c4e5bc0><31415926535897932384626433832795>] >>
startxref
915
%%EOF