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

paulspec.c

/*****************************************************************************
 *                                                                           *
 * Program:   paul                                                           *
 *            (P)rogramm zur (A)uswertung und (U)mformung von                *
 *            (L)aserbildern                                                 *
 * Modul:     paulspec.c                                                     *
 *            Some utilities for the image specification                     *
 * Author:    Andreas Tille                                                  *
 * Date:      25.05.1998                                                     *
 * Copyright: Andreas Tille, 1999; GNU Public License                        *
 *                                                                           *
 *****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

#include "paul.h"

char TypAusschnitt[]        = "Cut section",
     TypDelRand[]           = "Border deleted",
     TypDelScanRand[]       = "Scanner border deleted",
     TypDifferenzBild[]     = "Difference",
     TypFilter[]            = "Filter",
     TypFFT[]               = "FFT",
     TypGray[]              = "Monochrom",
     TypInsert[]            = "Image insertion",
     TypKontrastBild[]      = "Contrast",
     TypNegativ[]           = "Negativ",
     TypMove[]              = "Moved",
     TypMirror[]            = "Mirrored",
     TypRotate[]            = "Rotated",
     TypScan[]              = "Scan",
     TypShrink[]            = "Shrinked";

const char 
     ChunkNameSource[]      = "Source",
     ChunkNameSoftware[]    = "Software",
     ChunkNameTyp[]         = "Typ",
     ChunkNameDescription[] = "Description",
     ChunkNameAuthor[]      = "Author",
     ChunkFilmType[]        = "Film type",
     ChunkBrightness[]      = "Brightness",
     ChunkContrast[]        = "Contrast",
#ifdef PHYSICAL_PAUL
     ChunkPhysicalDataFile[]= "Physical",
     ChunkPhi[]             = "Phi",
     ChunkRelTime[]         = "RelTime",
#endif
     ChunkReferenceFile[]   = "Referenzdatei";

int Char2Chunk(CHUNK *chunk, char *buf)
/* set chunk value from string
 * --- Parameter: ---
 * CHUNK *chunk       : Chunk with value
 * --- Return: ---
 * char  *Char2Chunk(): RET_ERR or RET_OK
 */
{
  switch ( chunk->typ ) {
  case CT_INT:
    chunk->val.i = atoi(buf);
    return RET_OK;
  case CT_DOUBLE:
    chunk->val.d = atof(buf);
    return RET_OK;
  case CT_STRING: 
    FREE( chunk->val.s );
    chunk->val.s = g_strdup(buf);
    return RET_OK;
  default:
    return RET_ERR;
  }
}

char *Chunk2Char(CHUNK *chunk)
/* get allocated string from chunk value
 * --- Parameter: ---
 * CHUNK *chunk       : Chunk with value
 * --- Return: ---
 * char  *Chunk2Char(): Allocated string or NULL
 */
{
  if ( !IsValid(chunk) ) return NULL;
   
  switch ( chunk->typ ) {
    case CT_LTEXT:
    case CT_STRING: if ( chunk->val.s ) return g_strdup(chunk->val.s);
    case CT_INT:    return g_strdup_printf("%i", chunk->val.i);
    case CT_DOUBLE: return g_strdup_printf("%g", chunk->val.d);
  }
  return NULL;
}

int Chunk2Double(CHUNK *chunks, const char *key, double *val)
/* get double value from chunk value
 * --- Parameter: ---
 * CHUNK  *chunks        : Chunks with values
 * const   char  *key    : key of value to get
 * double *val           : pointer to double value
 * --- Return: ---
 * double *val           : value of chunk if of type CT_INT or CT_DOUBLE
 * char   *Chunk2Double(): RET_ERR or RET_OK
 */
{
  CHUNK *ap;

  for ( ap = chunks; ap->key != NULL; ap++ )
    if ( !strcmp(ap->key, key) ) {
      if ( !IsValid(ap) ) return RET_ERR;
   
      switch ( ap->typ ) {
        case CT_LTEXT:
        case CT_STRING: return RET_ERR;
        case CT_INT:    *val = (double)(ap->val.i);
                        break;
        case CT_DOUBLE: *val = ap->val.d;
                        break;
        default:        return RET_ERR;
      }
      return RET_OK;
    }
  
  return RET_ERR;
}

void CopyChunk(CHUNK *dest, CHUNK *src)
{
  dest->key = src->key;
  switch ( (dest->typ = src->typ) ) {
    case CT_LTEXT:
    case CT_STRING: if ( !(src->val.s) ) dest->val.s = NULL;
                    else                 dest->val.s = g_strdup(src->val.s);
                    break;
    case CT_INT:    dest->val.i = src->val.i;
                    break;
    case CT_DOUBLE: dest->val.d = src->val.d;
                  break;
  }
  dest->flag = src->flag;
}

char *GetCharSpec(CHUNK *chunks, const char *spec)
/* Read Spezifikation parameter
 * --- Parameter: ---
 * CHUNK      *chunks: all chunks with specifying data
 * const char *spec  : name of chunk to get
 * --- Return: ---
 * char  *GetSpec    : value of chunk to get or NULL if not existing
 */
{
  CHUNK *ap;

  g_return_val_if_fail ( chunks, NULL );
  
  for ( ap = chunks; ap->key != NULL; ap++ )
    if ( !strcmp(ap->key, spec) && 
         ( ap->typ == CT_LTEXT || ap->typ == CT_STRING ) ) 
      return ap->val.s;
  return NULL;
}


int CopySpec(CHUNK *chunks, const char *spec, C_VALUE value)
/* Copy spezification parameter
 * --- Parameter: ---
 * CHUNK      *chunks     : all Chunks
 * const char *spec       : name of chunk to set
 * C_VALUE    *value      : Value of Chunk to copy
 * --- Return: ---
 * CHUNK      *chunks     : new set chunk with NEW ALLOCATED memory in case of string values
 * char       *CopySpec() : RET_OK, RET_ERR if chunk dosn't exist
 */
{
  CHUNK *ap;
  char  *zw;

  for ( ap = chunks; ap->key != NULL; ap++ )
    if ( !strcmp(ap->key, spec) ) {
      if ( spec == ChunkNameDescription && ap->val.s ) {
        zw = ap->val.s;
        ap->val.s = g_strconcat(zw, "\n", value.s, NULL);
        FREE(zw);
      } else if ( spec == ChunkNameTyp && ap->val.s ) {
        if ( !strstr(ap->val.s, value.s) ) {
          zw = ap->val.s;         
          ap->val.s = g_strconcat(zw, "; ", value.s, NULL);
          FREE(zw);
      }
      } else {
      switch ( ap->typ ) {
      case CT_LTEXT:
        case CT_STRING: FREE(ap->val.s);
                        ap->val.s = g_strdup(value.s);
                        break;
        case CT_INT:    ap->val.i = value.i;
                      break;
        case CT_DOUBLE: ap->val.d = value.d;
                      break;
        }
      }
      ap->flag |= VALID;
      return RET_OK;
    }
  return RET_ERR;
}

int SetSpec(CHUNK *chunks, const char *spec, char *buf)
/* Set spezification parameter from string buffer
 * --- Parameter: ---
 * CHUNK      *chunks    : all Chunks
 * const char *spec      : name of chunk to set
 * char       *buf       : string with value
 * --- Return: ---
 * CHUNK      *chunks    : new set chunk with NEW ALLOCATED memory in case of string values
 * char       *SetSpec() : RET_OK, RET_ERR if chunk dosn't exist
 */
{
  CHUNK   *ap;
  C_VALUE  cv;

  cv.s = buf;
  for ( ap = chunks; ap->key != NULL; ap++ )
    if ( !strcmp(ap->key, spec) ) {
      if ( ap->typ == CT_LTEXT || ap->typ == CT_STRING ) 
        CopySpec(ap, spec, cv);
              /* ^^ don't double the code of CopySpec() but make use of the found      *
               *    value and foreward ap directly to avoid checking the chunks before */
      else
        Char2Chunk(ap, buf);

      ap->flag |= VALID;
      return RET_OK;
    }
  return RET_ERR;
}

int SetDoubleSpec(CHUNK *chunks, const char *spec, double d)
/* Set spezification parameter from string buffer
 * --- Parameter: ---
 * CHUNK      *chunks    : all Chunks
 * const char *spec      : name of chunk to set
 * char       *buf       : string with value
 * --- Return: ---
 * CHUNK      *chunks    : new set chunk with NEW ALLOCATED memory in case of string values
 * char       *SetSpec() : RET_OK, RET_ERR if chunk dosn't exist
 */
{
  CHUNK *ap;

  for ( ap = chunks; ap->key != NULL; ap++ )
    if ( !strcmp(ap->key, spec) ) {
      switch ( ap->typ ) {
      case CT_LTEXT:
        case CT_STRING:  return RET_ERR;
        case CT_INT:    ap->val.i = (int)d;
                      break;
        case CT_DOUBLE: ap->val.d = d;
                      break;
      }

      ap->flag |= VALID;
      return RET_OK;
    }
  return RET_ERR;
}

int SpecIsValid(CHUNK *chunks, const char *key)
/* check validity of a specification in a set of given chunks
 * --- Parameter: ---
 * CHUNK      *chunks        : Set of chunks
 * const char *key           : specification key
 * --- Return: ---
 * int         SpecIsValid() : valid value of the specified chunk
 */
{
  CHUNK *sp;

  for ( sp = chunks; sp->key != NULL; sp++ ) 
    if ( !strcmp(sp->key, key) ) return IsValid(sp);
  return INVALID;
}


PICTURE *InitSpec(void)
/* Initialise spezifikation parameter
 * --- Return: ---
 * PICTURE *InitSpec() : bild initialised
 */
{
  int      nchunks;
  PICTURE *bild;
  CHUNK   *ap, *sp,
           ChunkPredef[] = { {ChunkNameSource,       {NULL}, CT_STRING, INVALID} ,
                             {ChunkNameSoftware,     {NULL}, CT_STRING, INVALID} ,
                             {ChunkNameTyp,          {NULL}, CT_STRING, INVALID} ,
                             {ChunkNameDescription,  {NULL}, CT_LTEXT,  INVALID} ,
                             {ChunkNameAuthor,       {NULL}, CT_STRING, INVALID} ,
                             {ChunkFilmType,         {NULL}, CT_STRING, INVALID} ,
                             {ChunkBrightness,       {NULL}, CT_STRING, INVALID} ,
                             {ChunkContrast,         {NULL}, CT_STRING, INVALID} ,
#ifdef PHYSICAL_PAUL
                             {ChunkPhysicalDataFile, {NULL}, CT_STRING, EDITABLE} ,
                             {ChunkPhi,              {0},    CT_DOUBLE, EDITABLE} ,
                             {ChunkRelTime,          {0},    CT_DOUBLE, EDITABLE} ,
#endif
                             {ChunkReferenceFile,    {NULL}, CT_STRING, INVALID} ,
                             {NULL,                  {NULL}, 0,         INVALID} ,
                           };
   
  bild           = g_new(PICTURE, 1);
  bild->id       = PICTURE_ID;
  bild->im       = NULL;
  bild->W        = 0;
  bild->H        = 0;
  bild->DATA     = NULL;
  bild->file     = NULL;
  bild->ext      = NULL;
  bild->dir      = NULL;
  bild->size     = 0;
  bild->mark     = 0;
  bild->spp      = 3; /* at first assume RGB image at any case                                  */
  bild->storepix = 3; /* paul uses 3 byte per pixel; paulscan has to set storepix explicitely!! */
  bild->trans    = 0;
  bild->res      = 0;
  bild->x_offset = bild->y_offset = (unsigned long)-1;
  bild->n_gamma  = 0;
  bild->gamma    = NULL;
  bild->his      = NULL;
#ifdef HAVE_LIBFFTW
  bild->fftprof  = NULL;
#endif
  bild->zeit     = 0;
  bild->roff_x   = bild->roff_y   = 0;
  bild->flag     = 0;
  nchunks = sizeof(ChunkPredef) / sizeof(ChunkPredef[0]);
  bild->spec     = g_new0(CHUNK, nchunks);
  for ( ap = bild->spec, sp = ChunkPredef; sp->key != NULL; ap++, sp++ )
    CopyChunk(ap, sp);
  ap->key        = NULL;

  return bild;
}

time_t convert_png_time_to_time_t(png_time *ptime)
/* convert png_time struktur into time_t
 * --- Parameter: ---
 * png_time *zeit                       : png_time to convert
 * --- Return: ---
 * time_t   convert_png_time_to_time_t(): converted time
 */
{
  struct tm ttime;

  ttime.tm_year = ptime->year  - 1900;
  ttime.tm_mon  = ptime->month - 1;
  ttime.tm_mday = ptime->day;
  ttime.tm_hour = ptime->hour;
  ttime.tm_min  = ptime->minute;
  ttime.tm_sec  = ptime->second;

  return mktime(&ttime);
}

int NumValidChunks(CHUNK *chunks)
/* calculate number of valid chunks
 * --- Parameter: ---
 * CHUNK *chunk            : Chunks
 * --- Return: ---
 * int    NumValidChunks() : number of valid chunks
 */
{
  int    nchunks = 0;
  CHUNK *sp;
   
  for ( sp = chunks; sp->key != NULL; sp++ ) 
    if ( IsValid(sp) ) nchunks++;
  return nchunks;
}


static void GetPictureSource(PICTURE *bild)
/* obtain source of image (scanner, filename, source tag stored in file)
 * --- Parameter: ---
 * PICTURE    *bild     : image
 */
{
  C_VALUE  cv;

  if ( GetCharSpec(bild->spec, ChunkNameSource) ) return;
  cv.s = bild->file;
  CopySpec(bild->spec, ChunkNameSource, cv);
}


static void GetPictureTime(PICTURE *bild, char *file)
/* obtain time of picture creation (creation of file, tag inside file)
 * --- Parameter: ---
 * PICTURE    *bild     : image
 * char       *file     : filename of image (bild->file can not be used because the extension was
 *                        removed before)
 */
{
  struct    stat stat_buf;

  if ( bild->zeit > 0 ) return;
  if ( file && !stat(file, &stat_buf) ) bild->zeit = stat_buf.st_mtime;
  else                                  bild->zeit = time(NULL);
}


void GetPictureAuthor(PICTURE *bild)
/* How is using paul??
 * --- Parameter: ---
 * PICTURE    *bild : image
 */
{
  gchar   *s;
  C_VALUE  cv;
  
  g_return_if_fail ( IS_PICTURE(bild) );
  
  if ( GetCharSpec(bild->spec, ChunkNameAuthor) ) return;
  if ( (cv.s = g_get_real_name()) ) {
    if ( ( s = strchr(cv.s, ',')) ) *s = 0;
  } else
    cv.s = g_get_user_name();

  CopySpec(bild->spec, ChunkNameAuthor, cv);
}


void GetPictureSpecs(PICTURE *bild, char *file)
/* obtain all specification chunks of picture
 * --- Parameter: ---
 * PICTURE    *bild     : image
 * char       *file     : filename of image (bild->file cant be used because the extension was
 *                        removed before)
 */
{
  GetPictureAuthor(bild);
  if ( file ) GetPictureSource(bild);
  GetPictureTime(bild, file);
  if ( !GetCharSpec(bild->spec, ChunkNameSoftware) ) {
    C_VALUE  cv;

    cv.s = (char *)exename;
    CopySpec(bild->spec, ChunkNameSoftware, cv);
  }
}

void CreateDescription(PICTURE *bild, char *what)
/* Create image description
 * what+when
 * --- Parameter: ---
 * PICTURE *bild : image structure
 * char    *what : what was done with the image
 * --- Return: ---
 * PICTURE *bild : bild->spec ChunkNameDescription created
 */
{
  C_VALUE cv;
  time_t  t;

  g_return_if_fail( IS_PICTURE(bild) );
  
  if ( what == NULL ) what = "";
  t = time(NULL);
  cv.s = g_strdup_printf("%s (%s)", what, time_t2string(t));
  g_return_if_fail ( !CopySpec(bild->spec, ChunkNameDescription, cv) );
  FREE(cv.s);
}
                   



Generated by  Doxygen 1.6.0   Back to index