Back to... PDF Writer

Source file : gid-decoding_pnm.adb



with GID.Buffering;                     use GID.Buffering;

with Ada.Strings.Unbounded;             use Ada.Strings.Unbounded;

package body GID.Decoding_PNM is

  ----------
  -- Load --
  ----------

  procedure Load (image : in out Image_descriptor) is

    procedure Row_start (y : Natural) is
    begin
      Set_X_Y (0, Integer (image.height) - 1 - y);
    end Row_start;

    type Pixel is record
      color : RGB_Color_8_Bit;
      alpha : U8;
    end record;

    pix : Pixel;

    procedure Output_Pixel is
    pragma Inline (Output_Pixel);
      function Times_257 (x : Primary_color_range) return Primary_color_range is
      pragma Inline (Times_257);
      begin
        return 16 * (16 * x) + x;  --  this is 257 * x, = 16#0101# * x
        --  Numbers 8-bit -> no OA warning at instanciation. Returns x if type Primary_color_range is mod 2**8.
      end Times_257;
    begin
      case Primary_color_range'Modulus is
        when 256 =>
          Put_Pixel (
            Primary_color_range (pix.color.red),
            Primary_color_range (pix.color.green),
            Primary_color_range (pix.color.blue),
            Primary_color_range (pix.alpha)
          );
        when 65_536 =>
          Put_Pixel (
            Times_257 (Primary_color_range (pix.color.red)),
            Times_257 (Primary_color_range (pix.color.green)),
            Times_257 (Primary_color_range (pix.color.blue)),
            Times_257 (Primary_color_range (pix.alpha))
            --  Times_257 makes max intensity FF go to FFFF
          );
        when others =>
          raise invalid_primary_color_range with "PNM: color range not supported";
      end case;
    end Output_Pixel;

    ----------
    --  P1  --
    ----------

    procedure Get_Mono_Text_Picture is
    begin
      for y in 0 .. Integer (image.height) - 1 loop
        Row_start (y);
        for x in 0 .. Integer (image.width) - 1 loop
          pix.color.red   := U8 ((1 - Get_Integer (image.stream, single_char => True)) * 255);
          pix.color.green := pix.color.red;
          pix.color.blue  := pix.color.red;
          Output_Pixel;
        end loop;
        Feedback (((y + 1) * 100) / Integer (image.height));
      end loop;
    end Get_Mono_Text_Picture;

    ----------
    --  P2  --
    ----------

    procedure Get_Grey_Text_Picture is
    begin
      for y in 0 .. Integer (image.height) - 1 loop
        Row_start (y);
        for x in 0 .. Integer (image.width) - 1 loop
          pix.color.red   := U8 (Get_Integer (image.stream));
          pix.color.green := pix.color.red;
          pix.color.blue  := pix.color.red;
          Output_Pixel;
        end loop;
        Feedback (((y + 1) * 100) / Integer (image.height));
      end loop;
    end Get_Grey_Text_Picture;

    ----------
    --  P3  --
    ----------

    procedure Get_RGB_Text_Picture is
    begin
      for y in 0 .. Integer (image.height) - 1 loop
        Row_start (y);
        for x in 0 .. Integer (image.width) - 1 loop
          pix.color.red   := U8 (Get_Integer (image.stream));
          pix.color.green := U8 (Get_Integer (image.stream));
          pix.color.blue  := U8 (Get_Integer (image.stream));
          Output_Pixel;
        end loop;
        Feedback (((y + 1) * 100) / Integer (image.height));
      end loop;
    end Get_RGB_Text_Picture;

    ----------
    --  P4  --
    ----------

    procedure Get_Mono_Binary_Picture is
      bbf : U8;  --  Bit buffer
    begin
      for y in 0 .. Integer (image.height) - 1 loop
        Row_start (y);
        for x in 0 .. Integer (image.width) - 1 loop
          if x mod 8 = 0 then
            Get_Byte (image.buffer, bbf);
          end if;
          pix.color.red   := 255 * (1 - Shift_Right (bbf, 7));
          bbf := bbf * 2;
          pix.color.green := pix.color.red;
          pix.color.blue  := pix.color.red;
          Output_Pixel;
        end loop;
        Feedback (((y + 1) * 100) / Integer (image.height));
      end loop;
    end Get_Mono_Binary_Picture;

    ----------
    --  P5  --
    ----------

    procedure Get_Grey_Binary_Picture is
    begin
      for y in 0 .. Integer (image.height) - 1 loop
        Row_start (y);
        for x in 0 .. Integer (image.width) - 1 loop
          Get_Byte (image.buffer, pix.color.red);
          pix.color.green := pix.color.red;
          pix.color.blue  := pix.color.red;
          Output_Pixel;
        end loop;
        Feedback (((y + 1) * 100) / Integer (image.height));
      end loop;
    end Get_Grey_Binary_Picture;

    ----------
    --  P6  --
    ----------

    procedure Get_RGB_Binary_Picture is
    begin
      for y in 0 .. Integer (image.height) - 1 loop
        Row_start (y);
        for x in 0 .. Integer (image.width) - 1 loop
          Get_Byte (image.buffer, pix.color.red);
          Get_Byte (image.buffer, pix.color.green);
          Get_Byte (image.buffer, pix.color.blue);
          Output_Pixel;
        end loop;
        Feedback (((y + 1) * 100) / Integer (image.height));
      end loop;
    end Get_RGB_Binary_Picture;

  begin
    pix.alpha := 255; -- opaque is default
    if image.subformat_id >= 4 then  --  Binary
      Attach_Stream (image.buffer, image.stream);
    end if;
    --
    case image.subformat_id is
      when 1 =>
        Get_Mono_Text_Picture;
      when 2 =>
        Get_Grey_Text_Picture;
      when 3 =>
        Get_RGB_Text_Picture;
      when 4 =>
        Get_Mono_Binary_Picture;
      when 5 =>
        Get_Grey_Binary_Picture;
      when 6 =>
        Get_RGB_Binary_Picture;
      when others => null;
    end case;
  end Load;

  function Get_Token (
    stream      : Stream_Access;
    needs_EOL   : Boolean := False;
    single_char : Boolean := False
  )
  return String
  is
    c : Character;
    res : Unbounded_String;
    procedure Skip_comment is
    begin
      if c = '#' then
        loop
          Character'Read (stream, c);
          exit when c = ASCII.LF;
        end loop;
      end if;
    end Skip_comment;
  begin
    loop
      Character'Read (stream, c);
      Skip_comment;
      exit when c > ' ';
    end loop;
    loop
      if c > ' ' then
        res := res & c;
      end if;
      if single_char then
        exit when Length (res) = 1;
      end if;
      Character'Read (stream, c);
      Skip_comment;
      if needs_EOL then
        exit when c = ASCII.LF;
      else
        exit when c <= ' ';
      end if;
    end loop;
    return To_String (res);
  end Get_Token;

  function Get_Integer (
    stream      : Stream_Access;
    needs_EOL   : Boolean := False;
    single_char : Boolean := False
  )
  return Integer
  is
  begin
    return Integer'Value (Get_Token (stream, needs_EOL, single_char));
  end Get_Integer;

  function Get_Positive_32 (
    stream      : Stream_Access;
    needs_EOL   : Boolean := False;
    single_char : Boolean := False
  )
  return Positive_32
  is
  begin
    return Positive_32'Value (Get_Token (stream, needs_EOL, single_char));
  end Get_Positive_32;

end GID.Decoding_PNM;


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.