Logo Search packages:      
Sourcecode: paul version File versions  Download package

difpic.c

/*****************************************************************************
 *                                                                           *
 * Programm:  paul                                                           *
 *            (P)rogramm zur (A)uswertung und (U)mformung von                *
 *            (L)aserbildern                                                 *
 * Modul:     difpic.c                                                       *
 *            Funktions to calculate difference images                       *
 * Author:    Andreas Tille                                                  *
 * Date:      27.02.1998                                                     *
 * Copyright: Andreas Tille, 1999; GNU Public License                        *
 *                                                                           *
 *****************************************************************************/

#include <math.h>
#include <stdio.h>
#include <string.h>

#include "paul.h" 
#include "names.h"

#define  MINCOL  0xFF
#define  MAXCOL  0x00

static int strxcmp(const char *s1, const char *s2)
/* obtain the matching first characters of two strings
 * --- Parameter: ---
 * const char *s1, *s2: strings to compare
 * --- Return: ---
 * int   strxcmp()    : number of matching characters in the beginning of the
 *                      two strings
 */
{
   register char *p1 = (char *)s1 - 1, *p2 = (char *)s2 - 1;

   while ( *(++p1) && *(++p2) ) 
      if ( *p1 != *p2 ) break;
   return p1 - s1;
}

static int strbxcmp(const char *s1, const char *s2)
/* obtain the matching last characters of two strings
 * --- Parameter: ---
 * const char *s1, *s2: strings to compare
 * --- Return: ---
 * int   strbxcmp()   : number of matching characters in the end of the
 *                      two strings
 */
{
   register char *p1 = (char *)s1 + strlen(s1), 
                 *p2 = (char *)s2 + strlen(s2),
             *ss;
   
   ss = p1 - 1;
   while ( *(--p1) && *(--p2) ) 
      if ( *p1 != *p2 ) break;
   return ss - p1;
}

static char *DiffBildName(char *bild1, char *bild2)
/* obtain the name of difference image from to source image names
 * The comon parts of both sources at the beginning and the end (except extension)
 * will be used.  The different part in the middle will be stored as
 *  _[img1]-[img2]_
 * --- Parameter: ---
 * char *bild1         : name of first image
 * char *bild2         : name of second image
 * --- Return: ---
 * char *DiffBildName(): name of difference image (memory will be allocated
 *                       ... and some space for extension will be saved)
 */
{
  char        *buf, *pb;
  register int n, m, i;

  buf = g_malloc(strlen(bild1) + strlen(bild2) + 20);
  strncpy(buf, bild1, n = strxcmp(bild1,bild2));
  *(pb = buf + n) = '_';
  ++pb;
  if        ( n == strlen(bild1) ) {
    *(pb++)                   = '-';
    if ( n != strlen(bild2) ) strcpy(pb, bild2 + n);
    *(pb += strlen(bild2+n))  = '_';
    ++pb;
  } else if ( n == strlen(bild2) ) {
    if ( n != strlen(bild1) ) strcpy(pb, bild1 + n);
    *(pb += strlen(bild1+n))  = '-';
    *(++pb)                   = '_';
    ++pb;
  } else {
    m       = strbxcmp(bild1,bild2);
    if ( (i = strlen(bild1) - n - m) > 0 )  
      strncpy(pb, bild1 + n, i);
    else
      i = 1; /* This makes not much sense but avoids crashs for some unusual cases */
    *(pb += i) = '-';
    ++pb;
    if ( (i = strlen(bild2) - n - m) > 0 ) 
      strncpy(pb, bild2 + n, i);
    else
      i = 1; /* This makes not much sense but avoids crashs for some unusual cases */
    *(pb += i) = '_';
    ++pb;
    if ( m ) strncpy(pb, bild1 + strlen(bild1) - m, m);
    pb += m;
  }
  *pb = 0;
  pb = g_strdup(buf);
  FREE(buf);
  return pb;
}


static int DifferenceImage(PICTURE *bild1, PICTURE *bild2, OPTIONS *opt)
/* difference of pixels image1 - image2
 * --- Parameter: ---
 * PICTURE *bild1            : image which is subject to change
 * PICTURE *bild2            : image to subtract from first image
 * OPTIONS *opt              : used options:
 *                             eps   : noise threshold, lower values will be set to 0
 *                             offset: shift of brightness
 *                             scale : contrast factor
 * --- Return: ---
 * PICTURE *bild1            : bild1 now contains difference image 
 * int      DifferenceImage(): RET_OK, RET_ERR;
 */
{ 
  unsigned char           eps   = opt->eps, offset = opt->offset;
  double                  scale = opt->scale;
  register int            d;
  register unsigned char *a, *b, *u, *v, *fip;
  char                   *desc;

  g_return_val_if_fail( IS_PICTURE(bild1), RET_ERR );
  g_return_val_if_fail( IS_PICTURE(bild2), RET_ERR );
  
  if ( bild1->W != bild2->W || 
       bild1->H != bild2->H ) {
    g_warning(_("%s and %s have different size (%ix%i resp. %ix%i).\nTry using \"%s\" to get equal sized images."),
              bild1->file, bild2->file, bild1->W, bild1->H, bild2->W, bild2->H, Mo_ve);
    return RET_ERR;
  }
  if ( !IsMonochrom(bild1) ) MakeSingleGreen(bild1, opt->greps);
  if ( !IsMonochrom(bild2) ) MakeSingleGreen(bild2, opt->greps);
   
  desc = g_strdup_printf("%s - %s", bild1->file, bild2->file);
  ImgChunksUpdate(bild1, TypDifferenzBild, desc, NULL, DIFFERENZ);
  FREE(desc);

  desc        = DiffBildName(bild1->file, bild2->file);
  FREE(bild1->file);
  bild1->file = desc;
  bild1->spp  = 3;


  a = (bild1->DATA) + 1;
  b = (bild2->DATA) + 1;   
  for ( fip = a + 3 * (bild1->size); a < fip; 
        a += 3, b += 3) {
    if ( (d  = (int)*a - (int)*b) < 0 ) {
      u = a - 1;  /* bild1 < bild2 => store Difference in red channel */
      v = a + 1;  /*               => set blue channel 0              */
    } else {
      u = a + 1;
      v = a - 1;
    }
    if ( (d = abs(d)) < eps ) { /* suppress noise */
      *(a-1) = *a = *(a+1) = 0xFF;  /* zero differnce set white in favour of black because *
                                     * of higher contrast                                  */
      continue;   
    }
    d  = d * scale + offset;     /* enhance contrast and brightness */
    *u = (unsigned char)(d < 0x100 ? d : 0xFF);
    *a = *v = 0;
  }
  return RET_OK;
}


int DifferenceQueue(PAUL *p)
/* Differences of a list of images
 * --- Parameter: ---
 * PAUL *p               : list of images, options
 *                       : used options:
 *                         eps    : noise border
 *                         offset : increase brightness of difference image  
 *                         scale  : increase contrast of difference image
 * --- return: ---
 * p->piclist            : new list of images containing differences
 * int  DifferenceQueue(): RET_ERR or RET_OK
 */
{
  GList   *pl;

  g_return_val_if_fail ( IS_PAUL(p), RET_ERR );
  if ( !(p->piclist) ) return RET_ERR;
  g_return_val_if_fail ( CheckPicList(p->piclist), RET_ERR ) ;
  if ( NBILDER(p->piclist) < 2 ) return RET_OK;

  for ( pl = p->piclist; pl->next; pl = pl->next ) 
    if ( DifferenceImage(BILD(pl), BILD(pl->next), p->opt) ) return RET_ERR;
  FreePiclist(g_list_last(p->piclist));
  g_list_remove_link(p->piclist, g_list_last(p->piclist));
  p->opt->f &= ~DIFFERENZ;
  return RET_OK;
}

int MakeDifference(PAUL *p)
/* Difference of operating image to all other images
 * --- Parameter: ---
 * PAUL *p               : list of images, options
 *                       : used options:
 *                         eps    : noise border
 *                         offset : increase brightness of difference image  
 *                         scale  : increase contrast of difference image
 * --- return: ---
 * p->piclist            : new list of images containing differences
 * int  MakeDifference() : RET_ERR or RET_OK
 */
{
  GList *pl;
   
  g_return_val_if_fail ( IS_PAUL(p), RET_ERR ) ;
  if ( !(p->piclist) ) return RET_ERR;
  g_return_val_if_fail ( CheckPicList(p->piclist), RET_ERR ) ;
  if ( !CheckOperating(p) ) return RET_ERR;
  
  for ( pl = p->piclist; pl; pl = pl->next ) 
    if ( DifferenceImage(BILD(pl), p->op, p->opt) ) return RET_ERR;

  p->opt->f &= ~DIFFERENZ;
  return RET_OK;
}


Generated by  Doxygen 1.6.0   Back to index