comp.lang.ada
 help / color / mirror / Atom feed
From: ka@sorry.no.email (Kenneth Almquist)
Subject: Representing image data
Date: Tue, 10 Mar 2009 21:26:29 GMT
Date: 2009-03-10T21:26:29+00:00	[thread overview]
Message-ID: <9WAtl.2301$gm6.1634@nwrddc02.gnilink.net> (raw)

I've been working on the design of an image decoding library.  The
basic idea is that the library will examine the first few bytes of
an image, determine the format, and call the appropriate decoder,
so that an application using the library can read images without
writing code for each image format it wants to handle.

I'm looking for suggestions on what the Ada interface to the
library should look like--and in particular how the image contents
should be provided to the application using the library.  The current
design has a C interface with no type checking on the image data.

What follows is the C language interface presented in Ada syntax.
The data for each pixel consists of one or more samples.  There are
a fair number of possibilities, because both the meaning of the
samples and the number of bits per sample can vary.  The possibilities
for the meanings of the samples are:

    Imd.W - white (greyscale) sample
    Imd.WA - white + alpha (transparency) samples
    Imd.RGB - red + green + blue samples (color image)
    Imd.RGBA - RGB + alpha samples
    Imd.CMYK - C + M + Y + K samples (color printer separation)
    Imd.Unknown - one or more samples whose meaning is not known
                  by the library.

Any of the previous possibilities may be combined with Imd.Mapped.
If Imd.Mapped is set, there is one sample per pixel representing
an index into a color map.  Each entry in the color map will contain
one or more sample values, in one of the formats listed above.

The size of the samples can be one of:

    Imd.Size_1BE
    Imd.Size_8
    Imd.Size_16

Imd.Size_8 means that samples are 8 bits.  The corresponding Ada type
is Interfaces.Unsigned_8 or equivalent.  Imd.Size_16 means 16 bit
samples, stored in Interfaces.Unsigned_16 or equivalent.  Imd.Size_1BE
means one bit samples, packed into Unsigned_8 quantities in big endian
order (high order bit first).  Imd.Size_1BE is only used when there is
one sample per pixel; it is intended to allow bit maps to be represented
compactly.

If a color map is used, then the size of the samples in the color map
also needs to be specified.  The possiblities are:

    Imd.Map_Size_8
    Imd.Map_Size_16

In the C language interface, all of the above constants have the type
Interfaces.Unsigned_16, and can be combined using the "+" or "or"
operators.  For example, mapped RGB color with 8 bit sample sizes can
be specified as

    Imd.RGB or Imd.Mapped or Imd.Size_8 or Imd.Map_Size_8

Most applications would use only a few of the possible output formats.
The library contains conversions to:
    - convert mapped data to unmapped data
    - convert greyscale to RGB.
    - convert CMYK to RGB (but not very accurately).
    - add or discard the alpha channel.
    - convert sample sizes to 8 or 16 bits.
So the library can convert any image to (Imd.RGB or Imd.Size_8) except
for images where the meanings of the samples are unknown.

One additional variation is that the image can be decoded one row at a
time, or in one piece.  A row is represented as a sequence of pixel
values, in left to right order.  An image is represented as a sequence
of rows, in top to bottom order.  If the sample format is Imd.Size_1BE,
then each row will be padded if necessary to make the size a multiple
of 8, so that each row will start on a byte boundary.

After processing the image header, the steps for decoding an image are:

    -- Set the output type.
    -- The variable Decoder is a pointer to the decoder structure.
    if Imd.Set_Output_Format(Decoder, Imd.RGB or Imd.Mapped or
                              Imd.Size_8 or Imd.Map_Size_8) = False then
	Ada.Text_IO.Put_Line("Cannot convert to mapped RGB format");
        raise ...;
    end if;

    -- Read the map (only do this for mapped output).
    declare
        type Map_Type is ...;
        type Map_Ptr is access all Map_Type;
    begin
        -- Allocate space for map.  The Sizeof_Map routine calculates
        -- the correct size.
        Map_Ptr := malloc(Imd.Sizeof_Map(Decoder));
        if Map_Ptr = null then raise Storage_Error; end if;

	-- Get the map.
        Imd.Get_Map(Decoder, Map_Ptr.all'Address);
        if Decoder.Error /= 0 then raise ...; end if;
        ...
    end;

    -- Read the entire image at once.
    declare
        type Image_Array is ...;
        type Image_Ptr is access all Image_Array;
    begin
	-- Allocate space for the image.  Imd.Sizeof_Image calculates
	-- the correct size.
        Image_Ptr := malloc(Imd.Sizeof_Image(Decoder));
        if Map_Ptr = null then raise Storage_Error; end if;

        -- Read the image.
        Imd.Get_Image(Decoder, Image_Ptr.all'Address);
        if Decoder.Error /= 0 then raise ...; end if;
        ...
    end;

If the application wants to read one row at a time, it uses something like:

    -- Read the image, one row at a time.
    if Imd.Start_Output(Decoder) = False then
	Ada.Text_IO.Put_Line("Cannot decode image");
        raise ...;
    end if;

    for Row_Number in 1 .. Decoder.Height loop
        declare
            type Row is ...;
            package Row_Acc is new System.Address_To_Access_Conversions(Row);
            Row_Ptr : Row_Acc.Object_Ptr;
        begin
            -- Read one row.  Read_Row returns a pointer to the
            -- row, which is stored in a block of memory allocated
            -- by the library.
            Row_Ptr := Row_Acc.To_Pointer(Imd.Read_Row(Decoder));
            ...
        end;
    end loop;
    -- Check for error.  We could have done this inside the loop.
    if Decoder.Error /= 0 then raise ...; end if;

For Imd.RGB + Imd.Size_8 output, the Row type could be declared as

    type Primary is (Red, Green, Blue);
    type Pixel is array (Primary) of Interfaces.Unsigned_8;
    type Row is array(1 .. Decoder.Width) of Pixel;

But in C you would probably do the equivalent of

    type Row is array (Natural) of Interfaces.Unsigned_8;

Thanks for any ideas.
		                Kenneth Almquist



             reply	other threads:[~2009-03-10 21:26 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-10 21:26 Kenneth Almquist [this message]
2009-03-11  1:16 ` Representing image data 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
replies disabled

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