Leptonica 1.82.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
106#ifdef HAVE_CONFIG_H
107#include <config_auto.h>
108#endif /* HAVE_CONFIG_H */
109
110#ifdef _WIN32
111#include <windows.h>
112#endif /* _WIN32 */
113
114#include <time.h>
115#include "allheaders.h"
116#include <math.h>
117
118 /* Global for controlling message output at runtime */
119LEPT_DLL l_int32 LeptMsgSeverity = DEFAULT_SEVERITY;
120
121#define DEBUG_SEV 0
122
123/*----------------------------------------------------------------------*
124 * Control of error, warning and info messages *
125 *----------------------------------------------------------------------*/
142l_int32
143setMsgSeverity(l_int32 newsev)
144{
145l_int32 oldsev;
146char *envsev;
147
148 oldsev = LeptMsgSeverity;
149 if (newsev == L_SEVERITY_EXTERNAL) {
150 envsev = getenv("LEPT_MSG_SEVERITY");
151 if (envsev) {
152 LeptMsgSeverity = atoi(envsev);
153#if DEBUG_SEV
154 L_INFO("message severity set to external\n", "setMsgSeverity");
155#endif /* DEBUG_SEV */
156 } else {
157#if DEBUG_SEV
158 L_WARNING("environment var LEPT_MSG_SEVERITY not defined\n",
159 "setMsgSeverity");
160#endif /* DEBUG_SEV */
161 }
162 } else {
163 LeptMsgSeverity = newsev;
164#if DEBUG_SEV
165 L_INFO("message severity set to %d\n", "setMsgSeverity", newsev);
166#endif /* DEBUG_SEV */
167 }
168
169 return oldsev;
170}
171
172
173/*----------------------------------------------------------------------*
174 * Error return functions, invoked by macros *
175 *----------------------------------------------------------------------*
176 * *
177 * (1) These error functions print messages to stderr and allow *
178 * exit from the function that called them. *
179 * (2) They must be invoked only by the macros ERROR_INT, *
180 * ERROR_FLOAT and ERROR_PTR, which are in environ.h *
181 * (3) The print output can be disabled at compile time, either *
182 * by using -DNO_CONSOLE_IO or by setting LeptMsgSeverity. *
183 *----------------------------------------------------------------------*/
192l_int32
193returnErrorInt(const char *msg,
194 const char *procname,
195 l_int32 ival)
196{
197 lept_stderr("Error in %s: %s\n", procname, msg);
198 return ival;
199}
200
201
210l_float32
211returnErrorFloat(const char *msg,
212 const char *procname,
213 l_float32 fval)
214{
215 lept_stderr("Error in %s: %s\n", procname, msg);
216 return fval;
217}
218
219
228void *
229returnErrorPtr(const char *msg,
230 const char *procname,
231 void *pval)
232{
233 lept_stderr("Error in %s: %s\n", procname, msg);
234 return pval;
235}
236
237
238/*------------------------------------------------------------------------*
239 * Runtime redirection of stderr *
240 *------------------------------------------------------------------------*
241 * *
242 * The user can provide a callback function to redirect messages *
243 * that would otherwise go to stderr. Here are two examples: *
244 * (1) to stop all messages: *
245 * void send_to_devnull(const char *msg) {} *
246 * (2) to write to the system logger: *
247 * void send_to_syslog(const char *msg) { *
248 * syslog(1, msg); *
249 * } *
250 * These would then be registered using *
251 * leptSetStderrHandler(send_to_devnull); *
252 * and *
253 * leptSetStderrHandler(send_to_syslog); *
254 *------------------------------------------------------------------------*/
255 /* By default, all messages go to stderr */
256static void lept_default_stderr_handler(const char *formatted_msg)
257{
258 if (formatted_msg)
259 fputs(formatted_msg, stderr);
260}
261
262 /* The stderr callback handler is private to leptonica.
263 * By default it writes to stderr. */
264void (*stderr_handler)(const char *) = lept_default_stderr_handler;
265
266
280void leptSetStderrHandler(void (*handler)(const char *))
281{
282 if (handler)
283 stderr_handler = handler;
284 else
285 stderr_handler = lept_default_stderr_handler;
286}
287
288
289#define MAX_DEBUG_MESSAGE 2000
306void lept_stderr(const char *fmt, ...)
307{
308va_list args;
309char msg[MAX_DEBUG_MESSAGE];
310l_int32 n;
311
312 va_start(args, fmt);
313 n = vsnprintf(msg, sizeof(msg), fmt, args);
314 va_end(args);
315 if (n < 0)
316 return;
317 (*stderr_handler)(msg);
318}
319
320
321/*--------------------------------------------------------------------*
322 * Test files for equivalence *
323 *--------------------------------------------------------------------*/
332l_ok
333filesAreIdentical(const char *fname1,
334 const char *fname2,
335 l_int32 *psame)
336{
337l_int32 i, same;
338size_t nbytes1, nbytes2;
339l_uint8 *array1, *array2;
340
341 PROCNAME("filesAreIdentical");
342
343 if (!psame)
344 return ERROR_INT("&same not defined", procName, 1);
345 *psame = 0;
346 if (!fname1 || !fname2)
347 return ERROR_INT("both names not defined", procName, 1);
348
349 nbytes1 = nbytesInFile(fname1);
350 nbytes2 = nbytesInFile(fname2);
351 if (nbytes1 != nbytes2)
352 return 0;
353
354 if ((array1 = l_binaryRead(fname1, &nbytes1)) == NULL)
355 return ERROR_INT("array1 not read", procName, 1);
356 if ((array2 = l_binaryRead(fname2, &nbytes2)) == NULL) {
357 LEPT_FREE(array1);
358 return ERROR_INT("array2 not read", procName, 1);
359 }
360 same = 1;
361 for (i = 0; i < nbytes1; i++) {
362 if (array1[i] != array2[i]) {
363 same = 0;
364 break;
365 }
366 }
367 LEPT_FREE(array1);
368 LEPT_FREE(array2);
369 *psame = same;
370
371 return 0;
372}
373
374
375/*--------------------------------------------------------------------------*
376 * 16 and 32 bit byte-swapping on big endian and little endian machines *
377 *--------------------------------------------------------------------------*
378 * *
379 * These are typically used for I/O conversions: *
380 * (1) endian conversion for data that was read from a file *
381 * (2) endian conversion on data before it is written to a file *
382 *--------------------------------------------------------------------------*/
383
384/*--------------------------------------------------------------------*
385 * 16-bit byte swapping *
386 *--------------------------------------------------------------------*/
387#ifdef L_BIG_ENDIAN
388
389l_uint16
390convertOnBigEnd16(l_uint16 shortin)
391{
392 return ((shortin << 8) | (shortin >> 8));
393}
394
395l_uint16
396convertOnLittleEnd16(l_uint16 shortin)
397{
398 return shortin;
399}
400
401#else /* L_LITTLE_ENDIAN */
402
403l_uint16
404convertOnLittleEnd16(l_uint16 shortin)
405{
406 return ((shortin << 8) | (shortin >> 8));
407}
408
409l_uint16
410convertOnBigEnd16(l_uint16 shortin)
411{
412 return shortin;
413}
414
415#endif /* L_BIG_ENDIAN */
416
417
418/*--------------------------------------------------------------------*
419 * 32-bit byte swapping *
420 *--------------------------------------------------------------------*/
421#ifdef L_BIG_ENDIAN
422
423l_uint32
424convertOnBigEnd32(l_uint32 wordin)
425{
426 return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
427 ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
428}
429
430l_uint32
431convertOnLittleEnd32(l_uint32 wordin)
432{
433 return wordin;
434}
435
436#else /* L_LITTLE_ENDIAN */
437
438l_uint32
439convertOnLittleEnd32(l_uint32 wordin)
440{
441 return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
442 ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
443}
444
445l_uint32
446convertOnBigEnd32(l_uint32 wordin)
447{
448 return wordin;
449}
450
451#endif /* L_BIG_ENDIAN */
452
453
454/*---------------------------------------------------------------------*
455 * File corruption and byte replacement operations *
456 *---------------------------------------------------------------------*/
477l_ok
478fileCorruptByDeletion(const char *filein,
479 l_float32 loc,
480 l_float32 size,
481 const char *fileout)
482{
483l_int32 i, locb, sizeb, rembytes;
484size_t inbytes, outbytes;
485l_uint8 *datain, *dataout;
486
487 PROCNAME("fileCorruptByDeletion");
488
489 if (!filein || !fileout)
490 return ERROR_INT("filein and fileout not both specified", procName, 1);
491 if (loc < 0.0 || loc >= 1.0)
492 return ERROR_INT("loc must be in [0.0 ... 1.0)", procName, 1);
493 if (size <= 0.0)
494 return ERROR_INT("size must be > 0.0", procName, 1);
495 if (loc + size > 1.0)
496 size = 1.0 - loc;
497
498 datain = l_binaryRead(filein, &inbytes);
499 locb = (l_int32)(loc * inbytes + 0.5);
500 locb = L_MIN(locb, inbytes - 1);
501 sizeb = (l_int32)(size * inbytes + 0.5);
502 sizeb = L_MAX(1, sizeb);
503 sizeb = L_MIN(sizeb, inbytes - locb); /* >= 1 */
504 L_INFO("Removed %d bytes at location %d\n", procName, sizeb, locb);
505 rembytes = inbytes - locb - sizeb; /* >= 0; to be copied, after excision */
506
507 outbytes = inbytes - sizeb;
508 dataout = (l_uint8 *)LEPT_CALLOC(outbytes, 1);
509 for (i = 0; i < locb; i++)
510 dataout[i] = datain[i];
511 for (i = 0; i < rembytes; i++)
512 dataout[locb + i] = datain[locb + sizeb + i];
513 l_binaryWrite(fileout, "w", dataout, outbytes);
514
515 LEPT_FREE(datain);
516 LEPT_FREE(dataout);
517 return 0;
518}
519
520
541l_ok
542fileCorruptByMutation(const char *filein,
543 l_float32 loc,
544 l_float32 size,
545 const char *fileout)
546{
547l_int32 i, locb, sizeb;
548size_t bytes;
549l_uint8 *data;
550
551 PROCNAME("fileCorruptByMutation");
552
553 if (!filein || !fileout)
554 return ERROR_INT("filein and fileout not both specified", procName, 1);
555 if (loc < 0.0 || loc >= 1.0)
556 return ERROR_INT("loc must be in [0.0 ... 1.0)", procName, 1);
557 if (size <= 0.0)
558 return ERROR_INT("size must be > 0.0", procName, 1);
559 if (loc + size > 1.0)
560 size = 1.0 - loc;
561
562 data = l_binaryRead(filein, &bytes);
563 locb = (l_int32)(loc * bytes + 0.5);
564 locb = L_MIN(locb, bytes - 1);
565 sizeb = (l_int32)(size * bytes + 0.5);
566 sizeb = L_MAX(1, sizeb);
567 sizeb = L_MIN(sizeb, bytes - locb); /* >= 1 */
568 L_INFO("Randomizing %d bytes at location %d\n", procName, sizeb, locb);
569
570 /* Make an array of random bytes and do the substitution */
571 for (i = 0; i < sizeb; i++) {
572 data[locb + i] =
573 (l_uint8)(255.9 * ((l_float64)rand() / (l_float64)RAND_MAX));
574 }
575
576 l_binaryWrite(fileout, "w", data, bytes);
577 LEPT_FREE(data);
578 return 0;
579}
580
581
602l_ok
603fileReplaceBytes(const char *filein,
604 l_int32 start,
605 l_int32 nbytes,
606 l_uint8 *newdata,
607 size_t newsize,
608 const char *fileout)
609{
610l_int32 i, index;
611size_t inbytes, outbytes;
612l_uint8 *datain, *dataout;
613
614 PROCNAME("fileReplaceBytes");
615
616 if (!filein || !fileout)
617 return ERROR_INT("filein and fileout not both specified", procName, 1);
618
619 datain = l_binaryRead(filein, &inbytes);
620 if (start + nbytes > inbytes)
621 L_WARNING("start + nbytes > length(filein) = %zu\n", procName, inbytes);
622
623 if (!newdata) newsize = 0;
624 outbytes = inbytes - nbytes + newsize;
625 if ((dataout = (l_uint8 *)LEPT_CALLOC(outbytes, 1)) == NULL) {
626 LEPT_FREE(datain);
627 return ERROR_INT("calloc fail for dataout", procName, 1);
628 }
629
630 for (i = 0; i < start; i++)
631 dataout[i] = datain[i];
632 for (i = start; i < start + newsize; i++)
633 dataout[i] = newdata[i - start];
634 index = start + nbytes; /* for datain */
635 start += newsize; /* for dataout */
636 for (i = start; i < outbytes; i++, index++)
637 dataout[i] = datain[index];
638 l_binaryWrite(fileout, "w", dataout, outbytes);
639
640 LEPT_FREE(datain);
641 LEPT_FREE(dataout);
642 return 0;
643}
644
645
646/*---------------------------------------------------------------------*
647 * Generate random integer in given interval *
648 *---------------------------------------------------------------------*/
658l_ok
660 l_int32 end,
661 l_int32 seed,
662 l_int32 *pval)
663{
664l_float64 range;
665
666 PROCNAME("genRandomIntOnInterval");
667
668 if (!pval)
669 return ERROR_INT("&val not defined", procName, 1);
670 *pval = 0;
671 if (end < start)
672 return ERROR_INT("invalid range", procName, 1);
673
674 if (seed > 0) srand(seed);
675 range = (l_float64)(end - start + 1);
676 *pval = start + (l_int32)((l_float64)range *
677 ((l_float64)rand() / (l_float64)RAND_MAX));
678 return 0;
679}
680
681
682/*---------------------------------------------------------------------*
683 * Simple math function *
684 *---------------------------------------------------------------------*/
699l_int32
700lept_roundftoi(l_float32 fval)
701{
702 return (fval >= 0.0) ? (l_int32)(fval + 0.5) : (l_int32)(fval - 0.5);
703}
704
705
706/*---------------------------------------------------------------------*
707 * 64-bit hash functions *
708 *---------------------------------------------------------------------*/
731l_ok
732l_hashStringToUint64(const char *str,
733 l_uint64 *phash)
734{
735l_uint64 hash, mulp;
736
737 PROCNAME("l_hashStringToUint64");
738
739 if (phash) *phash = 0;
740 if (!str || (str[0] == '\0'))
741 return ERROR_INT("str not defined or empty", procName, 1);
742 if (!phash)
743 return ERROR_INT("&hash not defined", procName, 1);
744
745 mulp = 26544357894361247; /* prime, about 1/700 of the max uint64 */
746 hash = 104395301;
747 while (*str) {
748 hash += (*str++ * mulp) ^ (hash >> 7); /* shift [1...23] are ok */
749 }
750 *phash = hash ^ (hash << 37);
751 return 0;
752}
753
754
770l_ok
772 l_uint64 *phash)
773{
774l_uint64 h;
775l_uint8 *p;
776
777 PROCNAME("l_hashStringToUint64Fast");
778
779 if (phash) *phash = 0;
780 if (!str || (str[0] == '\0'))
781 return ERROR_INT("str not defined or empty", procName, 1);
782 if (!phash)
783 return ERROR_INT("&hash not defined", procName, 1);
784
785 h = 0;
786 for (p = (l_uint8 *)str; *p != '\0'; p++)
787 h = 37 * h + *p; /* 37 is good prime number for this */
788 *phash = h;
789 return 0;
790}
791
792
806l_ok
808 l_int32 y,
809 l_uint64 *phash)
810{
811 PROCNAME("l_hashPtToUint64");
812
813 if (!phash)
814 return ERROR_INT("&hash not defined", procName, 1);
815
816 *phash = (l_uint64)(2173249142.3849 * x + 3763193258.6227 * y);
817 return 0;
818}
819
820
836l_ok
838 l_uint64 *phash)
839{
840 PROCNAME("l_hashFloatToUint64");
841
842 if (!phash)
843 return ERROR_INT("&hash not defined", procName, 1);
844 val = (val >= 0.0) ? 847019.66701 * val : -217324.91613 * val;
845 *phash = (l_uint64)val;
846 return 0;
847}
848
849
850/*---------------------------------------------------------------------*
851 * Prime finders *
852 *---------------------------------------------------------------------*/
860l_ok
862 l_uint32 *pprime)
863{
864l_int32 i, is_prime;
865
866 PROCNAME("findNextLargerPrime");
867
868 if (!pprime)
869 return ERROR_INT("&prime not defined", procName, 1);
870 *pprime = 0;
871 if (start <= 0)
872 return ERROR_INT("start must be > 0", procName, 1);
873
874 for (i = start + 1; ; i++) {
875 lept_isPrime(i, &is_prime, NULL);
876 if (is_prime) {
877 *pprime = i;
878 return 0;
879 }
880 }
881
882 return ERROR_INT("prime not found!", procName, 1);
883}
884
885
895l_ok
896lept_isPrime(l_uint64 n,
897 l_int32 *pis_prime,
898 l_uint32 *pfactor)
899{
900l_uint32 div;
901l_uint64 limit, ratio;
902
903 PROCNAME("lept_isPrime");
904
905 if (pis_prime) *pis_prime = 0;
906 if (pfactor) *pfactor = 0;
907 if (!pis_prime)
908 return ERROR_INT("&is_prime not defined", procName, 1);
909 if (n <= 0)
910 return ERROR_INT("n must be > 0", procName, 1);
911
912 if (n % 2 == 0) {
913 if (pfactor) *pfactor = 2;
914 return 0;
915 }
916
917 limit = (l_uint64)sqrt((l_float64)n);
918 for (div = 3; div < limit; div += 2) {
919 ratio = n / div;
920 if (ratio * div == n) {
921 if (pfactor) *pfactor = div;
922 return 0;
923 }
924 }
925
926 *pis_prime = 1;
927 return 0;
928}
929
930
931/*---------------------------------------------------------------------*
932 * Gray code conversion *
933 *---------------------------------------------------------------------*/
946l_uint32
948{
949 return (val >> 1) ^ val;
950}
951
952
959l_uint32
961{
962l_uint32 shift;
963
964 for (shift = 1; shift < 32; shift <<= 1)
965 val ^= val >> shift;
966 return val;
967}
968
969
970/*---------------------------------------------------------------------*
971 * Leptonica version number *
972 *---------------------------------------------------------------------*/
981char *
983{
984size_t bufsize = 100;
985
986 char *version = (char *)LEPT_CALLOC(bufsize, sizeof(char));
987
988#ifdef _MSC_VER
989 #ifdef _USRDLL
990 char dllStr[] = "DLL";
991 #else
992 char dllStr[] = "LIB";
993 #endif
994 #ifdef _DEBUG
995 char debugStr[] = "Debug";
996 #else
997 char debugStr[] = "Release";
998 #endif
999 #ifdef _M_IX86
1000 char bitStr[] = " x86";
1001 #elif _M_X64
1002 char bitStr[] = " x64";
1003 #else
1004 char bitStr[] = "";
1005 #endif
1006 snprintf(version, bufsize, "leptonica-%d.%d.%d (%s, %s) [MSC v.%d %s %s%s]",
1007 LIBLEPT_MAJOR_VERSION, LIBLEPT_MINOR_VERSION, LIBLEPT_PATCH_VERSION,
1008 __DATE__, __TIME__, _MSC_VER, dllStr, debugStr, bitStr);
1009
1010#else
1011
1012 snprintf(version, bufsize, "leptonica-%d.%d.%d", LIBLEPT_MAJOR_VERSION,
1013 LIBLEPT_MINOR_VERSION, LIBLEPT_PATCH_VERSION);
1014
1015#endif /* _MSC_VER */
1016 return version;
1017}
1018
1019
1020/*---------------------------------------------------------------------*
1021 * Timing procs *
1022 *---------------------------------------------------------------------*/
1023#if !defined(_WIN32) && !defined(__Fuchsia__)
1024
1025#include <sys/time.h>
1026#include <sys/resource.h>
1027
1028static struct rusage rusage_before;
1029static struct rusage rusage_after;
1030
1040void
1042{
1043 getrusage(RUSAGE_SELF, &rusage_before);
1044}
1045
1046l_float32
1047stopTimer(void)
1048{
1049l_int32 tsec, tusec;
1050
1051 getrusage(RUSAGE_SELF, &rusage_after);
1052
1053 tsec = rusage_after.ru_utime.tv_sec - rusage_before.ru_utime.tv_sec;
1054 tusec = rusage_after.ru_utime.tv_usec - rusage_before.ru_utime.tv_usec;
1055 return (tsec + ((l_float32)tusec) / 1000000.0);
1056}
1057
1058
1072L_TIMER
1074{
1075struct rusage *rusage_start;
1076
1077 rusage_start = (struct rusage *)LEPT_CALLOC(1, sizeof(struct rusage));
1078 getrusage(RUSAGE_SELF, rusage_start);
1079 return rusage_start;
1080}
1081
1082l_float32
1083stopTimerNested(L_TIMER rusage_start)
1084{
1085l_int32 tsec, tusec;
1086struct rusage rusage_stop;
1087
1088 getrusage(RUSAGE_SELF, &rusage_stop);
1089
1090 tsec = rusage_stop.ru_utime.tv_sec -
1091 ((struct rusage *)rusage_start)->ru_utime.tv_sec;
1092 tusec = rusage_stop.ru_utime.tv_usec -
1093 ((struct rusage *)rusage_start)->ru_utime.tv_usec;
1094 LEPT_FREE(rusage_start);
1095 return (tsec + ((l_float32)tusec) / 1000000.0);
1096}
1097
1098
1106void
1107l_getCurrentTime(l_int32 *sec,
1108 l_int32 *usec)
1109{
1110struct timeval tv;
1111
1112 gettimeofday(&tv, NULL);
1113 if (sec) *sec = (l_int32)tv.tv_sec;
1114 if (usec) *usec = (l_int32)tv.tv_usec;
1115}
1116
1117#elif defined(__Fuchsia__) /* resource.h not implemented on Fuchsia. */
1118
1119 /* Timer functions are used for testing and debugging, and
1120 * are stubbed out. If they are needed in the future, they
1121 * can be implemented in Fuchsia using the zircon syscall
1122 * zx_object_get_info() in ZX_INFOR_THREAD_STATS mode. */
1123void
1124startTimer(void)
1125{
1126}
1127
1128l_float32
1129stopTimer(void)
1130{
1131 return 0.0;
1132}
1133
1134L_TIMER
1135startTimerNested(void)
1136{
1137 return NULL;
1138}
1139
1140l_float32
1141stopTimerNested(L_TIMER rusage_start)
1142{
1143 return 0.0;
1144}
1145
1146void
1147l_getCurrentTime(l_int32 *sec,
1148 l_int32 *usec)
1149{
1150}
1151
1152#else /* _WIN32 : resource.h not implemented under Windows */
1153
1154 /* Note: if division by 10^7 seems strange, the time is expressed
1155 * as the number of 100-nanosecond intervals that have elapsed
1156 * since 12:00 A.M. January 1, 1601. */
1157
1158static ULARGE_INTEGER utime_before;
1159static ULARGE_INTEGER utime_after;
1160
1161void
1162startTimer(void)
1163{
1164HANDLE this_process;
1165FILETIME start, stop, kernel, user;
1166
1167 this_process = GetCurrentProcess();
1168
1169 GetProcessTimes(this_process, &start, &stop, &kernel, &user);
1170
1171 utime_before.LowPart = user.dwLowDateTime;
1172 utime_before.HighPart = user.dwHighDateTime;
1173}
1174
1175l_float32
1176stopTimer(void)
1177{
1178HANDLE this_process;
1179FILETIME start, stop, kernel, user;
1180ULONGLONG hnsec; /* in units of hecto-nanosecond (100 ns) intervals */
1181
1182 this_process = GetCurrentProcess();
1183
1184 GetProcessTimes(this_process, &start, &stop, &kernel, &user);
1185
1186 utime_after.LowPart = user.dwLowDateTime;
1187 utime_after.HighPart = user.dwHighDateTime;
1188 hnsec = utime_after.QuadPart - utime_before.QuadPart;
1189 return (l_float32)(signed)hnsec / 10000000.0;
1190}
1191
1192L_TIMER
1193startTimerNested(void)
1194{
1195HANDLE this_process;
1196FILETIME start, stop, kernel, user;
1197ULARGE_INTEGER *utime_start;
1198
1199 this_process = GetCurrentProcess();
1200
1201 GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1202
1203 utime_start = (ULARGE_INTEGER *)LEPT_CALLOC(1, sizeof(ULARGE_INTEGER));
1204 utime_start->LowPart = user.dwLowDateTime;
1205 utime_start->HighPart = user.dwHighDateTime;
1206 return utime_start;
1207}
1208
1209l_float32
1210stopTimerNested(L_TIMER utime_start)
1211{
1212HANDLE this_process;
1213FILETIME start, stop, kernel, user;
1214ULARGE_INTEGER utime_stop;
1215ULONGLONG hnsec; /* in units of 100 ns intervals */
1216
1217 this_process = GetCurrentProcess ();
1218
1219 GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1220
1221 utime_stop.LowPart = user.dwLowDateTime;
1222 utime_stop.HighPart = user.dwHighDateTime;
1223 hnsec = utime_stop.QuadPart - ((ULARGE_INTEGER *)utime_start)->QuadPart;
1224 LEPT_FREE(utime_start);
1225 return (l_float32)(signed)hnsec / 10000000.0;
1226}
1227
1228void
1229l_getCurrentTime(l_int32 *sec,
1230 l_int32 *usec)
1231{
1232ULARGE_INTEGER utime, birthunix;
1233FILETIME systemtime;
1234LONGLONG birthunixhnsec = 116444736000000000; /*in units of 100 ns */
1235LONGLONG usecs;
1236
1237 GetSystemTimeAsFileTime(&systemtime);
1238 utime.LowPart = systemtime.dwLowDateTime;
1239 utime.HighPart = systemtime.dwHighDateTime;
1240
1241 birthunix.LowPart = (DWORD) birthunixhnsec;
1242 birthunix.HighPart = birthunixhnsec >> 32;
1243
1244 usecs = (LONGLONG) ((utime.QuadPart - birthunix.QuadPart) / 10);
1245
1246 if (sec) *sec = (l_int32) (usecs / 1000000);
1247 if (usec) *usec = (l_int32) (usecs % 1000000);
1248}
1249
1250#endif
1251
1252
1269{
1270L_WALLTIMER *timer;
1271
1272 timer = (L_WALLTIMER *)LEPT_CALLOC(1, sizeof(L_WALLTIMER));
1273 l_getCurrentTime(&timer->start_sec, &timer->start_usec);
1274 return timer;
1275}
1276
1283l_float32
1285{
1286l_int32 tsec, tusec;
1287L_WALLTIMER *timer;
1288
1289 PROCNAME("stopWallTimer");
1290
1291 if (!ptimer)
1292 return (l_float32)ERROR_FLOAT("&timer not defined", procName, 0.0);
1293 timer = *ptimer;
1294 if (!timer)
1295 return (l_float32)ERROR_FLOAT("timer not defined", procName, 0.0);
1296
1297 l_getCurrentTime(&timer->stop_sec, &timer->stop_usec);
1298 tsec = timer->stop_sec - timer->start_sec;
1299 tusec = timer->stop_usec - timer->start_usec;
1300 LEPT_FREE(timer);
1301 *ptimer = NULL;
1302 return (tsec + ((l_float32)tusec) / 1000000.0);
1303}
1304
1305
1318char *
1320{
1321char buf[128] = "", sep = 'Z';
1322l_int32 gmt_offset, relh, relm;
1323time_t ut, lt;
1324struct tm Tm;
1325struct tm *tptr = &Tm;
1326
1327 ut = time(NULL);
1328
1329 /* This generates a second "time_t" value by calling "gmtime" to
1330 fill in a "tm" structure expressed as UTC and then calling
1331 "mktime", which expects a "tm" structure expressed as the
1332 local time. The result is a value that is offset from the
1333 value returned by the "time" function by the local UTC offset.
1334 "tm_isdst" is set to -1 to tell "mktime" to determine for
1335 itself whether DST is in effect. This is necessary because
1336 "gmtime" always sets "tm_isdst" to 0, which would tell
1337 "mktime" to presume that DST is not in effect. */
1338#ifdef _WIN32
1339 #ifdef _MSC_VER
1340 gmtime_s(tptr, &ut);
1341 #else /* mingw */
1342 tptr = gmtime(&ut);
1343 #endif
1344#else
1345 gmtime_r(&ut, tptr);
1346#endif
1347 tptr->tm_isdst = -1;
1348 lt = mktime(tptr);
1349
1350 /* Calls "difftime" to obtain the resulting difference in seconds,
1351 * because "time_t" is an opaque type, per the C standard. */
1352 gmt_offset = (l_int32) difftime(ut, lt);
1353 if (gmt_offset > 0)
1354 sep = '+';
1355 else if (gmt_offset < 0)
1356 sep = '-';
1357 relh = L_ABS(gmt_offset) / 3600;
1358 relm = (L_ABS(gmt_offset) % 3600) / 60;
1359
1360#ifdef _WIN32
1361 #ifdef _MSC_VER
1362 localtime_s(tptr, &ut);
1363 #else /* mingw */
1364 tptr = localtime(&ut);
1365 #endif
1366#else
1367 localtime_r(&ut, tptr);
1368#endif
1369 strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tptr);
1370 sprintf(buf + 14, "%c%02d'%02d'", sep, relh, relm);
1371 return stringNew(buf);
1372}
l_ok fileCorruptByMutation(const char *filein, l_float32 loc, l_float32 size, const char *fileout)
fileCorruptByMutation()
Definition: utils1.c:542
char * l_getFormattedDate(void)
l_getFormattedDate()
Definition: utils1.c:1319
l_ok filesAreIdentical(const char *fname1, const char *fname2, l_int32 *psame)
filesAreIdentical()
Definition: utils1.c:333
l_ok fileReplaceBytes(const char *filein, l_int32 start, l_int32 nbytes, l_uint8 *newdata, size_t newsize, const char *fileout)
fileReplaceBytes()
Definition: utils1.c:603
l_float32 stopWallTimer(L_WALLTIMER **ptimer)
stopWallTimer()
Definition: utils1.c:1284
void startTimer(void)
startTimer(), stopTimer()
Definition: utils1.c:1041
l_ok l_hashStringToUint64Fast(const char *str, l_uint64 *phash)
l_hashStringToUint64Fast()
Definition: utils1.c:771
l_ok genRandomIntOnInterval(l_int32 start, l_int32 end, l_int32 seed, l_int32 *pval)
genRandomIntOnInterval()
Definition: utils1.c:659
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_ok lept_isPrime(l_uint64 n, l_int32 *pis_prime, l_uint32 *pfactor)
lept_isPrime()
Definition: utils1.c:896
char * getLeptonicaVersion(void)
getLeptonicaVersion()
Definition: utils1.c:982
void leptSetStderrHandler(void(*handler)(const char *))
leptSetStderrHandler()
Definition: utils1.c:280
l_float32 returnErrorFloat(const char *msg, const char *procname, l_float32 fval)
returnErrorFloat()
Definition: utils1.c:211
l_ok findNextLargerPrime(l_int32 start, l_uint32 *pprime)
findNextLargerPrime()
Definition: utils1.c:861
l_ok fileCorruptByDeletion(const char *filein, l_float32 loc, l_float32 size, const char *fileout)
fileCorruptByDeletion()
Definition: utils1.c:478
LEPT_DLL l_int32 LeptMsgSeverity
Definition: utils1.c:119
l_ok l_hashStringToUint64(const char *str, l_uint64 *phash)
l_hashStringToUint64()
Definition: utils1.c:732
void l_getCurrentTime(l_int32 *sec, l_int32 *usec)
l_getCurrentTime()
Definition: utils1.c:1107
L_TIMER startTimerNested(void)
startTimerNested(), stopTimerNested()
Definition: utils1.c:1073
l_int32 setMsgSeverity(l_int32 newsev)
setMsgSeverity()
Definition: utils1.c:143
l_int32 lept_roundftoi(l_float32 fval)
lept_roundftoi()
Definition: utils1.c:700
void * returnErrorPtr(const char *msg, const char *procname, void *pval)
returnErrorPtr()
Definition: utils1.c:229
l_uint32 convertGrayCodeToInt(l_uint32 val)
convertGrayCodeToInt()
Definition: utils1.c:960
l_int32 returnErrorInt(const char *msg, const char *procname, l_int32 ival)
returnErrorInt()
Definition: utils1.c:193
L_WALLTIMER * startWallTimer(void)
startWallTimer()
Definition: utils1.c:1268
l_uint32 convertIntToGrayCode(l_uint32 val)
convertIntToGrayCode()
Definition: utils1.c:947
l_ok l_hashFloat64ToUint64(l_float64 val, l_uint64 *phash)
l_hashFloat64ToUint64()
Definition: utils1.c:837
l_ok l_hashPtToUint64(l_int32 x, l_int32 y, l_uint64 *phash)
l_hashPtToUint64()
Definition: utils1.c:807
size_t nbytesInFile(const char *filename)
nbytesInFile()
Definition: utils2.c:1611
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1352
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1569
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223