File indexing completed on 2025-01-05 03:56:48

0001 /* -*- C++ -*-
0002  * File: halt_mt_win32.c
0003  * Copyright 2008-2021 LibRaw LLC (info@libraw.org)
0004  * Created: Sat Mar  8, 2008
0005  *
0006  * LibRaw  C API mutithreaded sample:  emulates call to "dcraw  -h [-w] [-a]
0007 [-v]"
0008  * Win32 version
0009 
0010 LibRaw is free software; you can redistribute it and/or modify
0011 it under the terms of the one of two licenses as you choose:
0012 
0013 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
0014    (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
0015 
0016 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
0017    (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
0018 
0019 
0020  */
0021 #include <stdio.h>
0022 #include <string.h>
0023 #include <stdlib.h>
0024 #include <math.h>
0025 #include <windows.h>
0026 #include "libraw/libraw.h"
0027 
0028 #ifdef LIBRAW_WIN32_CALLS
0029 #define snprintf _snprintf
0030 #endif
0031 
0032 #define HANDLE_ERRORS(ret)                                                     \
0033   do                                                                           \
0034   {                                                                            \
0035     if (ret)                                                                   \
0036     {                                                                          \
0037       fprintf(stderr, "%s: %s\n", fn, libraw_strerror(ret));                   \
0038       if (LIBRAW_FATAL_ERROR(ret))                                             \
0039       {                                                                        \
0040         libraw_close(iprc);                                                    \
0041         return -1;                                                             \
0042       }                                                                        \
0043     }                                                                          \
0044   } while (0)
0045 
0046 // global settings
0047 int verbose = 0, use_camera_wb = 0, use_auto_wb = 0, tiff_mode = 0;
0048 
0049 // global file queue
0050 HANDLE qmutex;
0051 char **queue = NULL;
0052 size_t qsize = 0, qptr = 0;
0053 
0054 char *get_next_file()
0055 {
0056   char *ret;
0057   DWORD dwWaitResult;
0058   if (!queue)
0059     return NULL;
0060   if (qptr >= qsize)
0061     return NULL;
0062 
0063   dwWaitResult = WaitForSingleObject(qmutex,    // handle to mutex
0064                                      INFINITE); // no time-out interval
0065   switch (dwWaitResult)
0066   {
0067   // The thread got ownership of the mutex
0068   case WAIT_OBJECT_0:
0069     ret = queue[qptr++];
0070     ReleaseMutex(qmutex);
0071     break;
0072   case WAIT_ABANDONED:
0073     return NULL; // cannot obtain the lock
0074   };
0075   return ret;
0076 }
0077 
0078 // thread routine
0079 int process_files(void *q)
0080 {
0081   int ret;
0082   int count = 0;
0083   char outfn[1024], *fn;
0084   libraw_data_t *iprc = libraw_init(0);
0085 
0086   if (!iprc)
0087   {
0088     fprintf(stderr, "Cannot create libraw handle\n");
0089     return -1;
0090   }
0091 
0092   while ((fn = get_next_file()))
0093   {
0094 
0095     iprc->params.half_size = 1; /* dcraw -h */
0096     iprc->params.use_camera_wb = use_camera_wb;
0097     iprc->params.use_auto_wb = use_auto_wb;
0098     iprc->params.output_tiff = tiff_mode;
0099 
0100     ret = libraw_open_file(iprc, fn);
0101     if (verbose)
0102       fprintf(stderr, "%s: %s/%s\n", fn, iprc->idata.make, iprc->idata.model);
0103     HANDLE_ERRORS(ret);
0104 
0105     ret = libraw_unpack(iprc);
0106     HANDLE_ERRORS(ret);
0107 
0108     ret = libraw_dcraw_process(iprc);
0109     HANDLE_ERRORS(ret);
0110 
0111     snprintf(outfn, 1023, "%s.%s", fn, tiff_mode ? "tif" : "ppm");
0112 
0113     if (verbose)
0114       fprintf(stderr, "Writing file %s\n", outfn);
0115     ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn);
0116     HANDLE_ERRORS(ret);
0117     count++;
0118   }
0119   libraw_close(iprc);
0120   printf("Processed %d files\n", count);
0121   return 0;
0122 }
0123 
0124 void usage(const char *p)
0125 {
0126   printf("Options:\n"
0127          "-J n  - set parallel job count (default 2)\n"
0128          "-v    - verbose\n"
0129          "-w    - use camera white balance\n"
0130          "-T    - output TIFF instead of PPM\n"
0131          "-a    - average image for white balance\n");
0132   exit(1);
0133 }
0134 
0135 int show_files(void *q)
0136 {
0137   char *p;
0138   int cnt = 0;
0139   while (p = get_next_file())
0140   {
0141     printf("%s\n", p);
0142     cnt++;
0143   }
0144   return cnt;
0145 }
0146 
0147 int main(int ac, char *av[])
0148 {
0149   int i, max_threads = 2;
0150   HANDLE *threads;
0151   DWORD ThreadID;
0152 
0153   if (ac < 2)
0154     usage(av[0]);
0155 
0156   queue = calloc(ac - 1, sizeof(queue[0]));
0157 
0158   for (i = 1; i < ac; i++)
0159   {
0160     if (av[i][0] == '-')
0161     {
0162       if (av[i][1] == 'w')
0163         use_camera_wb = 1;
0164       if (av[i][1] == 'a')
0165         use_auto_wb = 1;
0166       if (av[i][1] == 'v')
0167         verbose = 1;
0168       if (av[i][1] == 'T')
0169         tiff_mode = 1;
0170       if (av[i][1] == 'J')
0171       {
0172         max_threads = atoi(av[++i]);
0173         if (max_threads < 1)
0174         {
0175           fprintf(stderr, "Job count should be at least 1\n");
0176           exit(1);
0177         }
0178       }
0179     }
0180     else
0181       queue[qsize++] = av[i];
0182   }
0183   qmutex = CreateMutex(NULL, FALSE, NULL);
0184   threads = calloc(max_threads, sizeof(threads[0]));
0185   for (i = 0; i < max_threads; i++)
0186   {
0187 
0188     if (NULL ==
0189         (threads[i] = CreateThread(NULL, // default security attributes
0190                                    0,    // default stack size
0191                                    (LPTHREAD_START_ROUTINE)process_files,
0192                                    NULL,      // no thread function arguments
0193                                    0,         // default creation flags
0194                                    &ThreadID) // receive thread identifier
0195          ))
0196     {
0197       printf("CreateThread error: %d\n", GetLastError());
0198       return 1;
0199     }
0200   }
0201 
0202   WaitForMultipleObjects(max_threads, threads, TRUE, INFINITE);
0203 
0204   // Close thread and mutex handles
0205 
0206   for (i = 0; i < max_threads; i++)
0207     CloseHandle(threads[i]);
0208 
0209   CloseHandle(qmutex);
0210 
0211   return 0;
0212 }