00001 /*!@file Envision/env_stdio_interface.c */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Envision/env_stdio_interface.c $ 00035 // $Id: env_stdio_interface.c 12962 2010-03-06 02:13:53Z irock $ 00036 // 00037 00038 #ifndef ENVISION_ENV_STDIO_INTERFACE_C_DEFINED 00039 #define ENVISION_ENV_STDIO_INTERFACE_C_DEFINED 00040 00041 #include "Envision/env_stdio_interface.h" 00042 00043 #include "Envision/env_alloc.h" 00044 #include "Envision/env_image.h" 00045 #include "Envision/env_log.h" 00046 00047 #include <ctype.h> 00048 #include <errno.h> 00049 #include <stdarg.h> 00050 #include <stdio.h> // for fprintf() 00051 #include <stdlib.h> // for abort() 00052 #include <string.h> // for strerror() 00053 00054 // ###################################################################### 00055 static void lfatal(const char *msg, ...) 00056 __attribute__((format(__printf__,1,2))); 00057 00058 static void lfatal(const char *msg, ...) 00059 { 00060 va_list args; 00061 va_start(args, msg); 00062 00063 vfprintf(stderr, msg, args); 00064 00065 va_end(args); 00066 00067 fprintf(stderr, "\n"); 00068 fflush(stderr); 00069 00070 abort(); 00071 } 00072 00073 // ###################################################################### 00074 static void div2(const env_size_t numer, const env_size_t denom, 00075 const env_size_t ndigits, 00076 env_size_t* const whole, env_size_t* const fract) 00077 { 00078 *whole = numer / denom; 00079 *fract = 0; 00080 env_size_t rem = numer - (*whole * denom); 00081 for (env_size_t i = 0; i < ndigits; ++i) 00082 { 00083 rem *= 10; 00084 const env_size_t newwhole = rem / denom; 00085 ENV_ASSERT(newwhole < 10); 00086 rem = rem - (newwhole * denom); 00087 *fract *= 10; 00088 *fract += newwhole; 00089 } 00090 } 00091 00092 // ###################################################################### 00093 void env_stdio_assert_handler(const char* what, int custom_msg, 00094 const char* where, int line_no) 00095 { 00096 if (custom_msg) 00097 fprintf(stderr, "Assertion failed (%s:%d):\n\t%s\n\n", 00098 where, line_no, what); 00099 else 00100 fprintf(stderr, "Assertion failed (%s:%d):\n\texpected '%s'\n\n", 00101 where, line_no, what); 00102 abort(); 00103 } 00104 00105 // ###################################################################### 00106 void env_stdio_print_alloc_stats(const struct env_alloc_stats* p, 00107 const env_size_t block_size) 00108 { 00109 env_size_t kiB_block_size_whole, kiB_block_size_fract; 00110 div2(block_size, 1024, 2, 00111 &kiB_block_size_whole, &kiB_block_size_fract); 00112 00113 ENV_ASSERT(block_size > 0); 00114 00115 env_size_t n_cache_blocks = 0; 00116 00117 for (env_size_t i = 0; i < p->ncache_used; ++i) 00118 { 00119 const env_size_t nb = 00120 (p->cache[i].num_allocations 00121 * p->cache[i].alloc_size); 00122 00123 n_cache_blocks += p->cache[i].num_allocations; 00124 00125 env_size_t kiB_alloc_whole, kiB_alloc_fract; 00126 div2(nb, 1024, 2, 00127 &kiB_alloc_whole, &kiB_alloc_fract); 00128 00129 env_size_t kiB_alloc_size_whole, kiB_alloc_size_fract; 00130 div2(p->cache[i].alloc_size, 1024, 4, 00131 &kiB_alloc_size_whole, &kiB_alloc_size_fract); 00132 00133 env_size_t alloc_percent_whole, alloc_percent_fract; 00134 div2(nb*100, p->bytes_allocated, 2, 00135 &alloc_percent_whole, &alloc_percent_fract); 00136 00137 env_size_t block_ratio_whole, block_ratio_fract; 00138 char symbol; 00139 00140 if (p->cache[i].alloc_size - p->overhead >= block_size 00141 || p->cache[i].alloc_size - p->overhead <= 1) 00142 { 00143 div2(p->cache[i].alloc_size - p->overhead, 00144 block_size, 1, 00145 &block_ratio_whole, &block_ratio_fract); 00146 symbol = '*'; 00147 } 00148 else 00149 { 00150 div2(block_size, 00151 p->cache[i].alloc_size - p->overhead, 1, 00152 &block_ratio_whole, &block_ratio_fract); 00153 symbol = '/'; 00154 } 00155 00156 fprintf(stderr, 00157 "memstats: cache[%02lu/%02lu]: " 00158 "%5lu.%02lukiB (%3lu.%02lu%%) " 00159 "in %4lu allocations " 00160 "(%2lu active) of %5lu.%04lukiB" 00161 " (%lu.%02lukiB %c %5lu.%01lu + %2luB)\n", 00162 i, ENV_NCACHE, 00163 kiB_alloc_whole, kiB_alloc_fract, 00164 alloc_percent_whole, alloc_percent_fract, 00165 p->cache[i].num_allocations, 00166 p->cache[i].num_active, 00167 kiB_alloc_size_whole, kiB_alloc_size_fract, 00168 kiB_block_size_whole, kiB_block_size_fract, 00169 (int) symbol, 00170 block_ratio_whole, block_ratio_fract, 00171 p->overhead); 00172 } 00173 00174 env_size_t kiB_alloc_whole, kiB_alloc_fract; 00175 div2(p->bytes_allocated, 1024, 2, 00176 &kiB_alloc_whole, &kiB_alloc_fract); 00177 00178 env_size_t n_blocks_whole, n_blocks_fract; 00179 div2(p->bytes_allocated, block_size, 1, 00180 &n_blocks_whole, &n_blocks_fract); 00181 00182 fprintf(stderr, 00183 "memstats: =====[TOTAL]: " 00184 "%5lu.%02lukiB (100.00%%) " 00185 "in %4lu allocations " 00186 "(%2lu active) ================" 00187 " (%lu.%02lukiB * %5lu.%01lu )\n", 00188 kiB_alloc_whole, kiB_alloc_fract, 00189 n_cache_blocks, 00190 p->nallocations_current, 00191 kiB_block_size_whole, kiB_block_size_fract, 00192 n_blocks_whole, n_blocks_fract); 00193 00194 fprintf(stderr, 00195 "memstats: %lu/%lu cache table entries in use\n", 00196 p->ncache_used, ENV_NCACHE); 00197 00198 fprintf(stderr, 00199 "memstats: block alignment: %lu bytes\n", p->nalign); 00200 00201 fprintf(stderr, 00202 "memstats: all-time: %llukiB in %lu requested allocations\n", 00203 p->nbytes_alltime/1024, p->nallocations_alltime); 00204 00205 fprintf(stderr, 00206 "memstats: current: %lukiB in %lu active allocations\n", 00207 (unsigned long)(p->nbytes_current/1024), 00208 p->nallocations_current); 00209 } 00210 00211 // ###################################################################### 00212 struct env_rgb_pixel* env_stdio_parse_rgb(const char* fname, 00213 struct env_dims* outdims) 00214 { 00215 FILE* f = fopen(fname, "rb"); 00216 00217 if (f == 0) 00218 lfatal("Couldn't open file '%s' for reading.", fname); 00219 00220 int c = getc(f); 00221 if (c != 'P') 00222 lfatal("Missing magic number in pnm file '%s'" 00223 "(got '%c' [%d], expected '%c' [%d]).", 00224 fname, c, c, 'P', 'P'); 00225 00226 int mode = -1; 00227 int ret = fscanf(f, "%d", &mode); 00228 if (ret > 0 && mode != 6) 00229 lfatal("Wrong pnm mode (got 'P%d', expected 'P6')", 00230 mode); 00231 00232 while (1) 00233 { 00234 const int c = getc(f); 00235 if (!isspace(c)) 00236 { ungetc(c, f); break; } 00237 } 00238 00239 // copy and concatenate optional comment line(s) starting with '#' 00240 // into comments string 00241 00242 while (1) 00243 { 00244 const int c = getc(f); 00245 if (c != '#') 00246 { ungetc(c, f); break; } 00247 else 00248 { 00249 while (getc(f) != '\n') 00250 { /* empty loop */ } 00251 } 00252 } 00253 00254 int w = -1; 00255 int h = -1; 00256 int maxGrey = -1; 00257 ret = fscanf(f, "%d %d %d", &w, &h, &maxGrey); 00258 ENV_ASSERT(ret > 0); 00259 ENV_ASSERT(w > 0); 00260 ENV_ASSERT(h > 0); 00261 ENV_ASSERT(maxGrey > 0); 00262 00263 // read one more character of whitespace from the stream after maxGrey 00264 c = getc(f); 00265 if ( !isspace(c) ) 00266 lfatal("Missing whitespace after maxGrey in pbm file '%s'.", fname); 00267 00268 struct env_rgb_pixel* result = (struct env_rgb_pixel*) 00269 env_allocate(w * h * sizeof(struct env_rgb_pixel)); 00270 if (fread((char*) result, 3, w*h, f) != ((env_size_t)(w*h))) 00271 lfatal("%s: fread() failed", fname); 00272 outdims->w = w; 00273 outdims->h = h; 00274 return result; 00275 } 00276 00277 // ###################################################################### 00278 void env_stdio_write_gray(const struct env_image* iimage, 00279 const char* outstem, const char* name, int c) 00280 { 00281 if (!env_img_initialized(iimage)) 00282 return; 00283 00284 // if outstem is the empty string, then the user wanted us to 00285 // suppress output: 00286 if (outstem[0] == '\0') 00287 return; 00288 00289 char fname[256]; 00290 snprintf(fname, sizeof(fname), 00291 "%s-%s%06d.pnm", outstem, name, c); 00292 00293 FILE* const f = fopen(fname, "wb"); 00294 if (f == 0) 00295 lfatal("%s: couldn't open PNM file for writing (errno=%d, %s)", 00296 fname, errno, strerror(errno)); 00297 00298 if (fprintf(f, "P5\n%d %d\n255\n", 00299 (int) iimage->dims.w, (int) iimage->dims.h) < 0) 00300 lfatal("%s: fprintf() failed (errno=%d, %s)", 00301 fname, errno, strerror(errno)); 00302 00303 const intg32* const src = env_img_pixels(iimage); 00304 const env_size_t sz = env_img_size(iimage); 00305 byte* bimage = 00306 (byte*) env_allocate(sz * sizeof(byte)); 00307 00308 for (env_size_t i = 0; i < sz; ++i) 00309 { 00310 // the caller is supposed to have already ensured that 00311 // the intg32 image has been downsampled to a [0,255] 00312 // range, so let's verify that: 00313 ENV_ASSERT(src[i] >= 0 && src[i] <= 255); 00314 bimage[i] = (byte) src[i]; 00315 } 00316 00317 if (fwrite(bimage, 1, sz, f) != sz) 00318 { 00319 env_deallocate(bimage); 00320 lfatal("%s: fwrite() failed (errno=%d, %s)", 00321 fname, errno, strerror(errno)); 00322 } 00323 00324 env_deallocate(bimage); 00325 00326 if (fclose(f) != 0) 00327 lfatal("%s: fclose() failed (errno=%d, %s)", 00328 fname, errno, strerror(errno)); 00329 } 00330 00331 // ###################################################################### 00332 /* So things look consistent in everyone's emacs... */ 00333 /* Local Variables: */ 00334 /* indent-tabs-mode: nil */ 00335 /* c-file-style: "linux" */ 00336 /* End: */ 00337 00338 #endif // ENVISION_ENV_STDIO_INTERFACE_C_DEFINED