Back to... PDF Writer

Source file : gid-decoding_bmp.adb



with GID.Buffering;                     use GID.Buffering;

package body GID.Decoding_BMP is

  procedure Load (image : in out Image_descriptor) is
    b01, b, br, bg, bb : U8 := 0;
    x, x_max, y : Natural;
    --
    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;
    full_opaque : constant Primary_color_range := Primary_color_range'Last;
    --
    procedure Pixel_with_palette is
    pragma Inline (Pixel_with_palette);
    begin
      case Primary_color_range'Modulus is
        when 256 =>
          Put_Pixel (
            Primary_color_range (image.palette (Integer (b)).red),
            Primary_color_range (image.palette (Integer (b)).green),
            Primary_color_range (image.palette (Integer (b)).blue),
            full_opaque
          );
        when 65_536 =>
          Put_Pixel (
            Times_257 (Primary_color_range (image.palette (Integer (b)).red)),
            Times_257 (Primary_color_range (image.palette (Integer (b)).green)),
            Times_257 (Primary_color_range (image.palette (Integer (b)).blue)),
            --  Times_257 makes max intensity FF go to FFFF
            full_opaque
          );
        when others =>
          raise invalid_primary_color_range with "BMP: color range not supported";
      end case;
    end Pixel_with_palette;
    --
    pair : Boolean;
    bit : Natural range 0 .. 7;
    --
    line_bits : constant Float := Float (image.width * Positive_32 (image.bits_per_pixel));
    padded_line_size : constant Positive := 4 * Integer (Float'Ceiling (line_bits / 32.0));
    unpadded_line_size : constant Positive := Integer (Float'Ceiling (line_bits / 8.0));
    --  (in bytes)
  begin
    Attach_Stream (image.buffer, image.stream);
    y := 0;
    while y <= Integer (image.height) - 1 loop
      x := 0;
      x_max := Integer (image.width) - 1;
      case image.bits_per_pixel is
        when 1 => -- B/W
          bit := 0;
          Set_X_Y (x, y);
          while x <= x_max loop
            if bit = 0 then
              Get_Byte (image.buffer, b01);
            end if;
            b := (b01 and 16#80#) / 16#80#;
            Pixel_with_palette;
            b01 := b01 * 2; -- cannot overflow.
            if bit = 7 then
              bit := 0;
            else
              bit := bit + 1;
            end if;
            x := x + 1;
          end loop;
        when 4 => -- 16 colour image
          pair := True;
          Set_X_Y (x, y);
          while x <= x_max loop
            if pair then
              Get_Byte (image.buffer, b01);
              b := (b01 and 16#F0#) / 16#10#;
            else
              b := (b01 and 16#0F#);
            end if;
            pair := not pair;
            Pixel_with_palette;
            x := x + 1;
          end loop;
        when 8 => -- 256 colour image
          Set_X_Y (x, y);
          while x <= x_max loop
            Get_Byte (image.buffer, b);
            Pixel_with_palette;
            x := x + 1;
          end loop;
        when 24 => -- RGB, 256 colour per primary colour
          Set_X_Y (x, y);
          while x <= x_max loop
            Get_Byte (image.buffer, bb);
            Get_Byte (image.buffer, bg);
            Get_Byte (image.buffer, br);
            case Primary_color_range'Modulus is
              when 256 =>
                Put_Pixel (
                  Primary_color_range (br),
                  Primary_color_range (bg),
                  Primary_color_range (bb),
                  full_opaque
                );
              when 65_536 =>
                Put_Pixel (
                  Times_257 (Primary_color_range (br)),
                  Times_257 (Primary_color_range (bg)),
                  Times_257 (Primary_color_range (bb)),
                  --  Times_257 makes max intensity FF go to FFFF
                  full_opaque
                );
              when others =>
                raise invalid_primary_color_range with "BMP: color range not supported";
            end case;
            x := x + 1;
          end loop;
        when others =>
          null;
      end case;
      for i in unpadded_line_size + 1 .. padded_line_size loop
        Get_Byte (image.buffer, b);
      end loop;
      y := y + 1;
      Feedback ((y * 100) / Integer (image.height));
    end loop;
  end Load;

end GID.Decoding_BMP;


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.