Logo Search packages:      
Sourcecode: gandalf version File versions

image_bit.c

/**
 * File:          $RCSfile: image_bit.c,v $
 * Module:        Binary images
 * Part of:       Gandalf Library
 *
 * Revision:      $Revision: 1.40 $
 * Last edited:   $Date: 2003/08/08 18:37:40 $
 * Author:        $Author: pm $
 * Copyright:     (c) 2000 Imagineer Software Limited
 */

/* This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <gandalf/image/image_bit.h>

/**
 * \defgroup ImagePackage Image Package
 * \{
 */

/* start other groups */

/**
 * \defgroup ImageAllocate Allocate/Free an Image
 * \{
 */

/**
 * \}
 */

/**
 * \defgroup ImageSet Set Attributes of an Image
 * \{
 */

/**
 * \}
 */

/**
 * \defgroup ImageGet Get Attributes of an Image
 * \{
 */

/**
 * \}
 */

/**
 * \defgroup ImageTest Test Attributes of an Image
 * \{
 */

/**
 * \}
 */

/**
 * \defgroup ImageExtract Extract a Part of an Image
 * \{
 */

/**
 * \}
 */

/**
 * \defgroup ImageAccessPixel Access Individual Pixels of an Image
 * \{
 */

/**
 * \}
 */

/**
 * \defgroup ImageSize Return Size Attributes of a Pixel or an Image
 * \{
 */

/**
 * \}
 */

/**
 * \defgroup ImageFill Fill an Image
 * \{
 */

/**
 * \}
 */

/**
 * \}
 */

#define GAN_PIXEL Gan_BitWord
#define GAN_PIXEL_FORMAT grey-level
#define GAN_PIXEL_TYPE Gan_Bool
#define GAN_PIXTYPE GAN_BOOL
#define GAN_IMTYPE b
#define GAN_IMAGE_FORM_GEN gan_image_form_gen_b
#define GAN_IMAGE_SET_GEN gan_image_set_gen_b
#define GAN_IMAGE_ALLOC gan_image_alloc_b
#define GAN_IMAGE_ALLOC_DATA gan_image_alloc_data_b
#define GAN_IMAGE_FORM gan_image_form_b
#define GAN_IMAGE_FORM_DATA gan_image_form_data_b
#define GAN_IMAGE_SET gan_image_set_b
#define GAN_IMAGE_SET_PIX gan_image_set_pix_b
#define GAN_IMAGE_GET_PIX gan_image_get_pix_b
#define GAN_IMAGE_FILL_CONST gan_image_fill_const_b
#define GAN_IMAGE_GET_ACTIVE_SUBWINDOW gan_image_get_active_subwindow_b
#define GAN_IMAGE_MASK_WINDOW gan_image_mask_window_b
#define GAN_IMAGE_PIXEL_ZERO_VAL GAN_FALSE
#define GAN_FILL_ARRAY gan_fill_array_b
#define GAN_COPY_ARRAY gan_copy_array_b

/* to generate bitmap-specific code */
#define GAN_BITMAP

#include <gandalf/image/image_grey_noc.c>

#undef GAN_BITMAP
#undef GAN_PIXEL_FORMAT
#undef GAN_PIXEL_TYPE
#undef GAN_PIXEL
#undef GAN_PIXTYPE
#undef GAN_IMTYPE
#undef GAN_IMAGE_FORM_GEN
#undef GAN_IMAGE_SET_GEN
#undef GAN_IMAGE_ALLOC
#undef GAN_IMAGE_ALLOC_DATA
#undef GAN_IMAGE_FORM
#undef GAN_IMAGE_FORM_DATA
#undef GAN_IMAGE_SET
#undef GAN_IMAGE_SET_PIX
#undef GAN_IMAGE_GET_PIX
#undef GAN_IMAGE_FILL_CONST
#undef GAN_IMAGE_GET_ACTIVE_SUBWINDOW
#undef GAN_IMAGE_MASK_WINDOW
#undef GAN_IMAGE_PIXEL_ZERO_VAL
#undef GAN_FILL_ARRAY
#undef GAN_COPY_ARRAY

#include <gandalf/common/misc_error.h>

/**
 * \addtogroup ImagePackage
 * \{
 */

/**
 * \defgroup ImageBinary Binary Image Operations
 * \{
 */

/* if NDEBUG is defined, the functions below are implemented as macros */
#ifndef NDEBUG

/**
 * \brief Test local group of four binary pixels.
 *
 * Return #GAN_TRUE if bits at positions \a (row,col), \a (row,col+1),
 * \a (row+1,col) and \a (row+1,col+1) are all set to one (true),
 * or #GAN_FALSE otherwise.
 */
