Leptonica  1.77.0
Image processing and image analysis suite
utils1.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
99 #ifdef HAVE_CONFIG_H
100 #include "config_auto.h"
101 #endif /* HAVE_CONFIG_H */
102 
103 #ifdef _WIN32
104 #include <windows.h>
105 #endif /* _WIN32 */
106 
107 #include <time.h>
108 #include "allheaders.h"
109 #include <math.h>
110 
111  /* Global for controlling message output at runtime */
112 LEPT_DLL l_int32 LeptMsgSeverity = DEFAULT_SEVERITY;
113 
114 #define DEBUG_SEV 0
115 
116 /*----------------------------------------------------------------------*
117  * Control of error, warning and info messages *
118  *----------------------------------------------------------------------*/
135 l_int32
136 setMsgSeverity(l_int32 newsev)
137 {
138 l_int32 oldsev;
139 char *envsev;
140 
141  PROCNAME("setMsgSeverity");
142 
143  oldsev = LeptMsgSeverity;
144  if (newsev == L_SEVERITY_EXTERNAL) {
145  envsev = getenv("LEPT_MSG_SEVERITY");
146  if (envsev) {
147  LeptMsgSeverity = atoi(envsev);
148 #if DEBUG_SEV
149  L_INFO("message severity set to external\n", procName);
150 #endif /* DEBUG_SEV */
151  } else {
152 #if DEBUG_SEV
153  L_WARNING("environment var LEPT_MSG_SEVERITY not defined\n",
154  procName);
155 #endif /* DEBUG_SEV */
156  }
157  } else {
158  LeptMsgSeverity = newsev;
159 #if DEBUG_SEV
160  L_INFO("message severity set to %d\n", procName, newsev);
161 #endif /* DEBUG_SEV */
162  }
163 
164  return oldsev;
165 }
166 
167 
168 /*----------------------------------------------------------------------*
169  * Error return functions, invoked by macros *
170  * *
171  * (1) These error functions print messages to stderr and allow *
172  * exit from the function that called them. *
173  * (2) They must be invoked only by the macros ERROR_INT, *
174  * ERROR_FLOAT and ERROR_PTR, which are in environ.h *
175  * (3) The print output can be disabled at compile time, either *
176  * by using -DNO_CONSOLE_IO or by setting LeptMsgSeverity. *
177  *----------------------------------------------------------------------*/
186 l_int32
187 returnErrorInt(const char *msg,
188  const char *procname,
189  l_int32 ival)
190 {
191  fprintf(stderr, "Error in %s: %s\n", procname, msg);
192  return ival;
193 }
194 
195 
204 l_float32
205 returnErrorFloat(const char *msg,
206  const char *procname,
207  l_float32 fval)
208 {
209  fprintf(stderr, "Error in %s: %s\n", procname, msg);
210  return fval;
211 }
212 
213 
222 void *
223 returnErrorPtr(const char *msg,
224  const char *procname,
225  void *pval)
226 {
227  fprintf(stderr, "Error in %s: %s\n", procname, msg);
228  return pval;
229 }
230 
231 
232 /*--------------------------------------------------------------------*
233  * Test files for equivalence *
234  *--------------------------------------------------------------------*/
243 l_ok
244 filesAreIdentical(const char *fname1,
245  const char *fname2,
246  l_int32 *psame)
247 {
248 l_int32 i, same;
249 size_t nbytes1, nbytes2;
250 l_uint8 *array1, *array2;
251 
252  PROCNAME("filesAreIdentical");
253 
254  if (!psame)
255  return ERROR_INT("&same not defined", procName, 1);
256  *psame = 0;
257  if (!fname1 || !fname2)
258  return ERROR_INT("both names not defined", procName, 1);
259 
260  nbytes1 = nbytesInFile(fname1);
261  nbytes2 = nbytesInFile(fname2);
262  if (nbytes1 != nbytes2)
263  return 0;
264 
265  if ((array1 = l_binaryRead(fname1, &nbytes1)) == NULL)
266  return ERROR_INT("array1 not read", procName, 1);
267  if ((array2 = l_binaryRead(fname2, &nbytes2)) == NULL) {
268  LEPT_FREE(array1);
269  return ERROR_INT("array2 not read", procName, 1);
270  }
271  same = 1;
272  for (i = 0; i < nbytes1; i++) {
273  if (array1[i] != array2[i]) {
274  same = 0;
275  break;
276  }
277  }
278  LEPT_FREE(array1);
279  LEPT_FREE(array2);
280  *psame = same;
281 
282  return 0;
283 }
284 
285 
286 /*--------------------------------------------------------------------------*
287  * 16 and 32 bit byte-swapping on big endian and little endian machines *
288  * *
289  * These are typically used for I/O conversions: *
290  * (1) endian conversion for data that was read from a file *
291  * (2) endian conversion on data before it is written to a file *
292  *--------------------------------------------------------------------------*/
293 
294 /*--------------------------------------------------------------------*
295  * 16-bit byte swapping *
296  *--------------------------------------------------------------------*/
297 #ifdef L_BIG_ENDIAN
298 
299 l_uint16
300 convertOnBigEnd16(l_uint16 shortin)
301 {
302  return ((shortin << 8) | (shortin >> 8));
303 }
304 
305 l_uint16
306 convertOnLittleEnd16(l_uint16 shortin)
307 {
308  return shortin;
309 }
310 
311 #else /* L_LITTLE_ENDIAN */
312 
313 l_uint16
314 convertOnLittleEnd16(l_uint16 shortin)
315 {
316  return ((shortin << 8) | (shortin >> 8));
317 }
318 
319 l_uint16
320 convertOnBigEnd16(l_uint16 shortin)
321 {
322  return shortin;
323 }
324 
325 #endif /* L_BIG_ENDIAN */
326 
327 
328 /*--------------------------------------------------------------------*
329  * 32-bit byte swapping *
330  *--------------------------------------------------------------------*/
331 #ifdef L_BIG_ENDIAN
332 
333 l_uint32
334 convertOnBigEnd32(l_uint32 wordin)
335 {
336  return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
337  ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
338 }
339 
340 l_uint32
341 convertOnLittleEnd32(l_uint32 wordin)
342 {
343  return wordin;
344 }
345 
346 #else /* L_LITTLE_ENDIAN */
347 
348 l_uint32
349 convertOnLittleEnd32(l_uint32 wordin)
350 {
351  return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
352  ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
353 }
354 
355 l_uint32
356 convertOnBigEnd32(l_uint32 wordin)
357 {
358  return wordin;
359 }
360 
361 #endif /* L_BIG_ENDIAN */
362 
363 
364 /*---------------------------------------------------------------------*
365  * File corruption operations *
366  *---------------------------------------------------------------------*/
387 l_ok
388 fileCorruptByDeletion(const char *filein,
389  l_float32 loc,
390  l_float32 size,
391  const char *fileout)
392 {
393 l_int32 i, locb, sizeb, rembytes;
394 size_t inbytes, outbytes;
395 l_uint8 *datain, *dataout;
396 
397  PROCNAME("fileCorruptByDeletion");
398 
399  if (!filein || !fileout)
400  return ERROR_INT("filein and fileout not both specified", procName, 1);
401  if (loc < 0.0 || loc >= 1.0)
402  return ERROR_INT("loc must be in [0.0 ... 1.0)", procName, 1);
403  if (size <= 0.0)
404  return ERROR_INT("size must be > 0.0", procName, 1);
405  if (loc + size > 1.0)
406  size = 1.0 - loc;
407 
408  datain = l_binaryRead(filein, &inbytes);
409  locb = (l_int32)(loc * inbytes + 0.5);
410  locb = L_MIN(locb, inbytes - 1);
411  sizeb = (l_int32)(size * inbytes + 0.5);
412  sizeb = L_MAX(1, sizeb);
413  sizeb = L_MIN(sizeb, inbytes - locb); /* >= 1 */
414  L_INFO("Removed %d bytes at location %d\n", procName, sizeb, locb);
415  rembytes = inbytes - locb - sizeb; /* >= 0; to be copied, after excision */
416 
417  outbytes = inbytes - sizeb;
418  dataout = (l_uint8 *)LEPT_CALLOC(outbytes, 1);
419  for (i = 0; i < locb; i++)
420  dataout[i] = datain[i];
421  for (i = 0; i < rembytes; i++)
422  dataout[locb + i] = datain[locb + sizeb + i];
423  l_binaryWrite(fileout, "w", dataout, outbytes);
424 
425  LEPT_FREE(datain);
426  LEPT_FREE(dataout);
427  return 0;
428 }
429 
430 
451 l_ok
452 fileCorruptByMutation(const char *filein,
453  l_float32 loc,
454  l_float32 size,
455  const char *fileout)
456 {
457 l_int32 i, locb, sizeb;
458 size_t bytes;
459 l_uint8 *data;
460 
461  PROCNAME("fileCorruptByMutation");
462 
463  if (!filein || !fileout)
464  return ERROR_INT("filein and fileout not both specified", procName, 1);
465  if (loc < 0.0 || loc >= 1.0)
466  return ERROR_INT("loc must be in [0.0 ... 1.0)", procName, 1);
467  if (size <= 0.0)
468  return ERROR_INT("size must be > 0.0", procName, 1);
469  if (loc + size > 1.0)
470  size = 1.0 - loc;
471 
472  data = l_binaryRead(filein, &bytes);
473  locb = (l_int32)(loc * bytes + 0.5);
474  locb = L_MIN(locb, bytes - 1);
475  sizeb = (l_int32)(size * bytes + 0.5);
476  sizeb = L_MAX(1, sizeb);
477  sizeb = L_MIN(sizeb, bytes - locb); /* >= 1 */
478  L_INFO("Randomizing %d bytes at location %d\n", procName, sizeb, locb);
479 
480  /* Make an array of random bytes and do the substitution */
481  for (i = 0; i < sizeb; i++) {
482  data[locb + i] =
483  (l_uint8)(255.9 * ((l_float64)rand() / (l_float64)RAND_MAX));
484  }
485 
486  l_binaryWrite(fileout, "w", data, bytes);
487  LEPT_FREE(data);
488  return 0;
489 }
490 
491 
492 /*---------------------------------------------------------------------*
493  * Generate random integer in given range *
494  *---------------------------------------------------------------------*/
509 l_ok
511  l_int32 seed,
512  l_int32 *pval)
513 {
514  PROCNAME("genRandomIntegerInRange");
515 
516  if (!pval)
517  return ERROR_INT("&val not defined", procName, 1);
518  *pval = 0;
519  if (range < 2)
520  return ERROR_INT("range must be >= 2", procName, 1);
521 
522  if (seed > 0) srand(seed);
523  *pval = (l_int32)((l_float64)range *
524  ((l_float64)rand() / (l_float64)RAND_MAX));
525  return 0;
526 }
527 
528 
529 /*---------------------------------------------------------------------*
530  * Simple math function *
531  *---------------------------------------------------------------------*/
546 l_int32
547 lept_roundftoi(l_float32 fval)
548 {
549  return (fval >= 0.0) ? (l_int32)(fval + 0.5) : (l_int32)(fval - 0.5);
550 }
551 
552 
553 /*---------------------------------------------------------------------*
554  * 64-bit hash functions *
555  *---------------------------------------------------------------------*/
578 l_ok
579 l_hashStringToUint64(const char *str,
580  l_uint64 *phash)
581 {
582 l_uint64 hash, mulp;
583 
584  PROCNAME("l_hashStringToUint64");
585 
586  if (phash) *phash = 0;
587  if (!str || (str[0] == '\0'))
588  return ERROR_INT("str not defined or empty", procName, 1);
589  if (!phash)
590  return ERROR_INT("&hash not defined", procName, 1);
591 
592  mulp = 26544357894361247; /* prime, about 1/700 of the max uint64 */
593  hash = 104395301;
594  while (*str) {
595  hash += (*str++ * mulp) ^ (hash >> 7); /* shift [1...23] are ok */
596  }
597  *phash = hash ^ (hash << 37);
598  return 0;
599 }
600 
601 
624 l_ok
626  l_int32 y,
627  l_uint64 *phash)
628 {
629  PROCNAME("l_hashPtToUint64");
630 
631  if (!phash)
632  return ERROR_INT("&hash not defined", procName, 1);
633 
634  *phash = (l_uint64)(2173249142.3849 * x + 3763193258.6227 * y);
635  return 0;
636 }
637 
638 
664 l_ok
665 l_hashFloat64ToUint64(l_int32 nbuckets,
666  l_float64 val,
667  l_uint64 *phash)
668 {
669  PROCNAME("l_hashFloatToUint64");
670 
671  if (!phash)
672  return ERROR_INT("&hash not defined", procName, 1);
673  *phash = (l_uint64)((21.732491 * nbuckets) * val);
674  return 0;
675 }
676 
677 
678 /*---------------------------------------------------------------------*
679  * Prime finders *
680  *---------------------------------------------------------------------*/
688 l_ok
689 findNextLargerPrime(l_int32 start,
690  l_uint32 *pprime)
691 {
692 l_int32 i, is_prime;
693 
694  PROCNAME("findNextLargerPrime");
695 
696  if (!pprime)
697  return ERROR_INT("&prime not defined", procName, 1);
698  *pprime = 0;
699  if (start <= 0)
700  return ERROR_INT("start must be > 0", procName, 1);
701 
702  for (i = start + 1; ; i++) {
703  lept_isPrime(i, &is_prime, NULL);
704  if (is_prime) {
705  *pprime = i;
706  return 0;
707  }
708  }
709 
710  return ERROR_INT("prime not found!", procName, 1);
711 }
712 
713 
723 l_ok
724 lept_isPrime(l_uint64 n,
725  l_int32 *pis_prime,
726  l_uint32 *pfactor)
727 {
728 l_uint32 div;
729 l_uint64 limit, ratio;
730 
731  PROCNAME("lept_isPrime");
732 
733  if (pis_prime) *pis_prime = 0;
734  if (pfactor) *pfactor = 0;
735  if (!pis_prime)
736  return ERROR_INT("&is_prime not defined", procName, 1);
737  if (n <= 0)
738  return ERROR_INT("n must be > 0", procName, 1);
739 
740  if (n % 2 == 0) {
741  if (pfactor) *pfactor = 2;
742  return 0;
743  }
744 
745  limit = (l_uint64)sqrt((l_float64)n);
746  for (div = 3; div < limit; div += 2) {
747  ratio = n / div;
748  if (ratio * div == n) {
749  if (pfactor) *pfactor = div;
750  return 0;
751  }
752  }
753 
754  *pis_prime = 1;
755  return 0;
756 }
757 
758 
759 /*---------------------------------------------------------------------*
760  * Gray code conversion *
761  *---------------------------------------------------------------------*/
774 l_uint32
775 convertIntToGrayCode(l_uint32 val)
776 {
777  return (val >> 1) ^ val;
778 }
779 
780 
787 l_uint32
788 convertGrayCodeToInt(l_uint32 val)
789 {
790 l_uint32 shift;
791 
792  for (shift = 1; shift < 32; shift <<= 1)
793  val ^= val >> shift;
794  return val;
795 }
796 
797 
798 /*---------------------------------------------------------------------*
799  * Leptonica version number *
800  *---------------------------------------------------------------------*/
809 char *
811 {
812 size_t bufsize = 100;
813 
814  char *version = (char *)LEPT_CALLOC(bufsize, sizeof(char));
815 
816 #ifdef _MSC_VER
817  #ifdef _USRDLL
818  char dllStr[] = "DLL";
819  #else
820  char dllStr[] = "LIB";
821  #endif
822  #ifdef _DEBUG
823  char debugStr[] = "Debug";
824  #else
825  char debugStr[] = "Release";
826  #endif
827  #ifdef _M_IX86
828  char bitStr[] = " x86";
829  #elif _M_X64
830  char bitStr[] = " x64";
831  #else
832  char bitStr[] = "";
833  #endif
834  snprintf(version, bufsize, "leptonica-%d.%d.%d (%s, %s) [MSC v.%d %s %s%s]",
835  LIBLEPT_MAJOR_VERSION, LIBLEPT_MINOR_VERSION, LIBLEPT_PATCH_VERSION,
836  __DATE__, __TIME__, _MSC_VER, dllStr, debugStr, bitStr);
837 
838 #else
839 
840  snprintf(version, bufsize, "leptonica-%d.%d.%d", LIBLEPT_MAJOR_VERSION,
841  LIBLEPT_MINOR_VERSION, LIBLEPT_PATCH_VERSION);
842 
843 #endif /* _MSC_VER */
844  return version;
845 }
846 
847 
848 /*---------------------------------------------------------------------*
849  * Timing procs *
850  *---------------------------------------------------------------------*/
851 #ifndef _WIN32
852 
853 #include <sys/time.h>
854 #include <sys/resource.h>
855 
856 static struct rusage rusage_before;
857 static struct rusage rusage_after;
858 
868 void
870 {
871  getrusage(RUSAGE_SELF, &rusage_before);
872 }
873 
874 l_float32
875 stopTimer(void)
876 {
877 l_int32 tsec, tusec;
878 
879  getrusage(RUSAGE_SELF, &rusage_after);
880 
881  tsec = rusage_after.ru_utime.tv_sec - rusage_before.ru_utime.tv_sec;
882  tusec = rusage_after.ru_utime.tv_usec - rusage_before.ru_utime.tv_usec;
883  return (tsec + ((l_float32)tusec) / 1000000.0);
884 }
885 
886 
900 L_TIMER
902 {
903 struct rusage *rusage_start;
904 
905  rusage_start = (struct rusage *)LEPT_CALLOC(1, sizeof(struct rusage));
906  getrusage(RUSAGE_SELF, rusage_start);
907  return rusage_start;
908 }
909 
910 l_float32
911 stopTimerNested(L_TIMER rusage_start)
912 {
913 l_int32 tsec, tusec;
914 struct rusage rusage_stop;
915 
916  getrusage(RUSAGE_SELF, &rusage_stop);
917 
918  tsec = rusage_stop.ru_utime.tv_sec -
919  ((struct rusage *)rusage_start)->ru_utime.tv_sec;
920  tusec = rusage_stop.ru_utime.tv_usec -
921  ((struct rusage *)rusage_start)->ru_utime.tv_usec;
922  LEPT_FREE(rusage_start);
923  return (tsec + ((l_float32)tusec) / 1000000.0);
924 }
925 
926 
934 void
935 l_getCurrentTime(l_int32 *sec,
936  l_int32 *usec)
937 {
938 struct timeval tv;
939 
940  gettimeofday(&tv, NULL);
941  if (sec) *sec = (l_int32)tv.tv_sec;
942  if (usec) *usec = (l_int32)tv.tv_usec;
943  return;
944 }
945 
946 
947 #else /* _WIN32 : resource.h not implemented under Windows */
948 
949  /* Note: if division by 10^7 seems strange, the time is expressed
950  * as the number of 100-nanosecond intervals that have elapsed
951  * since 12:00 A.M. January 1, 1601. */
952 
953 static ULARGE_INTEGER utime_before;
954 static ULARGE_INTEGER utime_after;
955 
956 void
957 startTimer(void)
958 {
959 HANDLE this_process;
960 FILETIME start, stop, kernel, user;
961 
962  this_process = GetCurrentProcess();
963 
964  GetProcessTimes(this_process, &start, &stop, &kernel, &user);
965 
966  utime_before.LowPart = user.dwLowDateTime;
967  utime_before.HighPart = user.dwHighDateTime;
968 }
969 
970 l_float32
971 stopTimer(void)
972 {
973 HANDLE this_process;
974 FILETIME start, stop, kernel, user;
975 ULONGLONG hnsec; /* in units of hecto-nanosecond (100 ns) intervals */
976 
977  this_process = GetCurrentProcess();
978 
979  GetProcessTimes(this_process, &start, &stop, &kernel, &user);
980 
981  utime_after.LowPart = user.dwLowDateTime;
982  utime_after.HighPart = user.dwHighDateTime;
983  hnsec = utime_after.QuadPart - utime_before.QuadPart;
984  return (l_float32)(signed)hnsec / 10000000.0;
985 }
986 
987 L_TIMER
988 startTimerNested(void)
989 {
990 HANDLE this_process;
991 FILETIME start, stop, kernel, user;
992 ULARGE_INTEGER *utime_start;
993 
994  this_process = GetCurrentProcess();
995 
996  GetProcessTimes (this_process, &start, &stop, &kernel, &user);
997 
998  utime_start = (ULARGE_INTEGER *)LEPT_CALLOC(1, sizeof(ULARGE_INTEGER));
999  utime_start->LowPart = user.dwLowDateTime;
1000  utime_start->HighPart = user.dwHighDateTime;
1001  return utime_start;
1002 }
1003 
1004 l_float32
1005 stopTimerNested(L_TIMER utime_start)
1006 {
1007 HANDLE this_process;
1008 FILETIME start, stop, kernel, user;
1009 ULARGE_INTEGER utime_stop;
1010 ULONGLONG hnsec; /* in units of 100 ns intervals */
1011 
1012  this_process = GetCurrentProcess ();
1013 
1014  GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1015 
1016  utime_stop.LowPart = user.dwLowDateTime;
1017  utime_stop.HighPart = user.dwHighDateTime;
1018  hnsec = utime_stop.QuadPart - ((ULARGE_INTEGER *)utime_start)->QuadPart;
1019  LEPT_FREE(utime_start);
1020  return (l_float32)(signed)hnsec / 10000000.0;
1021 }
1022 
1023 void
1024 l_getCurrentTime(l_int32 *sec,
1025  l_int32 *usec)
1026 {
1027 ULARGE_INTEGER utime, birthunix;
1028 FILETIME systemtime;
1029 LONGLONG birthunixhnsec = 116444736000000000; /*in units of 100 ns */
1030 LONGLONG usecs;
1031 
1032  GetSystemTimeAsFileTime(&systemtime);
1033  utime.LowPart = systemtime.dwLowDateTime;
1034  utime.HighPart = systemtime.dwHighDateTime;
1035 
1036  birthunix.LowPart = (DWORD) birthunixhnsec;
1037  birthunix.HighPart = birthunixhnsec >> 32;
1038 
1039  usecs = (LONGLONG) ((utime.QuadPart - birthunix.QuadPart) / 10);
1040 
1041  if (sec) *sec = (l_int32) (usecs / 1000000);
1042  if (usec) *usec = (l_int32) (usecs % 1000000);
1043  return;
1044 }
1045 
1046 #endif
1047 
1048 
1063 L_WALLTIMER *
1065 {
1066 L_WALLTIMER *timer;
1067 
1068  timer = (L_WALLTIMER *)LEPT_CALLOC(1, sizeof(L_WALLTIMER));
1069  l_getCurrentTime(&timer->start_sec, &timer->start_usec);
1070  return timer;
1071 }
1072 
1079 l_float32
1081 {
1082 l_int32 tsec, tusec;
1083 L_WALLTIMER *timer;
1084 
1085  PROCNAME("stopWallTimer");
1086 
1087  if (!ptimer)
1088  return (l_float32)ERROR_FLOAT("&timer not defined", procName, 0.0);
1089  timer = *ptimer;
1090  if (!timer)
1091  return (l_float32)ERROR_FLOAT("timer not defined", procName, 0.0);
1092 
1093  l_getCurrentTime(&timer->stop_sec, &timer->stop_usec);
1094  tsec = timer->stop_sec - timer->start_sec;
1095  tusec = timer->stop_usec - timer->start_usec;
1096  LEPT_FREE(timer);
1097  *ptimer = NULL;
1098  return (tsec + ((l_float32)tusec) / 1000000.0);
1099 }
1100 
1101 
1114 char *
1116 {
1117 char buf[128] = "", sep = 'Z';
1118 l_int32 gmt_offset, relh, relm;
1119 time_t ut, lt;
1120 struct tm Tm;
1121 struct tm *tptr = &Tm;
1122 
1123  ut = time(NULL);
1124 
1125  /* This generates a second "time_t" value by calling "gmtime" to
1126  fill in a "tm" structure expressed as UTC and then calling
1127  "mktime", which expects a "tm" structure expressed as the
1128  local time. The result is a value that is offset from the
1129  value returned by the "time" function by the local UTC offset.
1130  "tm_isdst" is set to -1 to tell "mktime" to determine for
1131  itself whether DST is in effect. This is necessary because
1132  "gmtime" always sets "tm_isdst" to 0, which would tell
1133  "mktime" to presume that DST is not in effect. */
1134 #ifdef _WIN32
1135  gmtime_s(tptr, &ut);
1136 #else
1137  gmtime_r(&ut, tptr);
1138 #endif
1139  tptr->tm_isdst = -1;
1140  lt = mktime(tptr);
1141 
1142  /* Calls "difftime" to obtain the resulting difference in seconds,
1143  * because "time_t" is an opaque type, per the C standard. */
1144  gmt_offset = (l_int32) difftime(ut, lt);
1145 
1146  if (gmt_offset > 0)
1147  sep = '+';
1148  else if (gmt_offset < 0)
1149  sep = '-';
1150 
1151  relh = L_ABS(gmt_offset) / 3600;
1152  relm = (L_ABS(gmt_offset) % 3600) / 60;
1153 
1154  strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", localtime(&ut));
1155  sprintf(buf + 14, "%c%02d'%02d'", sep, relh, relm);
1156  return stringNew(buf);
1157 }
size_t nbytesInFile(const char *filename)
nbytesInFile()
Definition: utils2.c:1471
LEPT_DLL l_int32 LeptMsgSeverity
Definition: utils1.c:112
L_TIMER startTimerNested(void)
startTimerNested(), stopTimerNested()
Definition: utils1.c:901
l_ok l_hashPtToUint64(l_int32 x, l_int32 y, l_uint64 *phash)
l_hashPtToUint64()
Definition: utils1.c:625
l_ok genRandomIntegerInRange(l_int32 range, l_int32 seed, l_int32 *pval)
genRandomIntegerInRange()
Definition: utils1.c:510
l_int32 lept_roundftoi(l_float32 fval)
lept_roundftoi()
Definition: utils1.c:547
l_int32 setMsgSeverity(l_int32 newsev)
setMsgSeverity()
Definition: utils1.c:136
void startTimer(void)
startTimer(), stopTimer()
Definition: utils1.c:869
l_ok fileCorruptByMutation(const char *filein, l_float32 loc, l_float32 size, const char *fileout)
fileCorruptByMutation()
Definition: utils1.c:452
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:215
l_float32 stopWallTimer(L_WALLTIMER **ptimer)
stopWallTimer()
Definition: utils1.c:1080
l_ok l_hashFloat64ToUint64(l_int32 nbuckets, l_float64 val, l_uint64 *phash)
l_hashFloat64ToUint64()
Definition: utils1.c:665
void * returnErrorPtr(const char *msg, const char *procname, void *pval)
returnErrorPtr()
Definition: utils1.c:223
l_ok findNextLargerPrime(l_int32 start, l_uint32 *pprime)
findNextLargerPrime()
Definition: utils1.c:689
l_ok fileCorruptByDeletion(const char *filein, l_float32 loc, l_float32 size, const char *fileout)
fileCorruptByDeletion()
Definition: utils1.c:388
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1429
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1212
char * getLeptonicaVersion()
getLeptonicaVersion()
Definition: utils1.c:810
l_uint32 convertIntToGrayCode(l_uint32 val)
convertIntToGrayCode()
Definition: utils1.c:775
l_ok l_hashStringToUint64(const char *str, l_uint64 *phash)
l_hashStringToUint64()
Definition: utils1.c:579
l_float32 returnErrorFloat(const char *msg, const char *procname, l_float32 fval)
returnErrorFloat()
Definition: utils1.c:205
l_uint32 convertGrayCodeToInt(l_uint32 val)
convertGrayCodeToInt()
Definition: utils1.c:788
void l_getCurrentTime(l_int32 *sec, l_int32 *usec)
l_getCurrentTime()
Definition: utils1.c:935
l_ok filesAreIdentical(const char *fname1, const char *fname2, l_int32 *psame)
filesAreIdentical()
Definition: utils1.c:244
l_ok lept_isPrime(l_uint64 n, l_int32 *pis_prime, l_uint32 *pfactor)
lept_isPrime()
Definition: utils1.c:724
L_WALLTIMER * startWallTimer(void)
startWallTimer()
Definition: utils1.c:1064
char * l_getFormattedDate()
l_getFormattedDate()
Definition: utils1.c:1115
l_int32 returnErrorInt(const char *msg, const char *procname, l_int32 ival)
returnErrorInt()
Definition: utils1.c:187