Source file : gid-decoding_tga.adb
with GID.Buffering; use GID.Buffering;
with GID.Color_tables;
package body GID.Decoding_TGA is
----------
-- Load --
----------
procedure Load (image : in out Image_descriptor) is
procedure Row_start (y : Natural) is
begin
if image.top_first then
Set_X_Y (0, Integer (image.height) - 1 - y);
else
Set_X_Y (0, y);
end if;
end Row_start;
-- Run Length Encoding --
RLE_pixels_remaining : Natural := 0;
is_run_packet : Boolean;
type Pixel is record
color : RGB_Color_8_Bit;
alpha : U8;
end record;
pix, pix_mem : Pixel;
generic
bpp : Positive;
pal : Boolean;
procedure Get_pixel;
pragma Inline (Get_pixel);
--
procedure Get_pixel is
idx : Natural;
p1, p2, c, d : U8;
begin
if pal then
if image.palette'Length <= 256 then
Get_Byte (image.buffer, p1);
idx := Natural (p1);
else
Get_Byte (image.buffer, p1);
Get_Byte (image.buffer, p2);
idx := Natural (p1) + Natural (p2) * 256;
end if;
idx := idx + image.palette'First;
pix.color := image.palette (idx);
else
case bpp is
when 32 => -- BGRA
Get_Byte (image.buffer, pix.color.blue);
Get_Byte (image.buffer, pix.color.green);
Get_Byte (image.buffer, pix.color.red);
Get_Byte (image.buffer, pix.alpha);
when 24 => -- BGR
Get_Byte (image.buffer, pix.color.blue);
Get_Byte (image.buffer, pix.color.green);
Get_Byte (image.buffer, pix.color.red);
when 16 | 15 => -- 5 bit per channel
Get_Byte (image.buffer, c);
Get_Byte (image.buffer, d);
Color_tables.Convert (c, d, pix.color);
if bpp = 16 then
pix.alpha := U8 ((U16 (c and 128) * 255) / 128);
end if;
when 8 => -- Gray
Get_Byte (image.buffer, pix.color.green);
pix.color.red := pix.color.green;
pix.color.blue := pix.color.green;
when others =>
null;
end case;
end if;
end Get_pixel;
generic
rle_bpp : Positive;
rle_pal : Boolean;
procedure RLE_Pixel;
pragma Inline (RLE_Pixel);
--
procedure RLE_Pixel is
tmp : U8;
procedure Get_pixel_for_RLE is new Get_pixel (rle_bpp, rle_pal);
begin
if RLE_pixels_remaining = 0 then -- load RLE code
Get_Byte (image.buffer, tmp);
Get_pixel_for_RLE;
RLE_pixels_remaining := U8'Pos (tmp and 16#7F#);
is_run_packet := (tmp and 16#80#) /= 0;
if is_run_packet then
pix_mem := pix;
end if;
else
if is_run_packet then
pix := pix_mem;
else
Get_pixel_for_RLE;
end if;
RLE_pixels_remaining := RLE_pixels_remaining - 1;
end if;
end RLE_Pixel;
procedure RLE_pixel_32 is new RLE_Pixel (32, False);
procedure RLE_pixel_24 is new RLE_Pixel (24, False);
procedure RLE_pixel_16 is new RLE_Pixel (16, False);
procedure RLE_pixel_15 is new RLE_Pixel (15, False);
procedure RLE_pixel_8 is new RLE_Pixel (8, False);
procedure RLE_pixel_palette is new RLE_Pixel (1, True); -- 1: dummy
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 "TGA: color range not supported";
end case;
end Output_Pixel;
procedure Get_RGBA is -- 32 bits : R, G, B, A use 8 bits each.
procedure Get_pixel_32 is new Get_pixel (32, False);
begin
for y in 0 .. Integer (image.height) - 1 loop
Row_start (y);
for x in 0 .. Integer (image.width) - 1 loop
Get_pixel_32;
Output_Pixel;
end loop;
Feedback (((y + 1) * 100) / Integer (image.height));
end loop;
end Get_RGBA;
procedure Get_RGB is -- 24 bits : R, G, B use 8 bits each.
procedure Get_pixel_24 is new Get_pixel (24, False);
begin
for y in 0 .. Integer (image.height) - 1 loop
Row_start (y);
for x in 0 .. Integer (image.width) - 1 loop
Get_pixel_24;
Output_Pixel;
end loop;
Feedback (((y + 1) * 100) / Integer (image.height));
end loop;
end Get_RGB;
procedure Get_16 is -- 16 bits
procedure Get_pixel_16 is new Get_pixel (16, False);
begin
for y in 0 .. Integer (image.height) - 1 loop
Row_start (y);
for x in 0 .. Integer (image.width) - 1 loop
Get_pixel_16;
Output_Pixel;
end loop;
Feedback (((y + 1) * 100) / Integer (image.height));
end loop;
end Get_16;
procedure Get_15 is -- 15 bits
procedure Get_pixel_15 is new Get_pixel (15, False);
begin
for y in 0 .. Integer (image.height) - 1 loop
Row_start (y);
for x in 0 .. Integer (image.width) - 1 loop
Get_pixel_15;
Output_Pixel;
end loop;
Feedback (((y + 1) * 100) / Integer (image.height));
end loop;
end Get_15;
procedure Get_Gray is
procedure Get_pixel_8 is new Get_pixel (8, False);
begin
for y in 0 .. Integer (image.height) - 1 loop
Row_start (y);
for x in 0 .. Integer (image.width) - 1 loop
Get_pixel_8;
Output_Pixel;
end loop;
Feedback (((y + 1) * 100) / Integer (image.height));
end loop;
end Get_Gray;
procedure Get_with_palette is
procedure Get_pixel_palette is new Get_pixel (1, True); -- 1: dummy
begin
for y in 0 .. Integer (image.height) - 1 loop
Row_start (y);
for x in 0 .. Integer (image.width) - 1 loop
Get_pixel_palette;
Output_Pixel;
end loop;
Feedback (((y + 1) * 100) / Integer (image.height));
end loop;
end Get_with_palette;
begin
pix.alpha := 255; -- opaque is default
Attach_Stream (image.buffer, image.stream);
--
if image.RLE_encoded then
-- One format check per row
RLE_pixels_remaining := 0;
for y in 0 .. Integer (image.height) - 1 loop
Row_start (y);
if image.palette /= null then
for x in 0 .. Integer (image.width) - 1 loop
RLE_pixel_palette;
Output_Pixel;
end loop;
else
case image.bits_per_pixel is
when 32 =>
for x in 0 .. image.width - 1 loop
RLE_pixel_32;
Output_Pixel;
end loop;
when 24 =>
for x in 0 .. image.width - 1 loop
RLE_pixel_24;
Output_Pixel;
end loop;
when 16 =>
for x in 0 .. image.width - 1 loop
RLE_pixel_16;
Output_Pixel;
end loop;
when 15 =>
for x in 0 .. image.width - 1 loop
RLE_pixel_15;
Output_Pixel;
end loop;
when 8 =>
for x in 0 .. image.width - 1 loop
RLE_pixel_8;
Output_Pixel;
end loop;
when others => null;
end case;
end if;
Feedback (((y + 1) * 100) / Integer (image.height));
end loop;
elsif image.palette /= null then
Get_with_palette;
else
case image.bits_per_pixel is
when 32 =>
Get_RGBA;
when 24 =>
Get_RGB;
when 16 =>
Get_16;
when 15 =>
Get_15;
when 8 =>
Get_Gray;
when others => null;
end case;
end if;
end Load;
end GID.Decoding_TGA;
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.