Gan_Bool
00183  gan_image_bit_get_pix_4group ( Gan_Image *image,
                                unsigned row, unsigned col )
{
   /* consistency check */
   assert ( image->format == GAN_GREY_LEVEL_IMAGE && image->type == GAN_BOOL );

   gan_assert ( row < image->height-1 && col < image->width-1,
                "illegal pixel position in gan_image_bit_get_pix_4group()" );

   /* get pixel */
   return ((gan_bit_array_get_bit ( &image->ba[row],   col   ) &&
            gan_bit_array_get_bit ( &image->ba[row],   col+1 ) &&
            gan_bit_array_get_bit ( &image->ba[row+1], col   ) &&
            gan_bit_array_get_bit ( &image->ba[row+1], col+1 ))
           ? GAN_TRUE : GAN_FALSE);
}

/**
 * \brief Test local group of five binary pixels.
 *
 * Return #GAN_TRUE if bits at positions \a (row,col), \a (row,col-1),
 * \a (row,col+1), \a (row-1,col) and \a (row+1,col) are all set to one
 * (true), or #GAN_FALSE otherwise.
 */
Gan_Bool
00208  gan_image_bit_get_pix_5group ( Gan_Image *image,
                                unsigned row, unsigned col )
{
   /* consistency check */
   assert ( image->format == GAN_GREY_LEVEL_IMAGE && image->type == GAN_BOOL );

   gan_assert ( row > 0 && row < image->height-1 &&
                col > 0 && col < image->width-1,
                "illegal pixel position in gan_image_bit_get_pix_5group()" );

   /* get pixel */
   return ((gan_bit_array_get_bit ( &image->ba[row-1], col   ) &&
            gan_bit_array_get_bit ( &image->ba[row],   col-1 ) &&
            gan_bit_array_get_bit ( &image->ba[row],   col   ) &&
            gan_bit_array_get_bit ( &image->ba[row],   col+1 ) &&
            gan_bit_array_get_bit ( &image->ba[row+1], col   ))
           ? GAN_TRUE : GAN_FALSE);
}

/**
 * \brief Test local group of three binary pixels in a row.
 *
 * Return #GAN_TRUE if bits at positions \a (row,col), \a (row,col-1) and
 * \a (row,col+1) are all set to one (true), or #GAN_FALSE otherwise.
 */
Gan_Bool
00234  gan_image_bit_get_pix_3group_horiz ( Gan_Image *image,
                                      unsigned row, unsigned col )
{
   /* consistency check */
   assert ( image->format == GAN_GREY_LEVEL_IMAGE && image->type == GAN_BOOL );

   gan_assert ( row < image->height &&
                image->width > 2 && col > 0 && col < image->width-1,
                "illegal pixel in gan_image_bit_get_pix_3group_horiz()" );

   /* get pixel */
   return ((gan_bit_array_get_bit ( &image->ba[row], col-1 ) &&
            gan_bit_array_get_bit ( &image->ba[row], col   ) &&
            gan_bit_array_get_bit ( &image->ba[row], col+1 ))
           ? GAN_TRUE : GAN_FALSE);
}

/**
 * \brief Test local group of three binary pixels in a column.
 *
 * Return #GAN_TRUE if bits at positions \a (row,col), \a (row-1,col) and
 * \a (row+1,col) are all set to one (true), or #GAN_FALSE otherwise.
 */
Gan_Bool
00258  gan_image_bit_get_pix_3group_vert ( Gan_Image *image,
                                     unsigned row, unsigned col )
{
   /* consistency check */
   assert ( image->format == GAN_GREY_LEVEL_IMAGE && image->type == GAN_BOOL );

   gan_assert ( row > 0 && row < image->height-1 && image->width > 0 &&
                col < image->width,
                "illegal pixel in gan_image_bit_get_pix_3group_vert()" );

   /* get pixel */
   return ((gan_bit_array_get_bit ( &image->ba[row-1], col ) &&
            gan_bit_array_get_bit ( &image->ba[row],   col   ) &&
            gan_bit_array_get_bit ( &image->ba[row+1], col ))
           ? GAN_TRUE : GAN_FALSE);
}

#endif /* #ifndef NDEBUG */

/**
 * \brief Returns number of pixels set or unset in the given binary image.
 *
 * If \a val is passed as #GAN_TRUE, returns the number of pixels set to
 * one (true) in the given \a image. If \a val is #GAN_FALSE, counts the
 * number of zeros instead. If \a subwin is not \c NULL, counts the pixels
 * only inside the given subwindow.
 */
int
00286  gan_image_get_pixel_count_b ( Gan_Image *image, 
                               Gan_Bool val,
                               Gan_ImageWindow *subwin )
{
   Gan_ImageWindow new_subwin;
   unsigned int max_row, row;
   unsigned int max_col, col;
   int pixel_count = 0;
   Gan_Bool success;

   if ( image == NULL )
   {
      gan_err_flush_trace();
      gan_err_register ( "gan_image_get_pixel_count",
                         GAN_ERROR_ILLEGAL_ARGUMENT, "NULL image pointer" );
      return -1;
   }

   if(subwin == NULL)
   {
      subwin = &new_subwin;

      success = gan_image_get_active_subwindow_b(image, GAN_BYTE_ALIGNMENT,
                                                 subwin);
      
      if(!success)
      {
         gan_err_flush_trace();
         gan_err_register ( "gan_image_get_pixel_count",
                            GAN_ERROR_NO_DATA,
                            "Unable to determine active subimage" );
         return -1;
      }
   }
   
   max_row = subwin->r0 + subwin->height;
   max_col = subwin->c0 + subwin->width;

   for(row = subwin->r0; row < max_row; row++)
      for(col = subwin->c0; col < max_col; col++)
         if(gan_image_get_pix_b( image, row, col ))
            pixel_count++;

   /* if we wanted the number of unset pixels, adjust pixel count */
   if ( !val )
      pixel_count = (int)(image->height*image->width) - pixel_count;

   return pixel_count;
}

/**
 * \brief Invert binary image.
 * \return The result image \a result_image.
 *
 * Invert all the bits in the given \a image, writing the result into
 * \a result_image.
 */
Gan_Image *
00344  gan_image_bit_invert_q ( Gan_Image *image, Gan_Image *result_image )
{
   int iRow;

   gan_err_test_ptr ( image->format == GAN_GREY_LEVEL_IMAGE &&
                      image->type == GAN_BOOL, "image_bit_and_q",
                      GAN_ERROR_INCOMPATIBLE, "" );

   if ( result_image == NULL )
      result_image = gan_image_copy_s ( image );
   else if ( image != result_image )
      result_image = gan_image_copy_q ( image, result_image );
   
   if ( result_image == NULL )
   {
      gan_err_register ( "gan_image_bit_invert_q", GAN_ERROR_FAILURE, "" );
      return NULL;
   }

   /* apply bitwise inversion operation */
   for ( iRow = (int)image->height-1; iRow >= 0; iRow-- )
      if ( !gan_bit_array_invert_i ( &result_image->ba[iRow] ) )
      {
         gan_err_register ( "gan_image_bit_invert_q", GAN_ERROR_FAILURE, "" );
         return NULL;
      }
   
   /* success */
   return result_image;
}

/**
 * \brief Binary \c AND of all pixels in a binary image.
 * \return Result binary image \a result.
 *
 * Apply \c AND operation to two input binary images \a image1 and \a image2,
 * writing the result into \a result.
 */
Gan_Image *
00383  gan_image_bit_and_q ( Gan_Image *image1, Gan_Image *image2,
                       Gan_Image *result )
{
   int iRow;

   gan_err_test_ptr ( image1->format == GAN_GREY_LEVEL_IMAGE &&
                      image1->type == GAN_BOOL, "image_bit_and_q",
                      GAN_ERROR_INCOMPATIBLE, "" );
   gan_err_test_ptr ( image2->format == GAN_GREY_LEVEL_IMAGE &&
                      image2->type == GAN_BOOL, "image_bit_and_q",
                      GAN_ERROR_INCOMPATIBLE, "" );
   gan_err_test_ptr ( gan_image_test_dims(image1,image2),
                      "image_bit_and_q", GAN_ERROR_INCOMPATIBLE, "" );

   if ( result == NULL )
      result = gan_image_copy_s ( image1 );
   else if ( image1 != result )
      result = gan_image_copy_q ( image1, result );
   
   if ( result == NULL )
   {
      gan_err_register ( "gan_image_bit_and_q", GAN_ERROR_FAILURE, "" );
      return NULL;
   }

   /* apply AND operation */
   for ( iRow = (int)image1->height-1; iRow >= 0; iRow-- )
      if ( !gan_bit_array_and_i ( &result->ba[iRow], &image2->ba[iRow] ) )
      {
         gan_err_register ( "gan_image_bit_and_q", GAN_ERROR_FAILURE, "" );
         return NULL;
      }
   
   /* success */
   return result;
}

/**
 * \brief Binary \c NAND of all pixels in a binary image.
 * \return Result binary image \a result.
 *
 * Apply \c NAND operation (not \c AND) to two input binary images \a image1
 * and \a image2, writing the result into \a result.
 */
Gan_Image *
00428  gan_image_bit_nand_q ( Gan_Image *image1, Gan_Image *image2,
                        Gan_Image *result )
{
   int iRow;

   gan_err_test_ptr ( image1->format == GAN_GREY_LEVEL_IMAGE &&
                      image1->type == GAN_BOOL, "image_bit_nand_q",
                      GAN_ERROR_INCOMPATIBLE, "" );
   gan_err_test_ptr ( image2->format == GAN_GREY_LEVEL_IMAGE &&
                      image2->type == GAN_BOOL, "image_bit_nand_q",
                      GAN_ERROR_INCOMPATIBLE, "" );
   gan_err_test_ptr ( gan_image_test_dims(image1,image2),
                      "image_bit_nand_q", GAN_ERROR_INCOMPATIBLE, "" );

   if ( result == NULL )
      result = gan_image_copy_s ( image1 );
   else if ( image1 != result )
      result = gan_image_copy_q ( image1, result );
   
   if ( result == NULL )
   {
      gan_err_register ( "gan_image_bit_nand_q", GAN_ERROR_FAILURE, "" );
      return NULL;
   }

   /* apply NAND operation */
   for ( iRow = (int)image1->height-1; iRow >= 0; iRow-- )
      if ( !gan_bit_array_nand_i ( &result->ba[iRow], &image2->ba[iRow] ) )
      {
         gan_err_register ( "gan_image_bit_nand_q", GAN_ERROR_FAILURE, "" );
         return NULL;
      }
   
   /* success */
   return result;
}

/**
 * \brief Binary \c OR of all pixels in a binary image.
 * \return Result binary image \a result.
 *
 * Apply \c OR operation to two input binary images \a image1 and \a image2,
 * writing the result into \a result.
 */
Gan_Image *
00473  gan_image_bit_or_q ( Gan_Image *image1, Gan_Image *image2,
                      Gan_Image *result )
{
   int iRow;

   gan_err_test_ptr ( image1->format == GAN_GREY_LEVEL_IMAGE &&
                      image1->type == GAN_BOOL, "image_bit_or_q",
                      GAN_ERROR_INCOMPATIBLE, "" );
   gan_err_test_ptr ( image2->format == GAN_GREY_LEVEL_IMAGE &&
                      image2->type == GAN_BOOL, "image_bit_or_q",
                      GAN_ERROR_INCOMPATIBLE, "" );
   gan_err_test_ptr ( gan_image_test_dims(image1,image2),
                      "image_bit_or_q", GAN_ERROR_INCOMPATIBLE, "" );

   if ( result == NULL )
      result = gan_image_copy_s ( image1 );
   else if ( image1 != result )
      result = gan_image_copy_q ( image1, result );
   
   if ( result == NULL )
   {
      gan_err_register ( "gan_image_bit_or_q", GAN_ERROR_FAILURE, "" );
      return NULL;
   }

   /* apply OR operation */
   for ( iRow = (int)image1->height-1; iRow >= 0; iRow-- )
      if ( !gan_bit_array_or_i ( &result->ba[iRow], &image2->ba[iRow] ) )
      {
         gan_err_register ( "gan_image_bit_or_q", GAN_ERROR_FAILURE, "" );
         return NULL;
      }
   
   /* success */
   return result;
}

/**
 * \brief Binary \c EOR of all pixels in a binary image.
 * \return Result binary image \a result.
 *
 * Apply \c EOR operation (exclusive \c OR) to two input binary images
 * \a image1 and \a image2, writing the result into \a result.
 */
Gan_Image *
00518  gan_image_bit_eor_q ( Gan_Image *image1, Gan_Image *image2,
                       Gan_Image *result )
{
   int iRow;

   gan_err_test_ptr ( image1->format == GAN_GREY_LEVEL_IMAGE &&
                      image1->type == GAN_BOOL, "image_bit_eor_q",
                      GAN_ERROR_INCOMPATIBLE, "" );
   gan_err_test_ptr ( image2->format == GAN_GREY_LEVEL_IMAGE &&
                      image2->type == GAN_BOOL, "image_bit_eor_q",
                      GAN_ERROR_INCOMPATIBLE, "" );
   gan_err_test_ptr ( gan_image_test_dims(image1,image2),
                      "image_bit_eor_q", GAN_ERROR_INCOMPATIBLE, "" );

   if ( result == NULL )
      result = gan_image_copy_s ( image1 );
   else if ( image1 != result )
      result = gan_image_copy_q ( image1, result );
   
   if ( result == NULL )
   {
      gan_err_register ( "gan_image_bit_eor_q", GAN_ERROR_FAILURE, "" );
      return NULL;
   }

   /* apply exclusive OR operation */
   for ( iRow = (int)image1->height-1; iRow >= 0; iRow-- )
      if ( !gan_bit_array_eor_i ( &result->ba[iRow], &image2->ba[iRow] ) )
      {
         gan_err_register ( "gan_image_bit_eor_q", GAN_ERROR_FAILURE, "" );
         return NULL;
      }
   
   /* success */
   return result;
}

/**
 * \brief Binary \c AND-NOT of all pixels in a binary image.
 * \return Result binary image \a result.
 *
 * Apply \c AND-NOT operation to two input binary images \a image1
 * and \a image2, writing the result into \a result.
 */
Gan_Image *
00563  gan_image_bit_andnot_q ( Gan_Image *image1, Gan_Image *image2,
                          Gan_Image *result )
{
   int iRow;

   gan_err_test_ptr ( image1->format == GAN_GREY_LEVEL_IMAGE &&
                      image1->type == GAN_BOOL, "image_bit_andnot_q",
                      GAN_ERROR_INCOMPATIBLE, "" );
   gan_err_test_ptr ( image2->format == GAN_GREY_LEVEL_IMAGE &&
                      image2->type == GAN_BOOL, "image_bit_andnot_q",
                      GAN_ERROR_INCOMPATIBLE, "" );
   gan_err_test_ptr ( gan_image_test_dims(image1,image2),
                      "image_bit_andnot_q", GAN_ERROR_INCOMPATIBLE, "" );

   if ( result == NULL )
      result = gan_image_copy_s ( image1 );
   else if ( image1 != result )
      result = gan_image_copy_q ( image1, result );
   
   if ( result == NULL )
   {
      gan_err_register ( "gan_image_bit_andnot_q", GAN_ERROR_FAILURE, "" );
      return NULL;
   }

   /* apply AND-NOT operation */
   for ( iRow = (int)image1->height-1; iRow >= 0; iRow-- )
      if ( !gan_bit_array_andnot_i ( &result->ba[iRow], &image2->ba[iRow] ) )
      {
         gan_err_register ( "gan_image_bit_andnot_q", GAN_ERROR_FAILURE, "" );
         return NULL;
      }
   
   /* success */
   return result;
}

/**
 * \brief Fill part of a row of a binary image.
 *
 * Fill part of a row of a binary \a image, starting at position \a x, \a y
 * and filling \a width pixels to the right.
 */
Gan_Bool
00607  gan_image_bit_fill_row ( Gan_Image *image, unsigned y,
                          unsigned x, unsigned width, Gan_Bool pix )
{
   /* compatibility checks */
   gan_err_test_bool ( image->format == GAN_GREY_LEVEL_IMAGE &&
                       image->type == GAN_BOOL,
                       "gan_image_bit_fill_row", GAN_ERROR_ILLEGAL_ARGUMENT,
                       "" );
   gan_err_test_bool ( x+width <= image->width && y < image->height,
                       "gan_image_bit_fill_row", GAN_ERROR_ILLEGAL_ARGUMENT,
                       "" );

   if ( !gan_bit_array_fill_part ( &image->ba[y], x, width, pix ) )
   {
      gan_err_register ( "gan_image_bit_fill_row", GAN_ERROR_FAILURE, "" );
      return GAN_FALSE;
   }

   /* success */
   return GAN_TRUE;
}

/**
 * \brief Invert part of a row of a binary image.
 *
 * Invert part of a row of a binary \a image, starting at position \a x, \a y
 * and filling \a width pixels to the right.
 */
Gan_Bool
00636  gan_image_bit_invert_row ( Gan_Image *image, unsigned y,
                            unsigned x, unsigned width )
{
   /* compatibility checks */
   gan_err_test_bool ( image->format == GAN_GREY_LEVEL_IMAGE &&
                       image->type == GAN_BOOL,
                       "gan_image_bit_invert_row", GAN_ERROR_ILLEGAL_ARGUMENT,
                       "" );
   gan_err_test_bool ( x+width <= image->width && y < image->height,
                       "gan_image_bit_invert_row", GAN_ERROR_ILLEGAL_ARGUMENT,
                       "" );

   for ( ; --width > 0; x++ )
      gan_image_set_pix_b ( image, y, x,
                            (Gan_Bool)!gan_image_get_pix_b(image,y,x) );

   /* success */
   return GAN_TRUE;
}

/**
 * \}
 */

/**
 * \}
 */

Generated by  Doxygen 1.6.0   Back to index