1 /* -*- C++ -*-
2 * File: halt_mt_win32.c
3 * Copyright 2008-2021 LibRaw LLC (info@libraw.org)
4 * Created: Sat Mar 8, 2008
5 *
6 * LibRaw C API mutithreaded sample: emulates call to "dcraw -h [-w] [-a]
7 [-v]"
8 * Win32 version
9
10 LibRaw is free software; you can redistribute it and/or modify
11 it under the terms of the one of two licenses as you choose:
12
13 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
14 (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
15
16 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
17 (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
18
19
20 */
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <math.h>
25 #include <windows.h>
26 #include "libraw/libraw.h"
27
28 #ifdef LIBRAW_WIN32_CALLS
29 #define snprintf _snprintf
30 #endif
31
32 #define HANDLE_ERRORS(ret) \
33 do \
34 { \
35 if (ret) \
36 { \
37 fprintf(stderr, "%s: %s\n", fn, libraw_strerror(ret)); \
38 if (LIBRAW_FATAL_ERROR(ret)) \
39 { \
40 libraw_close(iprc); \
41 return -1; \
42 } \
43 } \
44 } while (0)
45
46 // global settings
47 int verbose = 0, use_camera_wb = 0, use_auto_wb = 0, tiff_mode = 0;
48
49 // global file queue
50 HANDLE qmutex;
51 char **queue = NULL;
52 size_t qsize = 0, qptr = 0;
53
get_next_file()54 char *get_next_file()
55 {
56 char *ret;
57 DWORD dwWaitResult;
58 if (!queue)
59 return NULL;
60 if (qptr >= qsize)
61 return NULL;
62
63 dwWaitResult = WaitForSingleObject(qmutex, // handle to mutex
64 INFINITE); // no time-out interval
65 switch (dwWaitResult)
66 {
67 // The thread got ownership of the mutex
68 case WAIT_OBJECT_0:
69 ret = queue[qptr++];
70 ReleaseMutex(qmutex);
71 break;
72 case WAIT_ABANDONED:
73 return NULL; // cannot obtain the lock
74 };
75 return ret;
76 }
77
78 // thread routine
process_files(void * q)79 int process_files(void *q)
80 {
81 int ret;
82 int count = 0;
83 char outfn[1024], *fn;
84 libraw_data_t *iprc = libraw_init(0);
85
86 if (!iprc)
87 {
88 fprintf(stderr, "Cannot create libraw handle\n");
89 return -1;
90 }
91
92 while ((fn = get_next_file()))
93 {
94
95 iprc->params.half_size = 1; /* dcraw -h */
96 iprc->params.use_camera_wb = use_camera_wb;
97 iprc->params.use_auto_wb = use_auto_wb;
98 iprc->params.output_tiff = tiff_mode;
99
100 ret = libraw_open_file(iprc, fn);
101 if (verbose)
102 fprintf(stderr, "%s: %s/%s\n", fn, iprc->idata.make, iprc->idata.model);
103 HANDLE_ERRORS(ret);
104
105 ret = libraw_unpack(iprc);
106 HANDLE_ERRORS(ret);
107
108 ret = libraw_dcraw_process(iprc);
109 HANDLE_ERRORS(ret);
110
111 snprintf(outfn, 1023, "%s.%s", fn, tiff_mode ? "tif" : "ppm");
112
113 if (verbose)
114 fprintf(stderr, "Writing file %s\n", outfn);
115 ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn);
116 HANDLE_ERRORS(ret);
117 count++;
118 }
119 libraw_close(iprc);
120 printf("Processed %d files\n", count);
121 return 0;
122 }
123
usage(const char * p)124 void usage(const char *p)
125 {
126 printf("Options:\n"
127 "-J n - set parallel job count (default 2)\n"
128 "-v - verbose\n"
129 "-w - use camera white balance\n"
130 "-T - output TIFF instead of PPM\n"
131 "-a - average image for white balance\n");
132 exit(1);
133 }
134
show_files(void * q)135 int show_files(void *q)
136 {
137 char *p;
138 int cnt = 0;
139 while (p = get_next_file())
140 {
141 printf("%s\n", p);
142 cnt++;
143 }
144 return cnt;
145 }
146
main(int ac,char * av[])147 int main(int ac, char *av[])
148 {
149 int i, max_threads = 2;
150 HANDLE *threads;
151 DWORD ThreadID;
152
153 if (ac < 2)
154 usage(av[0]);
155
156 queue = calloc(ac - 1, sizeof(queue[0]));
157
158 for (i = 1; i < ac; i++)
159 {
160 if (av[i][0] == '-')
161 {
162 if (av[i][1] == 'w')
163 use_camera_wb = 1;
164 if (av[i][1] == 'a')
165 use_auto_wb = 1;
166 if (av[i][1] == 'v')
167 verbose = 1;
168 if (av[i][1] == 'T')
169 tiff_mode = 1;
170 if (av[i][1] == 'J')
171 {
172 max_threads = atoi(av[++i]);
173 if (max_threads < 1)
174 {
175 fprintf(stderr, "Job count should be at least 1\n");
176 exit(1);
177 }
178 }
179 }
180 else
181 queue[qsize++] = av[i];
182 }
183 qmutex = CreateMutex(NULL, FALSE, NULL);
184 threads = calloc(max_threads, sizeof(threads[0]));
185 for (i = 0; i < max_threads; i++)
186 {
187
188 if (NULL ==
189 (threads[i] = CreateThread(NULL, // default security attributes
190 0, // default stack size
191 (LPTHREAD_START_ROUTINE)process_files,
192 NULL, // no thread function arguments
193 0, // default creation flags
194 &ThreadID) // receive thread identifier
195 ))
196 {
197 printf("CreateThread error: %d\n", GetLastError());
198 return 1;
199 }
200 }
201
202 WaitForMultipleObjects(max_threads, threads, TRUE, INFINITE);
203
204 // Close thread and mutex handles
205
206 for (i = 0; i < max_threads; i++)
207 CloseHandle(threads[i]);
208
209 CloseHandle(qmutex);
210
211 return 0;
212 }
213