Main Page   Compound List   File List   Compound Members   File Members  

image.c

00001 /*
00002 GOCR Copyright (C) 2000  Joerg Schulenburg Joerg.Schulenburg@physik.uni-magdeburg.de 
00003 GOCR API Copyright (C) 2001 Bruno Barberi Gnecco <brunobg@sourceforge.net>
00004 
00005 This program is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License
00007 as published by the Free Software Foundation; either version 2
00008 of the License, or (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019 */
00020 
00021 #include "config.h"
00022 #include "_gocr.h"
00023 #include "gocr.h"
00024 #include <string.h>
00025 #ifdef HAVE_PAM_H
00026 #include <pam.h>
00027 #endif
00028 #if defined HAVE_PNM_H && !defined HAVE_PAM_H
00029 #include <pnm.h>
00030 #endif
00031 
00032 gocrImage *currentimage = NULL;
00033 
00034 /* Fills the NEW image, sharing it with orig->data.
00035  */
00036 
00049 int _gocr_imageSharedCopy ( gocrImage *orig, int x0, int y0, int x1, int y1,
00050                             gocrImage *new ) {
00051   int i;
00052 
00053   _gocr_debug(3, fprintf(_data.error, 
00054       "_gocr_imageSharedCopy(%p, %d, %d, %d, %d, %p)\n", 
00055       orig, x0, y0, x1, y1, new);)
00056 
00057   if ( orig == NULL ) {
00058     _gocr_debug(1, fprintf(_data.error, "NULL pointer at _gocr_imageSharedCopy\n");)
00059     return -1;
00060   }
00061 
00062   _gocr_fixParameters ( &x0, &y0, &x1, &y1 );
00063   if ( x0 < 0 || x1 >= orig->x || y0 < 0 || y1 >= orig->y ) {
00064     _gocr_debug(1, fprintf(_data.error, "_gocr_imageSharedCopy: data OOB\n");)
00065     return -1;
00066   }
00067 
00068   if ( new == NULL ) {
00069     new = (gocrImage *)malloc(sizeof(gocrImage));
00070     if ( new == NULL ) {
00071       _gocr_debug(1, fprintf(_data.error, "gocr_imageSharedCopy NULL malloc\n");)
00072       return -1;
00073     }
00074   }
00075   else
00076     _gocr_debug(2, fprintf(_data.error, 
00077         "gocr_imageSharedCopy got a non NULL structure; memory waste may occur\n");)
00078     
00079   new->filename = NULL;
00080   new->x = x1 - x0 + 1;
00081   new->y = y1 - y0 + 1;
00082   new->type = orig->type;
00083   new->data = (gocrPixel **)malloc(new->x * sizeof(gocrPixel *));
00084   if ( new->data == NULL ) {
00085     _gocr_debug(1, fprintf(_data.error, "_gocr_imageSharedCopy: NULL malloc\n");)
00086     return -1;
00087   }
00088     
00089   for ( i = 0; i < new->x; i++ )
00090     new->data[i] = &orig->data[i + x0][y0];
00091 
00092   list_init(&new->blocklist);
00093   return 0;
00094 }
00095 
00108 /*  */
00109 int _gocr_imageCopy ( gocrImage *orig, int x0, int y0, int x1, int y1,
00110                             gocrImage *new ) {
00111   int i;
00112 
00113   _gocr_debug(3, fprintf(_data.error, 
00114       "_gocr_imageCopy(%p, %d, %d, %d, %d, %p)\n", 
00115       orig, x0, y0, x1, y1, new);)
00116 
00117   if ( orig == NULL ) {
00118     _gocr_debug(1, fprintf(_data.error, "NULL pointer at _gocr_imageCopy\n");)
00119     return -1;
00120   }
00121 
00122   _gocr_fixParameters ( &x0, &y0, &x1, &y1 );
00123   if ( x0 < 0 || x1 >= orig->x || y0 < 0 || y1 >= orig->y ) {
00124     _gocr_debug(1, fprintf(_data.error, "_gocr_imageCopy: data OOB\n");)
00125     return -1;
00126   }
00127 
00128   if ( new == NULL ) {
00129     new = (gocrImage *)malloc(sizeof(gocrImage));
00130     if ( new == NULL ) {
00131       _gocr_debug(1, fprintf(_data.error, "gocr_imageCopy NULL malloc\n");)
00132       return -1;
00133     }
00134   }
00135   new->filename = NULL;
00136   new->x = x1 - x0 + 1;
00137   new->y = y1 - y0 + 1;
00138   new->type = orig->type;
00139   new->data = (gocrPixel **)malloc(new->x * sizeof(gocrPixel *));
00140   if ( new->data == NULL ) {
00141     _gocr_debug(1, fprintf(_data.error, "_gocr_imageCopy: NULL malloc\n");)
00142     return -1;
00143   }
00144     
00145   for ( i = 0; i < new->x; i++ ) {
00146     new->data[i] = (gocrPixel *)malloc(new->y * sizeof(gocrPixel));
00147     if ( new->data[i] == NULL ) {
00148       _gocr_debug(1, fprintf(_data.error, "_gocr_imageCopy: NULL malloc[]\n");)
00149       for ( i--; i >= 0; i-- ) {
00150         free(new->data[i]);
00151         free(new);
00152       }
00153       return -1;
00154     }
00155     memcpy(new->data[i], &orig->data[i + x0][y0], new->y);
00156   }
00157 
00158   list_init(&new->blocklist);
00159   return 0;
00160 }
00161 
00171 void _gocr_fixParameters ( int *x0, int *x1, int *y0, int *y1 ) {
00172   if ( *x0 <= *x1 && *y0 <= *y1 ) /* OK */
00173     return;
00174 
00175   if ( *x0 > *x1 && *y0 > *y1 ) { /* then swap the pairs */
00176     int i;
00177     i = *x0; *x0 = *x1; *x1 = i;
00178     i = *y0; *y0 = *y1; *y1 = i;
00179     return;
00180   }
00181 
00182   if ( *x0 > *x1 && *y0 <= *y1 ) { /* correct is (x1,y0), (x0,y1) */
00183     int i;
00184     i = *x0; *x0 = *x1; *x1 = i;
00185     return;
00186   }
00187   
00188   if ( *x0 <= *x1 && *y0 > *y1 ) { /* correct is (x0,y1), (x1,y0) */
00189     int i;
00190     i = *y0; *y0 = *y1; *y1 = i;
00191     return;
00192   }
00193 }
00194 
00195 /*
00196     feel free to expand this list of usable converting programs
00197     Note 1: the last field must be NULL.
00198     Note 2: "smaller" extensions must come later: ".pnm.gz" must come
00199        before ".pnm".
00200  */
00201 static const char *xlist[]={
00202   ".pnm.gz",    "gzip -cd",
00203   ".pbm.gz",    "gzip -cd",
00204   ".pgm.gz",    "gzip -cd",
00205   ".ppm.gz",    "gzip -cd",
00206   ".pnm.bz2",   "bzip2 -cd",
00207   ".pbm.bz2",   "bzip2 -cd",
00208   ".pgm.bz2",   "bzip2 -cd",
00209   ".ppm.bz2",   "bzip2 -cd",
00210   ".jpg",       "djpeg -gray -pnm",
00211   ".jpeg",      "djpeg -gray -pnm",
00212   ".gif",       "giftopnm",
00213   ".bmp",       "bmptoppm",
00214   ".tiff",      "tifftopnm",
00215   ".png",       "pngtopnm",
00216   NULL
00217 };
00218 
00219 /* return a pointer to command converting file to pnm or NULL */
00220 static const char *testsuffix ( const char *name ) {
00221   int i;
00222 
00223   for ( i = 0; xlist[i] != NULL; i += 2 ) {
00224     if ( strstr( name, xlist[i] ) != NULL )
00225       return xlist[i+1];
00226   }
00227   return NULL;
00228 }
00229 
00238 int gocr_imageLoad ( const char *filename ) {
00239   const char *command;
00240   unsigned char **data;
00241   FILE *fp;
00242   int row, col, i;
00243 #ifdef HAVE_PAM_H
00244   struct pam inpam;
00245   tuple *tuplerow;
00246 #endif
00247 
00248   _gocr_debug(3, fprintf(_data.error, "gocr_imageLoad(%s)\n", filename);)
00249 
00250   /* open file; test if conversion is needed. */
00251   command = testsuffix( filename );
00252   if ( !command ) {
00253     fp = fopen(filename, "rb");
00254     if (!fp) {
00255       _gocr_debug(1, fprintf(_data.error, "File %s couldn't be opened\n", filename);)
00256       return -1;
00257     }
00258   }
00259   else {
00260     char *buf = (char *)malloc((strlen(command)+strlen(filename)+2)*sizeof(char));
00261 
00262     sprintf(buf, "%s %s", buf, filename);
00263     _gocr_debug(3, fprintf(_data.error, "# popen( %s )\n", buf);)
00264 #if defined(__USE_POSIX2)
00265     fp = popen(buf, "r");
00266 #else
00267     _gocr_debug(0, fprintf(_data.error, "Sorry, you must compile with __USE_POSIX2 to use pipes\n"
00268         "Cannot open this file format without pipes\n");)
00269 #endif
00270     if (!fp)
00271       _gocr_debug(1, fprintf(_data.error, "opening pipe %s\n", buf);)
00272 
00273     free(buf);
00274   }
00275 
00276   /* do we have an image? If so, close it first */
00277   if ( currentimage )
00278     gocr_imageClose();
00279 
00280   /* read file */
00281   /* Ok, I'll explain my dirty trick to save lots of memory: I cast img.data
00282     to (unsigned char **), read the image into it and filter. The monochrome
00283     conversor then is called with a threshold and takes care of filling the
00284     image.data.value fields correctly and zeroing all other fields. Confusing?
00285     Yes, a bit. But the nice method would take two times the memory we use now.
00286     Of course, a change in the size of gocrPixel is a disaster. Read the
00287     developers.txt file. */
00288 
00289   /* allocate memory */
00290   currentimage = (gocrImage *)malloc(sizeof(gocrImage));
00291   if ( currentimage == NULL ) {
00292     _gocr_debug(1, fprintf(_data.error, "gocr_loadImage NULL malloc\n");)
00293     return -1;
00294   }
00295 
00296 #ifdef HAVE_PAM_H
00297   pnm_readpaminit(fp, &inpam, sizeof(inpam));
00298 
00299   /* allocate memory for the image data */
00300   currentimage->x = inpam.height;
00301   currentimage->y = inpam.width;
00302   currentimage->data = (gocrPixel **)malloc(currentimage->x * sizeof(gocrPixel *));
00303   if ( currentimage->data == NULL ) {
00304     _gocr_debug(1, fprintf(_data.error, "_gocr_imageSharedCopy: NULL malloc\n");)
00305     fclose(fp);
00306     return -1;
00307   }
00308   for ( i = 0; i < currentimage->x; i++ )
00309     currentimage->data[i] = (gocrPixel *)malloc(currentimage->y * sizeof(gocrPixel));
00310 
00311   /* and fill it */
00312   if ( inpam.depth == 1 && strcmp(inpam.tuple_type, PAM_PBM_TUPLETYPE) == 0 ) {
00313     /* we have a PBM (Black and white) */
00314     _gocr_debug(3, fprintf(_data.error, "PBM format detected.\n");)
00315 
00316     currentimage->type = BLACK_AND_WHITE;
00317 
00318     tuplerow = pnm_allocpamrow(&inpam);
00319     for ( row = 0; row < inpam.height; row++ ) {
00320       pnm_readpamrow(&inpam, tuplerow);
00321       for ( col = 0; col < inpam.width; col++ ) {
00322         currentimage->data[row][col].value = 
00323             (tuplerow[col][0] == PAM_PBM_BLACK ? GOCR_BLACK : GOCR_WHITE );
00324       }
00325     }
00326     pnm_freepamrow(tuplerow);
00327   }
00328   else if ( inpam.depth == 1 && strcmp(inpam.tuple_type, PAM_PGM_TUPLETYPE) == 0 ) {
00329     /* we have a PGM (gray) */
00330     unsigned char **data = (unsigned char **)currentimage->data;
00331 
00332     _gocr_debug(3, fprintf(_data.error, "PGM format detected.\n");)
00333 
00334     currentimage->type = GRAY;
00335 
00336     tuplerow = pnm_allocpamrow(&inpam);
00337     for ( row = 0; row < inpam.height; row++ ) {
00338       pnm_readpamrow(&inpam, tuplerow);
00339       for ( col = 0; col < inpam.width; col++ ) {
00340         data[row][col] = tuplerow[col][0];
00341       }
00342     }
00343     pnm_freepamrow(tuplerow);
00344   } 
00345   else if ( inpam.depth == 3 && strcmp(inpam.tuple_type, PAM_PPM_TUPLETYPE) == 0 ) {
00346     /* we have a PPM (color) */
00347     _gocr_debug(3, fprintf(_data.error, "PPM format detected.\n");)
00348     _gocr_debug(0, fprintf(_data.error, "PPM format not handled yet.\n");)
00349     goto error;
00350   } 
00351   else {
00352     _gocr_debug(1, fprintf(_data.error, "Format not recognized.\n");)
00353     goto error;
00354   }
00355 #endif
00356 #if defined HAVE_PNM_H && !defined HAVE_PAM_H
00357  _gocr_debug(0, fprintf(_data.error, "PNM not coded yet. Get a newer NetPBM with pam functions.\n");)
00358 #endif
00359 
00360   currentimage->filename = strdup(filename);
00361 
00362   list_init(&currentimage->blocklist);
00363   fclose(fp);
00364 
00365   return 0;
00366 
00367 error: /* free, close, and return */
00368   fclose(fp);
00369   free(currentimage->data);
00370   free(currentimage);
00371   return -1;
00372 }
00373 
00379 void gocr_imageClose ( void ) {
00380   gocr_imageFree(currentimage);
00381 }
00382 
00390 void gocr_imageFree ( gocrImage *image ) {
00391    _gocr_debug(3, fprintf(_data.error, "gocr_imageFree(%p)\n", image);)
00392 
00393   if ( image == NULL )
00394     return;
00395 
00396   if ( image->filename )
00397     free(image->filename);
00398   if ( image->data ) {
00399     int i;
00400     
00401     for ( i = 0; i < image->x; i++ )
00402       if (image->data[i])
00403         free(image->data[i]);
00404 
00405     free(image->data);
00406   }
00407   image->x = image->y = 0;
00408   free(image);
00409 /*TODO  list_free(block)*/
00410 }
00411 
00412 /* if data == 1, print blocks and boxes frames */
00413 int _gocr_imageWrite ( gocrImage *image, char *filename, char data ) {
00414   FILE *fp;
00415 #ifdef HAVE_PAM_H
00416   struct pam outpam;
00417 #endif
00418 
00419   _gocr_debug(3, fprintf(_data.error, "_gocr_imageWrite(%p, %s)\n", image, filename);)
00420 
00421   if ( image == NULL ) {
00422     _gocr_debug(1, fprintf(_data.error, "_gocr_imageWrite: NULL image\n");)
00423     return -1;
00424   }
00425   
00426   /* open the file */
00427   if ( filename == NULL ) {
00428     filename = image->filename;
00429     if ( filename == NULL ) {
00430       _gocr_debug(1, fprintf(_data.error, "_gocr_imageWrite: NULL filename\n");)
00431       return -1;
00432     }
00433   }
00434 
00435   fp = fopen(filename, "w");
00436   if ( fp == NULL ) {
00437     _gocr_debug(1, fprintf(_data.error, "_gocr_imageWrite: file open error\n");)
00438     return -1;
00439   }
00440   
00441 #ifdef HAVE_PAM_H
00442   /* fill the pam structure */
00443   outpam.file = fp;
00444 #ifdef NOTDONEYET
00445   outpam.size = ;
00446   outpam.len = ;
00447   outpam.height = image->y;
00448   outpam.width = image->x;
00449 
00450   if ( data == 1 ) { /* output .pbm */
00451     outpam.format = PBM_FORMAT;
00452     outpam.depth = 1;
00453     outpam.maxval = 1;
00454     outpam.tuple_type = BLACKANDWHITE; 
00455   }
00456   else { /* output ppm */
00457     outpam.format = PPM_FORMAT;
00458     outpam.depth = 3;
00459     outpam.maxval = 255;
00460     outpam.tuple_type = RGB;
00461   }
00462 #endif
00463     
00464   pnm_writepaminit(&outpam);
00465   {
00466     tuple *tuplerow;
00467     int row;
00468  
00469     tuplerow = pnm_allocpamrow(&outpam);
00470     for (row = 0; row < outpam.height; row++) {
00471       /* fill row */
00472       pnm_writepamrow(&outpam, tuplerow);
00473     }
00474     pnm_freepamrow(tuplerow);
00475   }
00476 #endif
00477 #if defined HAVE_PNM_H && !defined HAVE_PAM_H
00478   if ( data == 0 ) { /* output .pbm */
00479     bit *bitrow;
00480 
00481     pbm_writepbminit(fp, image->x, image->y, 0);
00482     bitrow = pbm_allocrow(image->x);
00483     for ( i = 0; i < image->y; i++ ) {
00484       for ( j = 0; j < image->x; j++ )
00485         bitrow[j] = ( image->data[i][j].value == GOCR_BLACK ? PBM_BLACK : PBM_WHITE );
00486       pbm_writepbmrow(fp, bitrow, image->x, 0 );
00487     }
00488     pbm_freerow(bitrow);
00489   }
00490   else { /* output .ppm */
00491     pixel *pixelrow;
00492 
00493     ppm_writeppminit(fp, image->x, image->y, 255, 0);
00494     pixelrow = ppm_allocrow(image->x);
00495     for ( i = 0; i < image->y; i++ ) {
00496       for ( j = 0; j < image->x; j++ ) {
00497         /*TODO*/
00498       }
00499       ppm_writeppmrow(fp, pixelrow, image->x, 255, 0 );
00500     }
00501     ppm_freerow(pixelrow);
00502     
00503   }
00504 #endif
00505 
00506   fclose(fp);
00507 }
00508 
00519 int gocr_imageWrite ( gocrImage *image, char *filename ) {
00520   return _gocr_imageWrite( image, filename, 0 );
00521 }
00522 
00535 int gocr_imageWriteWithData ( gocrImage *image, char *filename ) {
00536   return _gocr_imageWrite( image, filename, 1 );
00537 }

Generated at Thu Mar 1 10:05:32 2001 for GOCR API by doxygen1.2.2 written by Dimitri van Heesch, © 1997-2000