comp.lang.ada
 help / color / mirror / Atom feed
From: ka@sorry.no.email (Kenneth Almquist)
Subject: Re: Representing image data
Date: Fri, 13 Mar 2009 20:31:18 GMT
Date: 2009-03-13T20:31:18+00:00	[thread overview]
Message-ID: <qozul.5$6%.1@nwrddc01.gnilink.net> (raw)
In-Reply-To: 9WAtl.2301$gm6.1634@nwrddc02.gnilink.net

Here is my latest version of the row-at-a-time interface.

First, sample values are best thought of as integer types rather than
modular types, so we shouldn't use the Unsigned types from the
Interfaces package even though they have the right type.  Instead,
we declare:

    type Sample_8 is range 0 .. 2**8 - 1;
    type Sample_16 is range 0 .. 2**16 - 1;

The size of these types defaults to 8 and 16, respectively, so no
size clauses are necessary.  An application could use these types
in to represent sample values throughout the application, or could
perform type conversions on the individual samples.

To make fetching rows type safe, we declare a generic package for
each possible type.  For example, to read an RGB image with 8 bits
per sample, one could write:

    declare
        package Rows is new Imd.RGB_8(Decoder);
        Row : Rows.Row_Ptr;
    begin
        for Row_Number in 1 .. Decoder.Height loop
            Rows.Get_Row(Row);
            for Column_Number in Row.all'Range loop
                Store_Pixel(Row_Number, Column_Number,
                            Row.all(Column_Number).Red,
                            Row.all(Column_Number).Green,
                            Row.all(Column_Number).Blue);
            end loop;
        end loop;
    end;

The Store_Pixel routine is a stand-in for whatever processing the
application wants to do on the pixel values.  This code ignores the
problem of error handling.

The Get_Row procedure produces a pointer to the next row.  It would
be possible to make it produce the contents of the row rather than
a pointer, but there doesn't seem to be a strong case for doing that.
The application code would be marginally simpler because the references
to "Row.all" would change to "Row".  It would also be marginally slower
because of the extra copying.

The Imd.RGB_8 package is defined an implemented as follows:

    generic
        Decoder : Decoder_State;
    package Imd.RGB_8 is

        -- Elaborating an instantation of this package will initialize
        -- the decoding of the image sample data.
        pragma Elaborate_Body;

        type Pixel is record
            Red : Sample_8;
            Green : Sample_8;
            Blue : Sample_8;
        end record;
        pragma Pack(Pixel);

        type Row_Array is array (Integer range 1 .. Decoder.Width) of Pixel;
        type Row_Ptr is access all Row_Array;

        -- Get_Row - Get the next row.  Each call to Get_Row generates a
        -- new row and returns a pointer to the row.  If an error occurs,
        -- Get_Row will set the error flag in the Decoder structure and
        -- continue processing, producing row data that may not be meaningful.
        procedure Get_Row(Row : out Row_Ptr);
        pragma Inline(Get_Row);

    end Imd.RGB_8;


    -- generic
    --    Decoder : Decoder_State;
    package body Imd.RGB_8 is

        function Imd_Read_Row(Decoder : Decoder_State) return Row_Ptr;
        pragma Import(C, Imd_Read_Row, "imd_read_row");

        procedure Imd_Start_Read(Decoder : Decoder_State);
        pragma Import(C, Imd_Start_Read, "imd_start_read");

        procedure Get_Row(Row : out Row_Ptr) is
        begin
            Row := Imd_Read_Row(Decoder);
        end Get_Row;

    begin
        Imd.Set_Output_Format(Decoder, RGB + Size_8);
        Imd_Start_Read(Decoder);
    end Imd.RGB_8;

We have to define a separate generic package for each pixel format
and sample size.  If the meaning of the samples is not known, the
package to use is Imd.Any_8 or Imd.Any_16, which defines the pixel
type as:

        type Pixel is array (Integer range 1 .. Decoder.Samples_Per_Pixel)
            of Sample_16;
        pragma Pack(Pixel);

This package could be used for any image type.

For mapped data, two generic instantiations are required

    declare
        package Map_Def is new Imd.Map_RGB_16(Decoder)
        package Rows is new Imd.Map_8(Decoder);
        Map : Map_Def.Map_Ptr;
        Row : Rows.Row_Ptr;
    begin
        Map_Def.Get_Map(Map);
        [loop through rows here]
    end;

Using two generic instantiations reduces the number of generic packages
required.  The first defines the type of the map, and the second
defines the type of the pixel samples that refer to the entries in
the map.

This scheme requires about 28 generic packages.
				    Kenneth Almquist



      parent reply	other threads:[~2009-03-13 20:31 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-10 21:26 Representing image data Kenneth Almquist
2009-03-11  1:16 ` Gautier
2009-03-11  2:43   ` Srini -
2009-03-11 21:12   ` Kenneth Almquist
2009-03-11 22:39     ` tmoran
2009-03-12  2:38   ` Randy Brukardt
2009-03-11  9:00 ` Dmitry A. Kazakov
2009-03-11 15:45   ` Brian Drummond
2009-03-11 20:12     ` sjw
2009-03-13 11:31       ` Brian Drummond
2009-03-13 20:31 ` Kenneth Almquist [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox