next up previous contents
Next: Filling an image with Up: Image file I/O Previous: Setting an image to   Contents

Accessing single pixels

To return the value of a single image pixel use
      Gan_Image *pImage;
      short sPixel;

      /* ... create and fill grey-level short integer image pImage ... */
      sPixel = gan_image_get_pix_gl_s ( pImage, 33, 40 );
This returns the pixel value at row position 33 and column position 40 (starting from zero). The RGB colour version would be
      Gan_Image *pImage;
      Gan_RGBPixel_uc rgbucPixel;

      /* ... create and fill RGB colour unsigned character image pImage ... */
      rgbucPixel = gan_image_get_pix_rgb_uc ( pImage, 33, 40 );

An alternative is to return a pointer to a pixel. This operation is available for every type and format of image except binary images, which are stored packed with 32 or 64 pixels to a memory word. To return a pointer to the above pixels you would use

      Gan_Image *pImage;
      short *psPixel;

      /* ... create and fill grey-level short integer image pImage ... */
      psPixel = gan_image_get_pixptr_gl_s ( pImage, 33, 40 );
for a grey-level image, or
      Gan_Image *pImage;
      Gan_RGBPixel_uc *prgbucPixel;

      /* ... create and fill RGB colour unsigned character image pImage ... */
      prgbucPixel = gan_image_get_pixptr_rgb_uc ( pImage, 33, 40 );
for an RGB colour image. This type of image access is useful when you want to read or set a lot of consecutive pixels on a row of an image, since you can use the returned pointer as a starting point. For instance the code fragment
      Gan_Image *pImage;
      Gan_RGBPixel_uc *prgbucPixel, rgbucZeroPixel = {0,0,0};
      int iCount;

      /* ... create and fill RGB colour unsigned character image pImage ... */
      prgbucPixel = gan_image_get_pixptr_rgb_uc ( pImage, 33, 40 );
      for ( iCount = 4; iCount >= 0; iCount-- )
         *prgbucPixel++ = rgbucZeroPixel;
sets the five RGB pixels at positions (33,40-44) to zero.

To set a pixel in a grey-level short integer image to a particular value, use the routine

      Gan_Image *pImage;

      /* ... create grey-level short integer image pImage ... */
      gan_image_set_pix_gl_s ( pImage, 33, 40, 123 );
This sets the pixel value at position 33, 40 to value 123. For an RGB unsigned character image you would use the code
      Gan_Image *pImage;
      Gan_RGBPixel_uc rgbucPixel = {12, 13, 14};

      /* ... create RGB colour unsigned character image pImage ... */
      gan_image_set_pix_rgb_uc ( pImage, 33, 40, &rgbucPixel );
This builds a pixel with RGB values 12 (red), 13 (green), 14 (blue) and sets the pixel at position 33, 40 to that RGB value.

With NDEBUG set these routines evaluate to macros which implement direct memory access, so there is no efficiency advantage to be gained from using other methods of accessing individual image pixels.

The higher level routines for accessing single pixels use the Gan_Pixel structure, which can be used to store data for a single pixel of any format and type. The Gan_Pixel structure stores the format and type of the pixel internally, and is defined in <gandalf/image/pixel.h>:

      /* structure definition for image pixel of any format or type */
      typedef struct Gan_Pixel
      {
         /// format of image: grey-level, RGB colour etc.
         Gan_ImageFormat format;

         /// type of pixel values: unsigned char, float etc.
         Gan_Type type;

         /// nested union defining pixel types
         union
         {
            /// grey level
            union
            {
               unsigned char  uc;
               short          s;
               unsigned short us;
               int            i;
               unsigned int   ui;
               double         d;
               float          f;
               Gan_Bool       b;
               void          *p;

      #ifdef GAN_UINT8
               gan_ui8 ui8;
      #endif
      #ifdef GAN_UINT16
               gan_ui16 ui16;
      #endif
      #ifdef GAN_UINT32
               gan_ui32 ui32;
      #endif
            } gl;

            /// grey level with alpha channel
            union
            {
               Gan_GLAPixel_uc uc;
               Gan_GLAPixel_s  s;
               Gan_GLAPixel_us us;
               Gan_GLAPixel_i  i;
               Gan_GLAPixel_ui ui;
               Gan_GLAPixel_d  d;
               Gan_GLAPixel_f  f;

      #ifdef GAN_UINT8
               Gan_GLAPixel_ui8 ui8;
      #endif
      #ifdef GAN_UINT16
               Gan_GLAPixel_ui16 ui16;
      #endif
      #ifdef GAN_UINT32
               Gan_GLAPixel_ui32 ui32;
      #endif
            } gla;

            /// RGB colour
            union
            {
               Gan_RGBPixel_uc uc;
               Gan_RGBPixel_s  s;
               Gan_RGBPixel_us us;
               Gan_RGBPixel_i  i;
               Gan_RGBPixel_ui ui;
               Gan_RGBPixel_d  d;
               Gan_RGBPixel_f  f;

      #ifdef GAN_UINT8
               Gan_RGBPixel_ui8 ui8;
      #endif
      #ifdef GAN_UINT16
               Gan_RGBPixel_ui16 ui16;
      #endif
      #ifdef GAN_UINT32
               Gan_RGBPixel_ui32 ui32;
      #endif
            } rgb;

            /// RGB colour with alpha channel
            union
            {
               Gan_RGBAPixel_uc uc;
               Gan_RGBAPixel_s  s;
               Gan_RGBAPixel_us us;
               Gan_RGBAPixel_i  i;
               Gan_RGBAPixel_ui ui;
               Gan_RGBAPixel_d  d;
               Gan_RGBAPixel_f  f;

      #ifdef GAN_UINT8
               Gan_RGBAPixel_ui8 ui8;
      #endif
      #ifdef GAN_UINT16
               Gan_RGBAPixel_ui16 ui16;
      #endif
      #ifdef GAN_UINT32
               Gan_RGBAPixel_ui32 ui32;
      #endif
            } rgba;

            /// 2D vector field
            union
            {
               Gan_Vector2_f f;
               Gan_Vector2   d;
               Gan_Vector2_s s;
               Gan_Vector2_i i;
            } vfield2D;

            /// 3D vector field
            union
            {
               Gan_Vector3_f f;
               Gan_Vector3   d;
               Gan_Vector3_s s;
               Gan_Vector3_i i;
            } vfield3D;
         } data;
      } Gan_Pixel;
