Hi,
Thanks Albert for committing my previous patches.
On Saturday 01 October 2011, Albert Astals Cid wrote:
> A Dijous, 29 de setembre de 2011, vàreu escriure:
> > I also want to be able to save a single page from a PDF file in a new PDF
> > file. I guess the cleanest way to do this will be to add a function
> > "savePageAs(const QString &exportFilePath, int page)" to
> > Poppler::Document. Is that OK?
>
> No, please add a void setPageList(const QList<int> &pageList); like we have
> in PSConverter.
>
> Also it would be great if instead of sending the patches to me directly you
> uses the poppler mailing list at
> http://lists.freedesktop.org/mailman/listinfo/poppler
Following your request, I implemented setPageList(...) in PDFConverter. In
order to have a similar behavior as in PSConverter (i.e. saving the selected
pages to one file, and not to a file per page), I also added a function
savePagesAs(OutStream *outStr, std::vector<int> pagesList); to PDFDoc. Since I
have no PDF-hacking experience, I copied the code from pdfunite.cc and adapted
it to the new situation. So I hope that the code is decent. At least it works
perfectly on my PDF files.
Best regards,
Glad
--
Truth is stranger than fiction, but it is because fiction is obliged
to stick to possibilities. Truth isn't.
-- Mark Twain
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 01d2759..0b958e5 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -689,6 +689,98 @@ int PDFDoc::savePageAs(GooString *name, int pageNo)
return errNone;
}
+int PDFDoc::savePagesAs(OutStream *outStr, std::vector<int> pagesList)
+{
+ int objectsCount = 0;
+ Guint numOffset = 0;
+ std::vector<Object> pages;
+ std::vector<Guint> offsets;
+ XRef *yRef, *countRef;
+ int rootNum;
+
+ for (int i = 0; i < (int) pagesList.size(); ++i) {
+ if (pagesList[i] < 1 || pagesList[i] > getNumPages()) {
+ error(-1, "Illegal pageNo: %d(%d)", pagesList[i], getNumPages());
+ return errBadPageNum;
+ }
+ }
+
+ yRef = new XRef();
+ countRef = new XRef();
+ yRef->add(0, 65535, 0, gFalse);
+ PDFDoc::writeHeader(outStr, getPDFMajorVersion(), getPDFMinorVersion());
+
+ for (int i = 0; i < (int) pagesList.size(); ++i) {
+ PDFRectangle *cropBox = NULL;
+ if (getCatalog()->getPage(pagesList[i])->isCropped())
+ cropBox = getCatalog()->getPage(pagesList[i])->getCropBox();
+ replacePageDict(pagesList[i],
+ getCatalog()->getPage(pagesList[i])->getRotate(),
+ getCatalog()->getPage(pagesList[i])->getMediaBox(), cropBox, NULL);
+ Ref *refPage = getCatalog()->getPageRef(pagesList[i]);
+ Object page;
+ getXRef()->fetch(refPage->num, refPage->gen, &page);
+ pages.push_back(page);
+ offsets.push_back(numOffset);
+ Dict *pageDict = page.getDict();
+ markPageObjects(pageDict, yRef, countRef, numOffset);
+ objectsCount += writePageObjects(outStr, yRef, numOffset);
+ numOffset = yRef->getNumObjects() + 1;
+ }
+
+ rootNum = yRef->getNumObjects() + 1;
+ yRef->add(rootNum, 0, outStr->getPos(), gTrue);
+ outStr->printf("%d 0 obj\n", rootNum);
+ outStr->printf("<< /Type /Catalog /Pages %d 0 R", rootNum + 1);
+ outStr->printf(">>\nendobj\n");
+ objectsCount++;
+
+ yRef->add(rootNum + 1, 0, outStr->getPos(), gTrue);
+ outStr->printf("%d 0 obj\n", rootNum + 1);
+ outStr->printf("<< /Type /Pages /Kids [");
+ for (int j = 0; j < (int) pages.size(); ++j)
+ outStr->printf(" %d 0 R", rootNum + j + 2);
+ outStr->printf(" ] /Count %d >>\nendobj\n", pages.size());
+ objectsCount++;
+
+ for (int i = 0; i < (int) pages.size(); ++i) {
+ yRef->add(rootNum + i + 2, 0, outStr->getPos(), gTrue);
+ outStr->printf("%d 0 obj\n", rootNum + i + 2);
+ outStr->printf("<< ");
+ Dict *pageDict = pages[i].getDict();
+ for (int j = 0; j < pageDict->getLength(); j++) {
+ if (j > 0)
+ outStr->printf(" ");
+ const char *key = pageDict->getKey(j);
+ Object value;
+ pageDict->getValNF(j, &value);
+ if (strcmp(key, "Parent") == 0) {
+ outStr->printf("/Parent %d 0 R", rootNum + 1);
+ } else {
+ outStr->printf("/%s ", key);
+ PDFDoc::writeObject(&value, NULL, outStr, yRef, offsets[i]);
+ }
+ value.free();
+ }
+ outStr->printf(" >>\nendobj\n");
+ objectsCount++;
+ }
+ Guint uxrefOffset = outStr->getPos();
+ yRef->writeToFile(outStr, gFalse /* do not write unnecessary entries */ );
+
+ Ref ref;
+ ref.num = rootNum;
+ ref.gen = 0;
+ PDFDoc::writeTrailer(uxrefOffset, objectsCount, outStr, (GBool) gFalse, 0,
+ &ref, yRef, getFileName()->getCString(), outStr->getPos());
+
+ delete yRef;
+ delete countRef;
+ for (int j = 0; j < (int) pages.size (); ++j)
+ pages[j].free();
+ return errNone;
+}
+
int PDFDoc::saveAs(GooString *name, PDFWriteMode mode) {
FILE *f;
OutStream *outStr;
diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h
index 92cee78..e5619de 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -222,6 +222,8 @@ public:
// Save one page with another name.
int savePageAs(GooString *name, int pageNo);
+ // Save multiple pages in the given output stream.
+ int savePagesAs(OutStream *outStr, std::vector<int> pagesList);
// Save this file with another name.
int saveAs(GooString *name, PDFWriteMode mode=writeStandard);
// Save this file in the given output stream.
diff --git a/qt4/src/poppler-pdf-converter.cc b/qt4/src/poppler-pdf-converter.cc
index 9699b75..887365b 100644
--- a/qt4/src/poppler-pdf-converter.cc
+++ b/qt4/src/poppler-pdf-converter.cc
@@ -34,6 +34,7 @@ class PDFConverterPrivate : public BaseConverterPrivate
public:
PDFConverterPrivate();
+ QList<int> pageList;
PDFConverter::PDFOptions opts;
};
@@ -66,6 +67,12 @@ PDFConverter::PDFOptions PDFConverter::pdfOptions() const
return d->opts;
}
+void PDFConverter::setPageList(const QList<int> &pageList)
+{
+ Q_D(PDFConverter);
+ d->pageList = pageList;
+}
+
bool PDFConverter::convert()
{
Q_D(PDFConverter);
@@ -90,7 +97,14 @@ bool PDFConverter::convert()
int errorCode = errNone;
QIODeviceOutStream stream(dev);
- if (d->opts & WithChanges)
+ if (!d->pageList.isEmpty())
+ {
+ std::vector<int> pageList;
+ for (int i = 0; i < d->pageList.size(); ++i)
+ pageList.push_back(d->pageList.at(i));
+ errorCode = d->document->doc->savePagesAs(&stream, pageList);
+ }
+ else if (d->opts & WithChanges)
{
errorCode = d->document->doc->saveAs(&stream);
}
diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h
index 637b69f..82bc826 100644
--- a/qt4/src/poppler-qt4.h
+++ b/qt4/src/poppler-qt4.h
@@ -1566,6 +1566,12 @@ height = dummy.height();
bool convert();
+ /**
+ Sets the list of pages to print. If the list of pages
+ is empty, all pages are printed.
+ */
+ void setPageList(const QList<int> &pageList);
+
private:
Q_DECLARE_PRIVATE(PDFConverter)
Q_DISABLE_COPY(PDFConverter)
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler