agpl_1.0.0_b5da3320/3rdparty/png_io/png_io-gamma_encoding.adb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
---------------------------------------------------------------------
---------------------------------------------------------------------
-- PNG_IO -- Ada95 Portable Network Graphics Input/Output Package  --
--                                                                 --
-- Copyright (©) 2003 Dr Stephen J. Sangwine (S.Sangwine@IEEE.org) --
--                                                                 --
-- This software was created by Stephen J. Sangwine. He hereby     --
-- asserts his Moral Right to be identified as author of this      --
-- software.                                                       --
---------------------------------------------------------------------
---------------------------------------------------------------------
-- PNG_IO is free software; you can redistribute it and/or modify  --
-- it under the terms of the GNU General Public License as         --
-- published by the Free Software Foundation; either version 2 of  --
-- the License, or (at your option) any later version.             --
--                                                                 --
-- PNG_IO is distributed in the hope that it will be useful, but   --
-- WITHOUT ANY WARRANTY; without even the implied warranty of      --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the    --
-- GNU General Public License for more details.                    --
--                                                                 --
-- You should have received a copy of the GNU General Public       --
-- License along with this software (in the file gpl.txt); if not, --
-- contact the Free Software Foundation, or access www.fsf.org.    --
---------------------------------------------------------------------
---------------------------------------------------------------------
-- Released:  1   July 2004                                        --
-- Edited:   13 August 2006 to refer to the ISO standard.          --
--           13 August 2006 to implement the changed from modular  --
--                          to discrete input and output samples:  --
--                          requiring use of 'Pos and 'Val to      --
--                          handle non-integer types.              --
---------------------------------------------------------------------
---------------------------------------------------------------------

with Ada.Numerics.Elementary_Functions;

package body PNG_IO.Gamma_Encoding is

  pragma Assert( Input_Sample'Pos( Input_Sample'First) = 0);
  pragma Assert(Output_Sample'Pos(Output_Sample'First) = 0);

  -- The gamma lookup table (below) handles a double conversion, from the
  -- input gamma to linearized pixels, and then to the output gamma. Either
  -- (or indeed both!) of the gamma values may be unity (i.e. 100_000). The
  -- two stage calculation is merged here into one stage. The ISO standard
  -- Sections 12.2 and 13.13 explains how the conversion is done. Simply
  -- put, the pixel values from the input file are converted to floats in the
  -- range 0.0 .. 1.0, the two gamma exponents are applied, and the result is
  -- then scaled into the output range.

  type Lookup_Table is array(Input_Sample) of Output_Sample;

  LUT : Lookup_Table; -- This is initialised below during elaboration.

  function To_Output_Gamma(I : Input_Sample) return Output_Sample is
  begin
    return LUT(I);
  end To_Output_Gamma;
  
begin

  Initialise_LUT : declare

    IG : constant Float := 1.0e5/Float( Input_Gamma);
    OG : constant Float := 1.0e5/Float(Output_Gamma);

    Exponent : constant Float := Float(IG)/Float(OG);

    use Ada.Numerics.Elementary_Functions; -- For the ** operator.
    
    IL : constant Float := Float( Input_Sample'Pos( Input_Sample'Last));
    OL : constant Float := Float(Output_Sample'Pos(Output_Sample'Last));

  begin

    for P in LUT'Range loop
      LUT(P) := Output_Sample'Val(Integer(((Float(Input_Sample'Pos(P))/IL) ** Exponent) * OL));
    end loop;

  end Initialise_LUT;
 
end PNG_IO.Gamma_Encoding;