Back to... PDF Writer

Source file : pdf_out-images.adb



with GID;

with Ada.Exceptions,
     Ada.Unchecked_Deallocation;

package body PDF_Out.Images is

  procedure Image_ref (pdf : in out PDF_Out_Stream; file_name : String; image_index : out Positive) is

    procedure Insert (file_name : String; node : in out p_Dir_node) is
    begin
      if node = null then
        pdf.img_count := pdf.img_count + 1;
        node := new Dir_node'
          ((name_len          => file_name'Length,
             left              => null,
             right             => null,
             file_name         => file_name,
             image_index       => pdf.img_count,
             pdf_object_index  => 0,  --  0 = not yet insterted into the PDF stream
             local_resource    => True)
          );
          image_index := pdf.img_count;
      elsif file_name > node.file_name then
        Insert (file_name, node.right);
      elsif file_name < node.file_name then
        Insert (file_name, node.left);
      else
        --  Name found, image was already referenced (above in the document)
        image_index := node.image_index;
        node.local_resource := True;
      end if;
    end Insert;
  begin
    Insert (file_name, pdf.img_dir_tree);
  end Image_ref;

  function Get_pixel_dimensions (image_file_name : String) return Rectangle is
    use Ada.Streams.Stream_IO;
    file : File_Type;
    i : GID.Image_descriptor;
  begin
    Open (file, In_File, image_file_name);
    GID.Load_image_header (i, Stream (file).all, try_tga => False);
    Close (file);
    return (0.0, 0.0, Real (GID.Pixel_width (i)), Real (GID.Pixel_height (i)));
  end Get_pixel_dimensions;

  procedure Traverse_private (pdf : PDF_Out_Stream) is

    procedure Traverse (p : p_Dir_node) is
    begin
      if p /= null then
        Traverse (p.left);
        Action_private (p.all);
        Traverse (p.right);
      end if;
    end Traverse;

  begin
    Traverse (pdf.img_dir_tree);
  end Traverse_private;

  procedure Clear_image_directory (pdf : in out PDF_Out_Stream) is
    procedure Clear (p : in out p_Dir_node) is
      procedure Dispose is new Ada.Unchecked_Deallocation (Dir_node, p_Dir_node);
    begin
      if p /= null then
        Clear (p.left);
        Clear (p.right);
        Dispose (p);
      end if;
    end Clear;
  begin
    Clear (pdf.img_dir_tree);
  end Clear_image_directory;

  procedure Clear_local_resource_flag (dn : in out Dir_node) is
  begin
    dn.local_resource := False;
  end Clear_local_resource_flag;

  procedure Clear_local_resource_flags (pdf : PDF_Out_Stream) is
    procedure Traverse_and_clear is new Traverse_private (Clear_local_resource_flag);
  begin
    Traverse_and_clear (pdf);
  end Clear_local_resource_flags;

  procedure Insert_unloaded_local_images (pdf : in out PDF_Out_Stream) is

    procedure Insert_Image_as_XObject (file_name : String) is
      file_size : Natural;
      use Ada.Streams.Stream_IO;
      file : File_Type;
      i : GID.Image_descriptor;
      use GID;
    begin
      Open (file, In_File, file_name);
      file_size := Integer (Size (file));
      GID.Load_image_header (i, Stream (file).all, try_tga => False);
      Close (file);
      if GID.Format (i) /= GID.JPEG then
        Ada.Exceptions.Raise_Exception
          (Not_implemented'Identity,
           "So far only JPEG images can be inserted. This image is of type " &
           GID.Detailed_format (i) & ", file name = " & file_name);
      end if;
      New_object (pdf);
      WL (pdf,
        "<< /Type /XObject /Subtype /Image /Width " &
        Img (GID.Pixel_width (i)) & " /Height " & Img (GID.Pixel_height (i)) &
        " /ColorSpace /DeviceRGB /BitsPerComponent " & Img (GID.Bits_per_pixel (i) / 3) &
        " /Length " & Img (file_size) & " /Filter /DCTDecode >>"
      );
      WL (pdf, "stream");
      Copy_File (file_name, pdf.pdf_stream.all);
      WL (pdf, "");
      WL (pdf, "endstream");
      WL (pdf, "endobj");
    end Insert_Image_as_XObject;

    procedure Insert_unloaded_local_image (dn : in out Dir_node) is
    begin
      if dn.local_resource and then dn.pdf_object_index = 0 then
        Insert_Image_as_XObject (dn.file_name);
        dn.pdf_object_index := pdf.objects;
      end if;
    end Insert_unloaded_local_image;

    procedure Traverse_and_load is new Traverse_private (Insert_unloaded_local_image);

  begin
    Traverse_and_load (pdf);
  end Insert_unloaded_local_images;

end PDF_Out.Images;


Ada PDF Writer: Ada package for writing PDF files (.pdf). Ada programming.
Some news about Ada PDF Writer and other Ada projects on Gautier's blog.