| /* -*- C++ -*- |
| * File: simple_dcraw.cpp |
| * Copyright 2008-2025 LibRaw LLC (info@libraw.org) |
| * Created: Sat Mar 8, 2008 |
| * |
| * LibRaw simple C++ API: emulates call to "dcraw [-D] [-T] [-v] [-e] [-4]" |
| |
| LibRaw is free software; you can redistribute it and/or modify |
| it under the terms of the one of two licenses as you choose: |
| |
| 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 |
| (See file LICENSE.LGPL provided in LibRaw distribution archive for details). |
| |
| 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
| (See file LICENSE.CDDL provided in LibRaw distribution archive for details). |
| |
| |
| */ |
| #include <stdio.h> |
| #include <string.h> |
| #include <math.h> |
| |
| #include "third_party/libraw/libraw/libraw.h" |
| |
| #ifndef LIBRAW_WIN32_CALLS |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <sys/stat.h> |
| #include <sys/mman.h> |
| #endif |
| |
| #ifdef LIBRAW_WIN32_CALLS |
| #define snprintf _snprintf |
| #endif |
| |
| int my_progress_callback(void *unused_data, enum LibRaw_progress state, |
| int iter, int expected) |
| { |
| if (iter == 0) |
| printf("CB: state=%x, expected %d iterations\n", state, expected); |
| return 0; |
| } |
| |
| char *customCameras[] = { |
| (char *)"43704960,4080,5356, 0, 0, 0, 0,0,148,0,0, Dalsa, FTF4052C Full,0", |
| (char *)"42837504,4008,5344, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 3:4", |
| (char *)"32128128,4008,4008, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 1:1", |
| (char *)"24096096,4008,3006, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 4:3", |
| (char *)"18068064,4008,2254, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 16:9", |
| (char *)"67686894,5049,6703, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C Full", |
| (char *)"66573312,4992,6668, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 3:4", |
| (char *)"49840128,4992,4992, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 1:1", |
| (char *)"37400064,4992,3746, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 4:3", |
| (char *)"28035072,4992,2808, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 16:9", |
| NULL}; |
| |
| int main(int ac, char *av[]) |
| { |
| int i, ret, verbose = 0, output_thumbs = 0, output_all_thumbs = 0; |
| |
| // don't use fixed size buffers in real apps! |
| char outfn[1024], thumbfn[1024]; |
| |
| LibRaw* RawProcessor = new LibRaw; |
| RawProcessor->imgdata.rawparams.custom_camera_strings = customCameras; |
| if (ac < 2) |
| { |
| printf("simple_dcraw - LibRaw %s sample. Emulates dcraw [-D] [-T] [-v] " |
| "[-e] [-E]\n" |
| " %d cameras supported\n" |
| "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n" |
| "\t-4 - 16-bit mode\n" |
| "\t-L - list supported cameras and exit\n" |
| "\t-v - verbose output\n" |
| "\t-T - output TIFF files instead of .pgm/ppm\n" |
| "\t-e - extract thumbnails (same as dcraw -e in separate run)\n" |
| "\t-E - extract all thumbnails\n", |
| LibRaw::version(), LibRaw::cameraCount(), av[0]); |
| delete RawProcessor; |
| return 0; |
| } |
| |
| putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field |
| |
| #define P1 RawProcessor->imgdata.idata |
| #define S RawProcessor->imgdata.sizes |
| #define C RawProcessor->imgdata.color |
| #define T RawProcessor->imgdata.thumbnail |
| #define P2 RawProcessor->imgdata.other |
| #define OUT RawProcessor->imgdata.params |
| |
| for (i = 1; i < ac; i++) |
| { |
| if (av[i][0] == '-') |
| { |
| if (av[i][1] == 'T' && av[i][2] == 0) |
| OUT.output_tiff = 1; |
| if (av[i][1] == 'v' && av[i][2] == 0) |
| verbose++; |
| if (av[i][1] == 'e' && av[i][2] == 0) |
| output_thumbs++; |
| if (av[i][1] == 'E' && av[i][2] == 0) |
| { |
| output_thumbs++; |
| output_all_thumbs++; |
| } |
| if (av[i][1] == '4' && av[i][2] == 0) |
| OUT.output_bps = 16; |
| if (av[i][1] == 'C' && av[i][2] == 0) |
| RawProcessor->set_progress_handler(my_progress_callback, NULL); |
| if (av[i][1] == 'L' && av[i][2] == 0) |
| { |
| const char **clist = LibRaw::cameraList(); |
| const char **cc = clist; |
| while (*cc) |
| { |
| printf("%s\n", *cc); |
| cc++; |
| } |
| delete RawProcessor; |
| exit(0); |
| } |
| continue; |
| } |
| |
| if (verbose) |
| printf("Processing file %s\n", av[i]); |
| |
| RawProcessor->imgdata.rawparams.options |= LIBRAW_RAWOPTIONS_ALLOW_JPEGXL_PREVIEWS; |
| |
| if ((ret = RawProcessor->open_file(av[i])) != LIBRAW_SUCCESS) |
| { |
| fprintf(stderr, "Cannot open_file %s: %s\n", av[i], libraw_strerror(ret)); |
| continue; // no recycle b/c open file will recycle itself |
| } |
| |
| if (!output_thumbs) // No unpack for thumb extraction |
| if ((ret = RawProcessor->unpack()) != LIBRAW_SUCCESS) |
| { |
| fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret)); |
| continue; |
| } |
| |
| // thumbnail unpacking and output in the middle of main |
| // image processing - for test purposes! |
| if(output_all_thumbs) |
| { |
| if (verbose) |
| printf("Extracting %d thumbnails\n", RawProcessor->imgdata.thumbs_list.thumbcount); |
| for (int t = 0; t < RawProcessor->imgdata.thumbs_list.thumbcount; t++) |
| { |
| if ((ret = RawProcessor->unpack_thumb_ex(t)) != LIBRAW_SUCCESS) |
| fprintf(stderr, "Cannot unpack_thumb #%d from %s: %s\n", t, av[i], libraw_strerror(ret)); |
| if (LIBRAW_FATAL_ERROR(ret)) |
| break; // skip to next file |
| snprintf(thumbfn, sizeof(thumbfn), "%s.thumb.%d.%s", av[i], t, |
| T.tformat == LIBRAW_THUMBNAIL_JPEG ? "jpg" |
| : (T.tformat == LIBRAW_THUMBNAIL_JPEGXL ? "jxl" |
| : (T.tcolors == 1 ? "pgm" : "ppm"))); |
| if (verbose) |
| printf("Writing thumbnail file %s\n", thumbfn); |
| if (LIBRAW_SUCCESS != (ret = RawProcessor->dcraw_thumb_writer(thumbfn))) |
| { |
| fprintf(stderr, "Cannot write %s: %s\n", thumbfn, libraw_strerror(ret)); |
| if (LIBRAW_FATAL_ERROR(ret)) |
| break; |
| } |
| } |
| continue; |
| } |
| else if (output_thumbs) |
| { |
| if ((ret = RawProcessor->unpack_thumb()) != LIBRAW_SUCCESS) |
| { |
| fprintf(stderr, "Cannot unpack_thumb %s: %s\n", av[i], |
| libraw_strerror(ret)); |
| if (LIBRAW_FATAL_ERROR(ret)) |
| continue; // skip to next file |
| } |
| else |
| { |
| snprintf(thumbfn, sizeof(thumbfn), "%s.%s", av[i], |
| T.tformat == LIBRAW_THUMBNAIL_JPEG ? "thumb.jpg" |
| : (T.tformat == LIBRAW_THUMBNAIL_JPEGXL ? "thumb.jxl" |
| : (T.tcolors == 1? "thumb.pgm" : "thumb.ppm"))); |
| if (verbose) |
| printf("Writing thumbnail file %s\n", thumbfn); |
| if (LIBRAW_SUCCESS != (ret = RawProcessor->dcraw_thumb_writer(thumbfn))) |
| { |
| fprintf(stderr, "Cannot write %s: %s\n", thumbfn, |
| libraw_strerror(ret)); |
| if (LIBRAW_FATAL_ERROR(ret)) |
| continue; |
| } |
| } |
| continue; |
| } |
| |
| ret = RawProcessor->dcraw_process(); |
| |
| if (LIBRAW_SUCCESS != ret) |
| { |
| fprintf(stderr, "Cannot do postprocessing on %s: %s\n", av[i], |
| libraw_strerror(ret)); |
| if (LIBRAW_FATAL_ERROR(ret)) |
| continue; |
| } |
| snprintf(outfn, sizeof(outfn), "%s.%s", av[i], |
| OUT.output_tiff ? "tiff" : (P1.colors > 1 ? "ppm" : "pgm")); |
| |
| if (verbose) |
| printf("Writing file %s\n", outfn); |
| |
| if (LIBRAW_SUCCESS != (ret = RawProcessor->dcraw_ppm_tiff_writer(outfn))) |
| fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret)); |
| |
| RawProcessor->recycle(); // just for show this call |
| } |
| |
| delete RawProcessor; |
| return 0; |
| } |