def transform( self, object_to_transform: AnyPDFType, context: Optional[WriteTransformerContext] = None, ): """ This method writes a Stream to a byte stream """ assert context is not None assert context.destination is not None assert isinstance(object_to_transform, Stream) # avoid resolving objects twice object_ref: typing.Optional[ Reference] = object_to_transform.get_reference( ) # type: ignore [attr-defined] if object_ref is not None and object_ref in context.resolved_references: assert object_ref is not None assert object_ref.object_number is not None logger.debug( "skip writing object %d %d R (already resolved)" % (object_ref.object_number, object_ref.generation_number or 0)) return # start object if needed started_object = False if object_ref is not None: assert object_ref.object_number is not None if object_ref.object_number is not None and object_ref.byte_offset is None: started_object = True self.start_object(object_to_transform, context) context.resolved_references.append(object_ref) # build stream dictionary stream_dictionary = Dictionary() # objects to turn into reference queue: typing.List[AnyPDFType] = [] for k, v in object_to_transform.items(): if k in ["Bytes", "DecodedBytes"]: continue if (isinstance(v, Dictionary) or isinstance(v, List) or isinstance(v, Stream) ) and v.can_be_referenced(): # type: ignore [union-attr] stream_dictionary[k] = self.get_reference(v, context) queue.append(v) else: stream_dictionary[k] = v # if self.compression_level == 0, remove \Filter if context.compression_level == 0 and Name( "Filter") in stream_dictionary: stream_dictionary.pop(Name("Filter")) # handle compression if "DecodedBytes" in object_to_transform: if context.compression_level == 0: bts = object_to_transform["DecodedBytes"] else: bts = zlib.compress(object_to_transform["DecodedBytes"], context.compression_level) stream_dictionary[Name("Length")] = pDecimal(len(bts)) else: assert "Bytes" in object_to_transform bts = object_to_transform["Bytes"] # write stream dictionary self.get_root_transformer().transform(stream_dictionary, context) # write "stream" context.destination.write(bytes("stream\n", "latin1")) # write bytes context.destination.write(bts) # write "endstream" context.destination.write(bytes("\nendstream\n", "latin1")) # end object if needed if started_object: self.end_object(object_to_transform, context) for e in queue: self.get_root_transformer().transform(e, context)
def transform( self, object_to_transform: AnyPDFType, context: Optional[WriteTransformerContext] = None, ): """ This method writes a Dictionary to a byte stream """ assert isinstance(object_to_transform, Dictionary) assert context is not None assert context.destination is not None assert context.destination # avoid resolving objects twice object_ref: typing.Optional[ Reference] = object_to_transform.get_reference( ) # type: ignore [attr-defined] if object_ref is not None and object_ref in context.resolved_references: assert object_ref is not None assert object_ref.object_number is not None logger.debug( "skip writing object %d %d R (already resolved)" % (object_ref.object_number, object_ref.generation_number or 0)) return # output value out_value = Dictionary() # objects to turn into reference queue: typing.List[AnyPDFType] = [] for k, v in object_to_transform.items(): if (isinstance(v, Dictionary) or isinstance(v, List) or isinstance(v, Stream) or isinstance(v, Image) or isinstance(v, Element) ) and v.can_be_referenced(): # type: ignore [union-attr] out_value[k] = self.get_reference(v, context) queue.append(v) else: out_value[k] = v # start object if needed started_object = False if object_ref is not None: assert object_ref.object_number is not None if object_ref.object_number is not None and object_ref.byte_offset is None: started_object = True self.start_object(object_to_transform, context) context.resolved_references.append(object_ref) # write dictionary at current location context.destination.write(bytes("<<", "latin1")) N = len(out_value.items()) for i, (k, v) in enumerate(out_value.items()): self.get_root_transformer().transform(k, context) context.destination.write(bytes(" ", "latin1")) self.get_root_transformer().transform(v, context) if i != N - 1: context.destination.write(bytes(" ", "latin1")) context.destination.write(bytes(">>\n", "latin1")) # end object if needed if started_object: self.end_object(object_to_transform, context) for e in queue: self.get_root_transformer().transform(e, context) # return return out_value