1 /* -*- C++ -*-
2 * File: halt_mt.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 *
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 <pthread.h>
26
27 #include "libraw/libraw.h"
28
29 #define HANDLE_ERRORS(ret) \
30 do \
31 { \
32 if (ret) \
33 { \
34 fprintf(stderr, "%s: %s\n", fn, libraw_strerror(ret)); \
35 if (LIBRAW_FATAL_ERROR(ret)) \
36 { \
37 libraw_close(iprc); \
38 return NULL; \
39 } \
40 } \
41 } while (0)
42
43 int verbose = 0, use_camera_wb = 0, use_auto_wb = 0, tiff_mode = 0;
44
45 pthread_mutex_t qm;
46 char **queue = NULL;
47 size_t qsize = 0, qptr = 0;
48
get_next_file()49 char *get_next_file()
50 {
51 char *ret;
52 if (!queue)
53 return NULL;
54 if (qptr >= qsize)
55 return NULL;
56 pthread_mutex_lock(&qm);
57 ret = queue[qptr++];
58 pthread_mutex_unlock(&qm);
59 return ret;
60 }
61
process_files(void * q)62 void *process_files(void *q)
63 {
64 int ret;
65 int count = 0;
66 char outfn[1024], *fn;
67 libraw_data_t *iprc = libraw_init(0);
68
69 if (!iprc)
70 {
71 fprintf(stderr, "Cannot create libraw handle\n");
72 return NULL;
73 }
74
75 while ((fn = get_next_file()))
76 {
77
78 iprc->params.half_size = 1; /* dcraw -h */
79 iprc->params.use_camera_wb = use_camera_wb;
80 iprc->params.use_auto_wb = use_auto_wb;
81 iprc->params.output_tiff = tiff_mode;
82
83 ret = libraw_open_file(iprc, fn);
84 if (verbose)
85 fprintf(stderr, "%s: %s/%s\n", fn, iprc->idata.make, iprc->idata.model);
86 HANDLE_ERRORS(ret);
87
88 ret = libraw_unpack(iprc);
89 HANDLE_ERRORS(ret);
90
91 ret = libraw_dcraw_process(iprc);
92 HANDLE_ERRORS(ret);
93
94 snprintf(outfn, 1023, "%s.%s", fn, tiff_mode ? "tiff" : "ppm");
95
96 if (verbose)
97 fprintf(stderr, "Writing file %s\n", outfn);
98 ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn);
99 HANDLE_ERRORS(ret);
100 count++;
101 }
102 libraw_close(iprc);
103 return NULL;
104 }
105
usage(const char * p)106 void usage(const char *p)
107 {
108 printf("%s: Multi-threaded LibRaw sample app. Emulates dcraw -h [-w] [-a]\n",
109 p);
110 printf("Options:\n"
111 "-J n - set parallel job count (default 2)\n"
112 "-v - verbose\n"
113 "-w - use camera white balance\n"
114 "-a - average image for white balance\n");
115 exit(1);
116 }
117
show_files(void * q)118 int show_files(void *q)
119 {
120 char *p;
121 int cnt = 0;
122 while ((p = get_next_file()))
123 {
124 printf("%s\n", p);
125 cnt++;
126 }
127 return cnt;
128 }
129
main(int ac,char * av[])130 int main(int ac, char *av[])
131 {
132 int i, max_threads = 2;
133 pthread_t *threads;
134 if (ac < 2)
135 usage(av[0]);
136
137 queue = calloc(ac - 1, sizeof(queue[0]));
138
139 for (i = 1; i < ac; i++)
140 {
141 if (av[i][0] == '-')
142 {
143 if (av[i][1] == 'w')
144 use_camera_wb = 1;
145 if (av[i][1] == 'a')
146 use_auto_wb = 1;
147 if (av[i][1] == 'v')
148 verbose = 1;
149 if (av[i][1] == 'T')
150 tiff_mode = 1;
151 if (av[i][1] == 'J')
152 {
153 max_threads = atoi(av[++i]);
154 if (max_threads < 1)
155 {
156 fprintf(stderr, "Job count should be at least 1\n");
157 exit(1);
158 }
159 }
160 }
161 else
162 queue[qsize++] = av[i];
163 }
164 pthread_mutex_init(&qm, NULL);
165 threads = calloc(max_threads, sizeof(threads[0]));
166 for (i = 0; i < max_threads; i++)
167 pthread_create(&threads[i], NULL, process_files, NULL);
168 for (i = 0; i < max_threads; i++)
169 {
170 int *iptr;
171 if (threads[i])
172 {
173 pthread_join(threads[i], (void *)&iptr);
174 }
175 }
176
177 return 0;
178 }
179