The Gan_Pixel structure should be accessed directly. There are no Gandalf access routines for it. The doubly nested union contains a structure for each Gandalf image format and type. These structures are also defined in the pixel.h header file. We have seen the definition of the Gan_RGBPixel_uc structure above, and the other structures are defined similarly. For instance the pixel to represent a single-precision floating point RGB pixel with alpha channel is
      /**
       * \brief Structure defining RGB single precision floating point pixel with alpha channel.
       */
      typedef struct Gan_RGBAPixel_f
      {
         float R, /**< Red channel */
               G, /**< Green channel */
               B, /**< Blue channel */
               A; /**< Alpha channel */
      } Gan_RGBAPixel_f;
Note that the vector field pixels use Gandalf fixed size vectors to hold the image data.

To set/get a pixel in an image using the higher level routines gan_image_set_pix() and gan_image_get_pix(), look at the following code fragment.

      Gan_Image *pImage;
      int iRow, iCol;
      Gan_Pixel Pixel;

      /* create grey-level signed short image */
      pImage = gan_image_alloc_gl_s ( 200, 100 );

      /* set up pixel format and type */
      Pixel.format = GAN_GREY_LEVEL_IMAGE;
      Pixel.type = GAN_SHORT;

      /* fill image with ramp data */
      for ( iRow = (int)pImage->height-1; iRow >= 0; iRow-- )
         for ( iCol = (int)pImage->width-1; iCol >= 0; iCol-- )
         {
            /* set pixel data */
            Pixel.data.gl.s = iRow+iCol;

            /* fill pixel in image. The format and type of the pixel should
               be the same as that of the image */
            gan_image_set_pix ( pImage, iRow, iCol, &Pixel );
         }

      /* print pixel value, should be 27+35 = 62 */
      Pixel = gan_image_get_pix ( pImage, 27, 35 );
      printf ( "pixel value = %d\n", Pixel.data.gl.s );
Here we created an image, filled it with ``ramp'' data that linearly increases the grey-level value with the row and column coordinates of the image, and extract a single pixel. For an RGB image we could add the following code:
      /* convert the image to RGB format and unsigned character type */
      gan_image_set_rgb_uc ( pImage, 100, 50 );

      /* set up pixel format and type */
      Pixel.format = GAN_RGB_COLOUR_IMAGE;
      Pixel.type = GAN_UCHAR;

      /* fill image with ramp data */
      for ( iRow = (int)pImage->height-1; iRow >= 0; iRow-- )
         for ( iCol = (int)pImage->width-1; iCol >= 0; iCol-- )
         {
            /* set pixel data */
            Pixel.data.rgb.uc.R = iRow+iCol;
            Pixel.data.rgb.uc.G = iRow;
            Pixel.data.rgb.uc.B = iCol;

            /* fill pixel in image. The format and type of the pixel should
               be the same as that of the image */
            gan_image_set_pix ( pImage, iRow, iCol, &Pixel );
         }

      /* print pixel value, should be R=37+11=48, G=37, B=11 */
      Pixel = gan_image_get_pix ( pImage, 37, 11 );
      printf ( "pixel value R=%d G=%d B=%d\n",
               Pixel.data.rgb.uc.R, Pixel.data.rgb.uc.G, Pixel.data.rgb.uc.B );

If you have a Gan_Pixel structure in a different format/type to the image, use gan_image_convert_pixel_[qsi]() to convert it to the format & type of the image before calling gan_image_set_pix(). See Section 4.3.4 for details.

Error detection: The .._get_pix...() routines cannot return an error condition. Instead they invoke
gan_assert() (see Section 2.1.3) to check for errors, which aborts the program if an error is found. The
..._set_pix...() routines return a boolean value, returning GAN_TRUE on success, invoking the Gandalf error handler and returning GAN_FALSE on failure. The most likely failure modes are accessing a pixel outside the image (both ..._get_pix...() and ..._set_pix...()) and mismatch between image and pixel format/type (..._set_pix...() only). These errors are program bugs rather than data-dependent errors, so using gan_assert() to handle errors is fairly safe.


next up previous contents
Next: Filling an image with Up: Image file I/O Previous: Setting an image to   Contents
2006-03-17