mirror of
https://github.com/qpdf/qpdf.git
synced 2025-01-03 07:12:28 +00:00
QPDFPageObjectHelper::getPageImages: support form XObjects
This commit is contained in:
parent
1562d34c09
commit
e7a8554563
@ -32,6 +32,10 @@
|
||||
|
||||
class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
// This is a helper class for page objects, but as of qpdf 10.1,
|
||||
// many of the methods also work for form XObjects. When this is
|
||||
// the case, it is noted in the comment.
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFPageObjectHelper(QPDFObjectHandle);
|
||||
@ -40,14 +44,15 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
}
|
||||
|
||||
// Return the effective value of this attribute for the page. If
|
||||
// the requested attribute is not present on the page but is
|
||||
// Works with pages and form XObjects. Return the effective value
|
||||
// of this attribute for the page/form XObject. For pages, if the
|
||||
// requested attribute is not present on the page but is
|
||||
// inheritable, look up through the page's ancestors in the page
|
||||
// tree. If copy_if_shared is true, then this method will replace
|
||||
// the attribute with a shallow copy if it is in indirect or
|
||||
// inherited and return the copy. You should do this if you are
|
||||
// going to modify the returned object and want the modifications
|
||||
// to apply to the current page only.
|
||||
// to apply to the current page/form XObject only.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle
|
||||
getAttribute(std::string const& name, bool copy_if_shared);
|
||||
@ -70,7 +75,8 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
// Returns an empty map if there are no images or no resources.
|
||||
// Prior to qpdf 8.4.0, this function did not support inherited
|
||||
// resources, but it does now. Return value is a map from XObject
|
||||
// name to the image object, which is always a stream.
|
||||
// name to the image object, which is always a stream. Works with
|
||||
// form XObjects as well as pages.
|
||||
QPDF_DLL
|
||||
std::map<std::string, QPDFObjectHandle> getPageImages();
|
||||
|
||||
|
@ -1320,35 +1320,7 @@ QPDFObjectHandle::getGeneration() const
|
||||
std::map<std::string, QPDFObjectHandle>
|
||||
QPDFObjectHandle::getPageImages()
|
||||
{
|
||||
std::map<std::string, QPDFObjectHandle> result;
|
||||
QPDFObjectHandle resources =
|
||||
QPDFPageObjectHelper(*this).getAttribute("/Resources", false);
|
||||
if (resources.isDictionary())
|
||||
{
|
||||
if (resources.hasKey("/XObject"))
|
||||
{
|
||||
QPDFObjectHandle xobject = resources.getKey("/XObject");
|
||||
std::set<std::string> keys = xobject.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
std::string key = (*iter);
|
||||
QPDFObjectHandle value = xobject.getKey(key);
|
||||
if (value.isStream())
|
||||
{
|
||||
QPDFObjectHandle dict = value.getDict();
|
||||
if (dict.hasKey("/Subtype") &&
|
||||
(dict.getKey("/Subtype").getName() == "/Image") &&
|
||||
(! dict.hasKey("/ImageMask")))
|
||||
{
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return QPDFPageObjectHelper(*this).getPageImages();
|
||||
}
|
||||
|
||||
std::vector<QPDFObjectHandle>
|
||||
|
@ -314,33 +314,46 @@ QPDFObjectHandle
|
||||
QPDFPageObjectHelper::getAttribute(std::string const& name,
|
||||
bool copy_if_shared)
|
||||
{
|
||||
bool inheritable = ((name == "/MediaBox") || (name == "/CropBox") ||
|
||||
(name == "/Resources") || (name == "/Rotate"));
|
||||
|
||||
QPDFObjectHandle node = this->oh;
|
||||
QPDFObjectHandle result(node.getKey(name));
|
||||
std::set<QPDFObjGen> seen;
|
||||
QPDFObjectHandle result;
|
||||
QPDFObjectHandle dict;
|
||||
bool is_form_xobject = this->oh.isFormXObject();
|
||||
bool inherited = false;
|
||||
while (inheritable && result.isNull() && node.hasKey("/Parent"))
|
||||
if (is_form_xobject)
|
||||
{
|
||||
seen.insert(node.getObjGen());
|
||||
node = node.getKey("/Parent");
|
||||
if (seen.count(node.getObjGen()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
dict = this->oh.getDict();
|
||||
result = dict.getKey(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
dict = this->oh;
|
||||
bool inheritable = ((name == "/MediaBox") || (name == "/CropBox") ||
|
||||
(name == "/Resources") || (name == "/Rotate"));
|
||||
|
||||
QPDFObjectHandle node = dict;
|
||||
result = node.getKey(name);
|
||||
if (! result.isNull())
|
||||
std::set<QPDFObjGen> seen;
|
||||
while (inheritable && result.isNull() && node.hasKey("/Parent"))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFPageObjectHelper non-trivial inheritance");
|
||||
inherited = true;
|
||||
seen.insert(node.getObjGen());
|
||||
node = node.getKey("/Parent");
|
||||
if (seen.count(node.getObjGen()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
result = node.getKey(name);
|
||||
if (! result.isNull())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFPageObjectHelper non-trivial inheritance");
|
||||
inherited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (copy_if_shared && (inherited || result.isIndirect()))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFPageObjectHelper copy shared attribute");
|
||||
QTC::TC("qpdf", "QPDFPageObjectHelper copy shared attribute",
|
||||
is_form_xobject ? 0 : 1);
|
||||
result = result.shallowCopy();
|
||||
this->oh.replaceKey(name, result);
|
||||
dict.replaceKey(name, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -376,7 +389,34 @@ QPDFPageObjectHelper::getMediaBox(bool copy_if_shared)
|
||||
std::map<std::string, QPDFObjectHandle>
|
||||
QPDFPageObjectHelper::getPageImages()
|
||||
{
|
||||
return this->oh.getPageImages();
|
||||
std::map<std::string, QPDFObjectHandle> result;
|
||||
QPDFObjectHandle resources = getAttribute("/Resources", false);
|
||||
if (resources.isDictionary())
|
||||
{
|
||||
if (resources.hasKey("/XObject"))
|
||||
{
|
||||
QPDFObjectHandle xobject = resources.getKey("/XObject");
|
||||
std::set<std::string> keys = xobject.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
std::string key = (*iter);
|
||||
QPDFObjectHandle value = xobject.getKey(key);
|
||||
if (value.isStream())
|
||||
{
|
||||
QPDFObjectHandle dict = value.getDict();
|
||||
if (dict.hasKey("/Subtype") &&
|
||||
(dict.getKey("/Subtype").getName() == "/Image") &&
|
||||
(! dict.hasKey("/ImageMask")))
|
||||
{
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
@ -571,13 +611,8 @@ QPDFPageObjectHelper::removeUnreferencedResourcesHelper(
|
||||
removeUnreferencedResourcesHelper(
|
||||
resource.getDict(), seen,
|
||||
[&resource]() {
|
||||
auto result = resource.getDict().getKey("/Resources");
|
||||
if (result.isDictionary())
|
||||
{
|
||||
result = result.shallowCopy();
|
||||
resource.getDict().replaceKey("/Resources", result);
|
||||
}
|
||||
return result;
|
||||
return QPDFPageObjectHelper(resource)
|
||||
.getAttribute("/Resources", true);
|
||||
},
|
||||
[&resource](QPDFObjectHandle::TokenFilter* f) {
|
||||
resource.filterAsContents(f);
|
||||
|
@ -422,7 +422,7 @@ QPDFFormFieldObjectHelper create AP from scratch 0
|
||||
QPDFFormFieldObjectHelper replaced BMC at EOF 0
|
||||
QPDFFormFieldObjectHelper fallback Tf 0
|
||||
QPDFPageObjectHelper non-trivial inheritance 0
|
||||
QPDFPageObjectHelper copy shared attribute 0
|
||||
QPDFPageObjectHelper copy shared attribute 1
|
||||
qpdf from_nr from repeat_nr 0
|
||||
QPDF resolve duplicated page object 0
|
||||
QPDF handle direct page object 0
|
||||
|
Loading…
Reference in New Issue
Block a user