def test_image_direct_embed(infile): img = Image.open(os.path.join(IMG_DIR, infile)) w = IncrementalPdfFileWriter(BytesIO(MINIMAL)) image_ref = images.pil_image(img, w) page_ref, resources = w.find_page_for_modification(0) resources[pdf_name('/XObject')] = generic.DictionaryObject( {pdf_name('/Img'): image_ref}) w.update_container(resources) content_stream: generic.StreamObject = page_ref.get_object()['/Contents'] content_stream._data = \ content_stream.data + b' q 50 0 0 50 5 5 cm /Img Do Q' content_stream._encoded_data = None w.update_container(content_stream) w.write_in_place() # TODO flatten and do a visual comparison image_obj = image_ref.get_object() if 'indexed' in infile: assert '/SMask' not in image_obj else: assert '/SMask' in image_obj
def append_signature_field(pdf_out: IncrementalPdfFileWriter, sig_field_spec: SigFieldSpec): """ Append signature fields to a PDF file. :param pdf_out: Incremental writer to house the objects. :param sig_field_spec: A :class:`.SigFieldSpec` object describing the signature field to add. """ root = pdf_out.root page_ref = pdf_out.find_page_for_modification(sig_field_spec.on_page)[0] # use default appearance field_created, sig_field_ref = _prepare_sig_field( sig_field_spec.sig_field_name, root, update_writer=pdf_out, existing_fields_only=False, box=sig_field_spec.box, include_on_page=page_ref, lock_sig_flags=False) if not field_created: raise PdfWriteError('Signature field with name %s already exists.' % sig_field_spec.sig_field_name) sig_field = sig_field_ref.get_object() if sig_field_spec.seed_value_dict is not None: # /SV must be an indirect reference as per the spec sv_ref = pdf_out.add_object( sig_field_spec.seed_value_dict.as_pdf_object()) sig_field[pdf_name('/SV')] = sv_ref lock = sig_field_spec.format_lock_dictionary() if lock is not None: sig_field[pdf_name('/Lock')] = pdf_out.add_object(lock)
def _prepare_sig_field(sig_field_name, root, update_writer: IncrementalPdfFileWriter, existing_fields_only=False, lock_sig_flags=True, **kwargs): """ Returns a tuple of a boolean and a reference to a signature field. The boolean is ``True`` if the field was created, and ``False`` otherwise. """ if sig_field_name is None: # pragma: nocover raise ValueError try: form = root['/AcroForm'] try: fields = form['/Fields'] except KeyError: raise ValueError('/AcroForm has no /Fields') candidates = enumerate_sig_fields_in(fields, with_name=sig_field_name) sig_field_ref = None try: field_name, value, sig_field_ref = next(candidates) if value is not None: raise SigningError( 'Signature field with name %s appears to be filled already.' % sig_field_name) except StopIteration: if existing_fields_only: raise SigningError( 'No empty signature field with name %s found.' % sig_field_name) form_created = False except KeyError: # we have to create the form if existing_fields_only: raise SigningError('This file does not contain a form.') # no AcroForm present, so create one form = generic.DictionaryObject() root[pdf_name('/AcroForm')] = update_writer.add_object(form) fields = generic.ArrayObject() form[pdf_name('/Fields')] = fields # now we need to mark the root as updated update_writer.update_root() form_created = True sig_field_ref = None if sig_field_ref is not None: return False, sig_field_ref if '.' in sig_field_name: raise NotImplementedError( "Creating fields deep in the form hierarchy is not supported" "right now.") # no signature field exists, so create one # default: grab a reference to the first page page_ref = update_writer.find_page_for_modification(0)[0] sig_form_kwargs = {'include_on_page': page_ref} sig_form_kwargs.update(**kwargs) sig_field = SignatureFormField(sig_field_name, writer=update_writer, **sig_form_kwargs) sig_field_ref = sig_field.reference fields.append(sig_field_ref) # make sure /SigFlags is present. If not, create it sig_flags = 3 if lock_sig_flags else 1 form.setdefault(pdf_name('/SigFlags'), generic.NumberObject(sig_flags)) # if a field was added to an existing form, register an extra update if not form_created: update_writer.update_container(fields) return True, sig_field_ref