Squashed 'rtengine/libraw/' content from commit cccb97647
git-subtree-dir: rtengine/libraw git-subtree-split: cccb97647fcee56801fa68231fa8a38aa8b52ef7
This commit is contained in:
174
samples/4channels.cpp
Normal file
174
samples/4channels.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/* -*- C++ -*-
|
||||
* File: 4channels.cpp
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Mon Feb 09, 2009
|
||||
*
|
||||
* LibRaw sample
|
||||
* Generates 4 TIFF file from RAW data, one file per channel
|
||||
*
|
||||
|
||||
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 "libraw/libraw.h"
|
||||
|
||||
#ifndef LIBRAW_WIN32_CALLS
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef LIBRAW_WIN32_CALLS
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
int i, ret;
|
||||
int autoscale = 0, black_subtraction = 1, use_gamma = 0;
|
||||
char outfn[1024];
|
||||
|
||||
LibRaw RawProcessor;
|
||||
if (ac < 2)
|
||||
{
|
||||
usage:
|
||||
printf("4channels - LibRaw %s sample. %d cameras supported\n"
|
||||
"Usage: %s [-s N] [-g] [-A] [-B] [-N] raw-files....\n"
|
||||
"\t-s N - select Nth image in file (default=0)\n"
|
||||
"\t-g - use gamma correction with gamma 2.2 (not precise,use for "
|
||||
"visual inspection only)\n"
|
||||
"\t-A - autoscaling (by integer factor)\n"
|
||||
"\t-B - no black subtraction\n",
|
||||
LibRaw::version(), LibRaw::cameraCount(), av[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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
|
||||
#define OUTR RawProcessor.imgdata.rawparams
|
||||
|
||||
OUT.output_bps = 16;
|
||||
OUT.output_tiff = 1;
|
||||
OUT.user_flip = 0;
|
||||
OUT.no_auto_bright = 1;
|
||||
OUT.half_size = 1;
|
||||
|
||||
for (i = 1; i < ac; i++)
|
||||
{
|
||||
if (av[i][0] == '-')
|
||||
{
|
||||
if (av[i][1] == 's' && av[i][2] == 0)
|
||||
{
|
||||
i++;
|
||||
OUTR.shot_select = av[i] ? atoi(av[i]) : 0;
|
||||
}
|
||||
else if (av[i][1] == 'g' && av[i][2] == 0)
|
||||
use_gamma = 1;
|
||||
else if (av[i][1] == 'A' && av[i][2] == 0)
|
||||
autoscale = 1;
|
||||
else if (av[i][1] == 'B' && av[i][2] == 0)
|
||||
{
|
||||
black_subtraction = 0;
|
||||
}
|
||||
else
|
||||
goto usage;
|
||||
continue;
|
||||
}
|
||||
if (!use_gamma)
|
||||
OUT.gamm[0] = OUT.gamm[1] = 1;
|
||||
|
||||
int c;
|
||||
printf("Processing file %s\n", av[i]);
|
||||
if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret));
|
||||
continue; // no recycle b/c open file will recycle itself
|
||||
}
|
||||
if (P1.is_foveon)
|
||||
{
|
||||
printf("Cannot process Foveon image %s\n", av[i]);
|
||||
continue;
|
||||
}
|
||||
if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
|
||||
continue;
|
||||
}
|
||||
RawProcessor.raw2image();
|
||||
if (black_subtraction)
|
||||
{
|
||||
RawProcessor.subtract_black();
|
||||
}
|
||||
|
||||
if (autoscale)
|
||||
{
|
||||
unsigned max = 0, scale = 1;
|
||||
for (int j = 0; j < S.iheight * S.iwidth; j++)
|
||||
for (int c = 0; c < 4; c++)
|
||||
if (max < RawProcessor.imgdata.image[j][c])
|
||||
max = RawProcessor.imgdata.image[j][c];
|
||||
if (max > 0 && max < 1 << 15)
|
||||
{
|
||||
scale = (1 << 16) / max;
|
||||
printf("Scaling with multiplier=%d (max=%d)\n", scale, max);
|
||||
for (int j = 0; j < S.iheight * S.iwidth; j++)
|
||||
for (c = 0; c < 4; c++)
|
||||
RawProcessor.imgdata.image[j][c] *= scale;
|
||||
}
|
||||
printf("Black level (scaled)=%d\n", C.black * scale);
|
||||
}
|
||||
else
|
||||
printf("Black level (unscaled)=%d\n", C.black);
|
||||
|
||||
// hack to make dcraw tiff writer happy
|
||||
int isrgb = (P1.colors == 4 ? 0 : 1);
|
||||
P1.colors = 1;
|
||||
S.width = S.iwidth;
|
||||
S.height = S.iheight;
|
||||
|
||||
for (int layer = 0; layer < 4; layer++)
|
||||
{
|
||||
if (layer > 0)
|
||||
{
|
||||
for (int rc = 0; rc < S.iheight * S.iwidth; rc++)
|
||||
RawProcessor.imgdata.image[rc][0] =
|
||||
RawProcessor.imgdata.image[rc][layer];
|
||||
}
|
||||
char lname[8];
|
||||
if (isrgb)
|
||||
{
|
||||
snprintf(lname, 7, "%c", ((char *)("RGBG"))[layer]);
|
||||
if (layer == 3)
|
||||
strcat(lname, "2");
|
||||
}
|
||||
else
|
||||
snprintf(lname, 7, "%c", ((char *)("GCMY"))[layer]);
|
||||
|
||||
if (OUTR.shot_select)
|
||||
snprintf(outfn, sizeof(outfn), "%s-%d.%s.tiff", av[i], OUTR.shot_select,
|
||||
lname);
|
||||
else
|
||||
snprintf(outfn, sizeof(outfn), "%s.%s.tiff", av[i], lname);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
2
samples/Makefile
Normal file
2
samples/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
all:
|
||||
(cd ..; make all_samples)
|
670
samples/dcraw_emu.cpp
Normal file
670
samples/dcraw_emu.cpp
Normal file
@@ -0,0 +1,670 @@
|
||||
/* -*- C++ -*-
|
||||
* File: dcraw_emu.cpp
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Sun Mar 23, 2008
|
||||
*
|
||||
* LibRaw simple C++ API sample: almost complete dcraw emulator
|
||||
*
|
||||
|
||||
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).
|
||||
|
||||
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
// suppress sprintf-related warning. sprintf() is permitted in sample code
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libraw/libraw.h"
|
||||
|
||||
#ifndef LIBRAW_WIN32_CALLS
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef LIBRAW_WIN32_CALLS
|
||||
#define snprintf _snprintf
|
||||
#include <windows.h>
|
||||
#else
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifdef USE_DNGSDK
|
||||
#include "dng_host.h"
|
||||
#include "dng_negative.h"
|
||||
#include "dng_simple_image.h"
|
||||
#include "dng_info.h"
|
||||
#endif
|
||||
|
||||
void usage(const char *prog)
|
||||
{
|
||||
printf("dcraw_emu: almost complete dcraw emulator\n");
|
||||
printf("Usage: %s [OPTION]... [FILE]...\n", prog);
|
||||
printf("-c float-num Set adjust maximum threshold (default 0.75)\n"
|
||||
"-v Verbose: print progress messages (repeated -v will add "
|
||||
"verbosity)\n"
|
||||
"-w Use camera white balance, if possible\n"
|
||||
"-a Average the whole image for white balance\n"
|
||||
"-A <x y w h> Average a grey box for white balance\n"
|
||||
"-r <r g b g> Set custom white balance\n"
|
||||
"+M/-M Use/don't use an embedded color matrix\n"
|
||||
"-C <r b> Correct chromatic aberration\n"
|
||||
"-P <file> Fix the dead pixels listed in this file\n"
|
||||
"-K <file> Subtract dark frame (16-bit raw PGM)\n"
|
||||
"-k <num> Set the darkness level\n"
|
||||
"-S <num> Set the saturation level\n"
|
||||
"-R <num> Set raw processing options to num\n"
|
||||
"-n <num> Set threshold for wavelet denoising\n"
|
||||
"-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)\n"
|
||||
"-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)\n"
|
||||
"-o [0-8] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ,ACES,\n"
|
||||
" DCI-P3,Rec2020)\n"
|
||||
#ifndef NO_LCMS
|
||||
"-o file Output ICC profile\n"
|
||||
"-p file Camera input profile (use \'embed\' for embedded profile)\n"
|
||||
#endif
|
||||
"-j Don't stretch or rotate raw pixels\n"
|
||||
"-W Don't automatically brighten the image\n"
|
||||
"-b <num> Adjust brightness (default = 1.0)\n"
|
||||
"-q N Set the interpolation quality:\n"
|
||||
" 0 - linear, 1 - VNG, 2 - PPG, 3 - AHD, 4 - DCB\n"
|
||||
" 11 - DHT, 12 - AAHD\n"
|
||||
"-h Half-size color image (twice as fast as \"-q 0\")\n"
|
||||
"-f Interpolate RGGB as four colors\n"
|
||||
"-m <num> Apply a 3x3 median filter to R-G and B-G\n"
|
||||
"-s [0..N-1] Select one raw image from input file\n"
|
||||
"-4 Linear 16-bit, same as \"-6 -W -g 1 1\n"
|
||||
"-6 Write 16-bit output\n"
|
||||
"-g pow ts Set gamma curve to gamma pow and toe slope ts (default = "
|
||||
"2.222 4.5)\n"
|
||||
"-T Write TIFF instead of PPM\n"
|
||||
"-G Use green_matching() filter\n"
|
||||
"-B <x y w h> use cropbox\n"
|
||||
"-F Use FILE I/O instead of streambuf API\n"
|
||||
"-Z <suf> Output filename generation rules\n"
|
||||
" .suf => append .suf to input name, keeping existing suffix "
|
||||
"too\n"
|
||||
" suf => replace input filename last extension\n"
|
||||
" - => output to stdout\n"
|
||||
" filename.suf => output to filename.suf\n"
|
||||
"-timing Detailed timing report\n"
|
||||
"-fbdd N 0 - disable FBDD noise reduction (default), 1 - light "
|
||||
"FBDD, 2 - full\n"
|
||||
"-dcbi N Number of extra DCD iterations (default - 0)\n"
|
||||
"-dcbe DCB color enhance\n"
|
||||
"-aexpo <e p> exposure correction\n"
|
||||
"-apentax4shot enables merge of 4-shot pentax files\n"
|
||||
"-apentax4shotorder 3102 sets pentax 4-shot alignment order\n"
|
||||
#ifdef USE_RAWSPEED_BITS
|
||||
"-arsbits V Set use_rawspeed to V\n"
|
||||
#endif
|
||||
"-mmap Use memory mmaped buffer instead of plain FILE I/O\n"
|
||||
"-mem Use memory buffer instead of FILE I/O\n"
|
||||
"-disars Do not use RawSpeed library\n"
|
||||
"-disinterp Do not run interpolation step\n"
|
||||
"-dsrawrgb1 Disable YCbCr to RGB conversion for sRAW (Cb/Cr "
|
||||
"interpolation enabled)\n"
|
||||
"-dsrawrgb2 Disable YCbCr to RGB conversion for sRAW (Cb/Cr "
|
||||
"interpolation disabled)\n"
|
||||
#ifdef USE_DNGSDK
|
||||
"-dngsdk Use Adobe DNG SDK for DNG decode\n"
|
||||
"-dngflags N set DNG decoding options to value N\n"
|
||||
#endif
|
||||
"-doutputflags N set params.output_flags to N\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int verbosity = 0;
|
||||
int cnt = 0;
|
||||
int my_progress_callback(void *d, enum LibRaw_progress p, int iteration,
|
||||
int expected)
|
||||
{
|
||||
char *passed = (char *)(d ? d : "default string"); // data passed to callback
|
||||
// at set_callback stage
|
||||
|
||||
if (verbosity > 2) // verbosity set by repeat -v switches
|
||||
{
|
||||
printf("CB: %s pass %d of %d (data passed=%s)\n", libraw_strprogress(p),
|
||||
iteration, expected, passed);
|
||||
}
|
||||
else if (iteration == 0) // 1st iteration of each step
|
||||
printf("Starting %s (expecting %d iterations)\n", libraw_strprogress(p),
|
||||
expected);
|
||||
else if (iteration == expected - 1)
|
||||
printf("%s finished\n", libraw_strprogress(p));
|
||||
|
||||
/// if(++cnt>10) return 1; // emulate user termination on 10-th callback
|
||||
/// call
|
||||
|
||||
return 0; // always return 0 to continue processing
|
||||
}
|
||||
|
||||
// timer
|
||||
#ifndef LIBRAW_WIN32_CALLS
|
||||
static struct timeval start, end;
|
||||
void timerstart(void) { gettimeofday(&start, NULL); }
|
||||
void timerprint(const char *msg, const char *filename)
|
||||
{
|
||||
gettimeofday(&end, NULL);
|
||||
float msec = (end.tv_sec - start.tv_sec) * 1000.0f +
|
||||
(end.tv_usec - start.tv_usec) / 1000.0f;
|
||||
printf("Timing: %s/%s: %6.3f msec\n", filename, msg, msec);
|
||||
}
|
||||
#else
|
||||
LARGE_INTEGER start;
|
||||
void timerstart(void) { QueryPerformanceCounter(&start); }
|
||||
void timerprint(const char *msg, const char *filename)
|
||||
{
|
||||
LARGE_INTEGER unit, end;
|
||||
QueryPerformanceCounter(&end);
|
||||
QueryPerformanceFrequency(&unit);
|
||||
float msec = (float)(end.QuadPart - start.QuadPart);
|
||||
msec /= (float)unit.QuadPart / 1000.0f;
|
||||
printf("Timing: %s/%s: %6.3f msec\n", filename, msg, msec);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct file_mapping
|
||||
{
|
||||
void *map;
|
||||
INT64 fsize;
|
||||
#ifdef LIBRAW_WIN32_CALLS
|
||||
HANDLE fd, fd_map;
|
||||
file_mapping() : map(0), fsize(0), fd(INVALID_HANDLE_VALUE), fd_map(INVALID_HANDLE_VALUE){}
|
||||
#else
|
||||
int fd;
|
||||
file_mapping() : map(0), fsize(0), fd(-1){}
|
||||
#endif
|
||||
};
|
||||
|
||||
void create_mapping(struct file_mapping& data, const std::string& fn)
|
||||
{
|
||||
#ifdef LIBRAW_WIN32_CALLS
|
||||
std::wstring fpath(fn.begin(), fn.end());
|
||||
if ((data.fd = CreateFileW(fpath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) return;
|
||||
LARGE_INTEGER fs;
|
||||
if (!GetFileSizeEx(data.fd, &fs)) return;
|
||||
data.fsize = fs.QuadPart;
|
||||
if ((data.fd_map = ::CreateFileMapping(data.fd, 0, PAGE_READONLY, fs.HighPart, fs.LowPart, 0)) == INVALID_HANDLE_VALUE) return;
|
||||
data.map = MapViewOfFile(data.fd_map, FILE_MAP_READ, 0, 0, data.fsize);
|
||||
#else
|
||||
struct stat stt;
|
||||
if ((data.fd = open(fn.c_str(), O_RDONLY)) < 0) return;
|
||||
if (fstat(data.fd, &stt) != 0) return;
|
||||
data.fsize = stt.st_size;
|
||||
data.map = mmap(0, data.fsize, PROT_READ | PROT_WRITE, MAP_PRIVATE, data.fd, 0);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
void close_mapping(struct file_mapping& data)
|
||||
{
|
||||
#ifdef LIBRAW_WIN32_CALLS
|
||||
if (data.map) UnmapViewOfFile(data.map);
|
||||
if (data.fd_map != INVALID_HANDLE_VALUE) CloseHandle(data.fd_map);
|
||||
if (data.fd != INVALID_HANDLE_VALUE) CloseHandle(data.fd);
|
||||
data.map = 0;
|
||||
data.fsize = 0;
|
||||
data.fd = data.fd_map = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
if (data.map)
|
||||
munmap(data.map, data.fsize);
|
||||
if (data.fd >= 0)
|
||||
close(data.fd);
|
||||
data.map = 0;
|
||||
data.fsize = 0;
|
||||
data.fd = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc == 1)
|
||||
usage(argv[0]);
|
||||
|
||||
LibRaw RawProcessor;
|
||||
int i, arg, c, ret;
|
||||
char opm, opt, *cp, *sp;
|
||||
int use_timing = 0, use_mem = 0, use_mmap = 0;
|
||||
char *outext = NULL;
|
||||
#ifdef USE_DNGSDK
|
||||
dng_host *dnghost = NULL;
|
||||
#endif
|
||||
struct file_mapping mapping;
|
||||
void *iobuffer = 0;
|
||||
#ifdef OUT
|
||||
#undef OUT
|
||||
#endif
|
||||
#define OUT RawProcessor.imgdata.params
|
||||
#define OUTR RawProcessor.imgdata.rawparams
|
||||
|
||||
argv[argc] = (char *)"";
|
||||
for (arg = 1; (((opm = argv[arg][0]) - 2) | 2) == '+';)
|
||||
{
|
||||
char *optstr = argv[arg];
|
||||
opt = argv[arg++][1];
|
||||
if ((cp = strchr(sp = (char *)"cnbrkStqmHABCgU", opt)) != 0)
|
||||
for (i = 0; i < "111411111144221"[cp - sp] - '0'; i++)
|
||||
if (!isdigit(argv[arg + i][0]) && !optstr[2])
|
||||
{
|
||||
fprintf(stderr, "Non-numeric argument to \"-%c\"\n", opt);
|
||||
return 1;
|
||||
}
|
||||
if (!strchr("ftdeam", opt) && argv[arg - 1][2]) {
|
||||
fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
|
||||
continue;
|
||||
}
|
||||
switch (opt)
|
||||
{
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
case 'G':
|
||||
OUT.green_matching = 1;
|
||||
break;
|
||||
case 'c':
|
||||
OUT.adjust_maximum_thr = (float)atof(argv[arg++]);
|
||||
break;
|
||||
case 'U':
|
||||
OUT.auto_bright_thr = (float)atof(argv[arg++]);
|
||||
break;
|
||||
case 'n':
|
||||
OUT.threshold = (float)atof(argv[arg++]);
|
||||
break;
|
||||
case 'b':
|
||||
OUT.bright = (float)atof(argv[arg++]);
|
||||
break;
|
||||
case 'P':
|
||||
OUT.bad_pixels = argv[arg++];
|
||||
break;
|
||||
case 'K':
|
||||
OUT.dark_frame = argv[arg++];
|
||||
break;
|
||||
case 'r':
|
||||
for (c = 0; c < 4; c++)
|
||||
OUT.user_mul[c] = (float)atof(argv[arg++]);
|
||||
break;
|
||||
case 'C':
|
||||
OUT.aber[0] = 1 / atof(argv[arg++]);
|
||||
OUT.aber[2] = 1 / atof(argv[arg++]);
|
||||
break;
|
||||
case 'g':
|
||||
OUT.gamm[0] = 1 / atof(argv[arg++]);
|
||||
OUT.gamm[1] = atof(argv[arg++]);
|
||||
break;
|
||||
case 'k':
|
||||
OUT.user_black = atoi(argv[arg++]);
|
||||
break;
|
||||
case 'S':
|
||||
OUT.user_sat = atoi(argv[arg++]);
|
||||
break;
|
||||
case 'R':
|
||||
OUTR.options = atoi(argv[arg++]);
|
||||
break;
|
||||
case 't':
|
||||
if (!strcmp(optstr, "-timing"))
|
||||
use_timing = 1;
|
||||
else if (!argv[arg - 1][2])
|
||||
OUT.user_flip = atoi(argv[arg++]);
|
||||
else
|
||||
fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
|
||||
break;
|
||||
case 'q':
|
||||
OUT.user_qual = atoi(argv[arg++]);
|
||||
break;
|
||||
case 'm':
|
||||
if (!strcmp(optstr, "-mmap"))
|
||||
use_mmap = 1;
|
||||
else
|
||||
if (!strcmp(optstr, "-mem"))
|
||||
use_mem = 1;
|
||||
else
|
||||
{
|
||||
if (!argv[arg - 1][2])
|
||||
OUT.med_passes = atoi(argv[arg++]);
|
||||
else
|
||||
fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
|
||||
}
|
||||
break;
|
||||
case 'H':
|
||||
OUT.highlight = atoi(argv[arg++]);
|
||||
break;
|
||||
case 's':
|
||||
OUTR.shot_select = abs(atoi(argv[arg++]));
|
||||
break;
|
||||
case 'o':
|
||||
if (isdigit(argv[arg][0]) && !isdigit(argv[arg][1]))
|
||||
OUT.output_color = atoi(argv[arg++]);
|
||||
#ifndef NO_LCMS
|
||||
else
|
||||
OUT.output_profile = argv[arg++];
|
||||
break;
|
||||
case 'p':
|
||||
OUT.camera_profile = argv[arg++];
|
||||
#endif
|
||||
break;
|
||||
case 'h':
|
||||
OUT.half_size = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if (!strcmp(optstr, "-fbdd"))
|
||||
OUT.fbdd_noiserd = atoi(argv[arg++]);
|
||||
else
|
||||
{
|
||||
if (!argv[arg - 1][2])
|
||||
OUT.four_color_rgb = 1;
|
||||
else
|
||||
fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
for (c = 0; c < 4; c++)
|
||||
OUT.greybox[c] = atoi(argv[arg++]);
|
||||
break;
|
||||
case 'B':
|
||||
for (c = 0; c < 4; c++)
|
||||
OUT.cropbox[c] = atoi(argv[arg++]);
|
||||
break;
|
||||
case 'a':
|
||||
if (!strcmp(optstr, "-aexpo"))
|
||||
{
|
||||
OUT.exp_correc = 1;
|
||||
OUT.exp_shift = (float)atof(argv[arg++]);
|
||||
OUT.exp_preser = (float)atof(argv[arg++]);
|
||||
}
|
||||
#ifdef USE_RAWSPEED_BITS
|
||||
else if (!strcmp(optstr, "-arsbits"))
|
||||
{
|
||||
OUTR.use_rawspeed = atoi(argv[arg++]);
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(optstr, "-apentax4shot"))
|
||||
{
|
||||
OUTR.options |= LIBRAW_RAWOPTIONS_PENTAX_PS_ALLFRAMES;
|
||||
}
|
||||
else if (!strcmp(optstr, "-apentax4shotorder"))
|
||||
{
|
||||
strncpy(OUTR.p4shot_order, argv[arg++], 5);
|
||||
}
|
||||
else if (!argv[arg - 1][2])
|
||||
OUT.use_auto_wb = 1;
|
||||
else
|
||||
fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
|
||||
break;
|
||||
case 'w':
|
||||
OUT.use_camera_wb = 1;
|
||||
break;
|
||||
case 'M':
|
||||
OUT.use_camera_matrix = (opm == '+')?3:0;
|
||||
break;
|
||||
case 'j':
|
||||
OUT.use_fuji_rotate = 0;
|
||||
break;
|
||||
case 'W':
|
||||
OUT.no_auto_bright = 1;
|
||||
break;
|
||||
case 'T':
|
||||
OUT.output_tiff = 1;
|
||||
break;
|
||||
case '4':
|
||||
OUT.gamm[0] = OUT.gamm[1] = OUT.no_auto_bright = 1; /* no break here! */
|
||||
case '6':
|
||||
OUT.output_bps = 16;
|
||||
break;
|
||||
case 'Z':
|
||||
outext = strdup(argv[arg++]);
|
||||
break;
|
||||
case 'd':
|
||||
if (!strcmp(optstr, "-dcbi"))
|
||||
OUT.dcb_iterations = atoi(argv[arg++]);
|
||||
else if (!strcmp(optstr, "-doutputflags"))
|
||||
OUT.output_flags = atoi(argv[arg++]);
|
||||
else if (!strcmp(optstr, "-disars"))
|
||||
OUTR.use_rawspeed = 0;
|
||||
else if (!strcmp(optstr, "-disinterp"))
|
||||
OUT.no_interpolation = 1;
|
||||
else if (!strcmp(optstr, "-dcbe"))
|
||||
OUT.dcb_enhance_fl = 1;
|
||||
else if (!strcmp(optstr, "-dsrawrgb1"))
|
||||
{
|
||||
OUTR.specials |= LIBRAW_RAWSPECIAL_SRAW_NO_RGB;
|
||||
OUTR.specials &= ~LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE;
|
||||
}
|
||||
else if (!strcmp(optstr, "-dsrawrgb2"))
|
||||
{
|
||||
OUTR.specials &= ~LIBRAW_RAWSPECIAL_SRAW_NO_RGB;
|
||||
OUTR.specials |= LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE;
|
||||
}
|
||||
#ifdef USE_DNGSDK
|
||||
else if (!strcmp(optstr, "-dngsdk"))
|
||||
{
|
||||
dnghost = new dng_host;
|
||||
RawProcessor.set_dng_host(dnghost);
|
||||
}
|
||||
else if (!strcmp(optstr, "-dngflags"))
|
||||
{
|
||||
OUTR.use_dngsdk = atoi(argv[arg++]);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown option \"-%c\".\n", opt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifndef LIBRAW_WIN32_CALLS
|
||||
putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
|
||||
#else
|
||||
_putenv(
|
||||
(char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
|
||||
#endif
|
||||
#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
|
||||
|
||||
if (outext && !strcmp(outext, "-"))
|
||||
use_timing = verbosity = 0;
|
||||
|
||||
if (verbosity > 1)
|
||||
RawProcessor.set_progress_handler(my_progress_callback,
|
||||
(void *)"Sample data passed");
|
||||
#ifdef LIBRAW_USE_OPENMP
|
||||
if (verbosity)
|
||||
printf("Using %d threads\n", omp_get_max_threads());
|
||||
#endif
|
||||
|
||||
int done = 0;
|
||||
int total = argc - arg;
|
||||
for (; arg < argc; arg++)
|
||||
{
|
||||
char outfn[1024];
|
||||
|
||||
if (verbosity)
|
||||
printf("Processing file %s\n", argv[arg]);
|
||||
|
||||
timerstart();
|
||||
|
||||
if (use_mmap)
|
||||
{
|
||||
create_mapping(mapping, argv[arg]);
|
||||
if (!mapping.map)
|
||||
{
|
||||
fprintf(stderr, "Cannot map %s\n", argv[arg]);
|
||||
close_mapping(mapping);
|
||||
continue;
|
||||
}
|
||||
if ((ret = RawProcessor.open_buffer(mapping.map,mapping.fsize) !=
|
||||
LIBRAW_SUCCESS))
|
||||
{
|
||||
fprintf(stderr, "Cannot open_buffer %s: %s\n", argv[arg], libraw_strerror(ret));
|
||||
close_mapping(mapping);
|
||||
continue; // no recycle b/c open file will recycle itself
|
||||
}
|
||||
}
|
||||
else if (use_mem)
|
||||
{
|
||||
int file = open(argv[arg], O_RDONLY | O_BINARY);
|
||||
struct stat st;
|
||||
if (file < 0)
|
||||
{
|
||||
fprintf(stderr, "Cannot open %s: %s\n", argv[arg], strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (fstat(file, &st))
|
||||
{
|
||||
fprintf(stderr, "Cannot stat %s: %s\n", argv[arg], strerror(errno));
|
||||
close(file);
|
||||
continue;
|
||||
}
|
||||
if (!(iobuffer = malloc(st.st_size)))
|
||||
{
|
||||
fprintf(stderr, "Cannot allocate %d kbytes for memory buffer\n",
|
||||
(int)(st.st_size / 1024));
|
||||
close(file);
|
||||
continue;
|
||||
}
|
||||
int rd;
|
||||
if (st.st_size != (rd = read(file, iobuffer, st.st_size)))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Cannot read %d bytes instead of %d to memory buffer\n",
|
||||
(int)rd, (int)st.st_size);
|
||||
close(file);
|
||||
free(iobuffer);
|
||||
continue;
|
||||
}
|
||||
close(file);
|
||||
if ((ret = RawProcessor.open_buffer(iobuffer, st.st_size)) !=
|
||||
LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot open_buffer %s: %s\n", argv[arg],
|
||||
libraw_strerror(ret));
|
||||
free(iobuffer);
|
||||
continue; // no recycle b/c open file will recycle itself
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = RawProcessor.open_file(argv[arg]);
|
||||
|
||||
if (ret != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot open %s: %s\n", argv[arg],
|
||||
libraw_strerror(ret));
|
||||
continue; // no recycle b/c open_file will recycle itself
|
||||
}
|
||||
}
|
||||
|
||||
if (use_timing)
|
||||
timerprint("LibRaw::open_file()", argv[arg]);
|
||||
|
||||
timerstart();
|
||||
if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot unpack %s: %s\n", argv[arg],
|
||||
libraw_strerror(ret));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (use_timing)
|
||||
timerprint("LibRaw::unpack()", argv[arg]);
|
||||
|
||||
timerstart();
|
||||
if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_process()))
|
||||
{
|
||||
fprintf(stderr, "Cannot do postprocessing on %s: %s\n", argv[arg],
|
||||
libraw_strerror(ret));
|
||||
if (LIBRAW_FATAL_ERROR(ret))
|
||||
continue;
|
||||
}
|
||||
if (use_timing)
|
||||
timerprint("LibRaw::dcraw_process()", argv[arg]);
|
||||
|
||||
if (!outext)
|
||||
snprintf(outfn, sizeof(outfn), "%s.%s", argv[arg],
|
||||
OUT.output_tiff ? "tiff" : (P1.colors > 1 ? "ppm" : "pgm"));
|
||||
else if (!strcmp(outext, "-"))
|
||||
snprintf(outfn, sizeof(outfn), "-");
|
||||
else
|
||||
{
|
||||
if (*outext == '.') // append
|
||||
snprintf(outfn, sizeof(outfn), "%s%s", argv[arg], outext);
|
||||
else if (strchr(outext, '.') && *outext != '.') // dot is not 1st char
|
||||
strncpy(outfn, outext, sizeof(outfn));
|
||||
else
|
||||
{
|
||||
strncpy(outfn, argv[arg], sizeof(outfn));
|
||||
if (strlen(outfn) > 0)
|
||||
{
|
||||
char *lastchar = outfn + strlen(outfn); // points to term 0
|
||||
while (--lastchar > outfn)
|
||||
{
|
||||
if (*lastchar == '/' || *lastchar == '\\')
|
||||
break;
|
||||
if (*lastchar == '.')
|
||||
{
|
||||
*lastchar = 0;
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
strncat(outfn, ".", sizeof(outfn) - strlen(outfn) - 1);
|
||||
strncat(outfn, outext, sizeof(outfn) - strlen(outfn) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbosity)
|
||||
{
|
||||
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));
|
||||
else
|
||||
done++;
|
||||
|
||||
RawProcessor.recycle(); // just for show this call
|
||||
|
||||
if (use_mmap && mapping.map)
|
||||
close_mapping(mapping);
|
||||
else if (use_mem && iobuffer)
|
||||
{
|
||||
free(iobuffer);
|
||||
iobuffer = 0;
|
||||
}
|
||||
}
|
||||
#ifdef USE_DNGSDK
|
||||
if (dnghost)
|
||||
delete dnghost;
|
||||
#endif
|
||||
if (total == 0)
|
||||
return 1;
|
||||
if (done < total)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
78
samples/dcraw_half.c
Normal file
78
samples/dcraw_half.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/* -*- C++ -*-
|
||||
* File: dcraw_half.c
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Sat Mar 8 , 2008
|
||||
*
|
||||
* LibRaw C API sample: emulates "dcraw -h"
|
||||
*
|
||||
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 <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "libraw/libraw.h"
|
||||
|
||||
#define HANDLE_FATAL_ERROR(ret) \
|
||||
if (ret) \
|
||||
{ \
|
||||
fprintf(stderr, "%s: libraw %s\n", av[i], libraw_strerror(ret)); \
|
||||
if (LIBRAW_FATAL_ERROR(ret)) \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define HANDLE_ALL_ERRORS(ret) \
|
||||
if (ret) \
|
||||
{ \
|
||||
fprintf(stderr, "%s: libraw %s\n", av[i], libraw_strerror(ret)); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
int i;
|
||||
libraw_data_t *iprc = libraw_init(0);
|
||||
|
||||
if (!iprc)
|
||||
{
|
||||
fprintf(stderr, "Cannot create libraw handle\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
iprc->params.half_size = 1; /* dcraw -h */
|
||||
|
||||
for (i = 1; i < ac; i++)
|
||||
{
|
||||
char outfn[1024];
|
||||
int ret = libraw_open_file(iprc, av[i]);
|
||||
HANDLE_ALL_ERRORS(ret);
|
||||
|
||||
printf("Processing %s (%s %s)\n", av[i], iprc->idata.make,
|
||||
iprc->idata.model);
|
||||
|
||||
ret = libraw_unpack(iprc);
|
||||
HANDLE_ALL_ERRORS(ret);
|
||||
|
||||
ret = libraw_dcraw_process(iprc);
|
||||
HANDLE_ALL_ERRORS(ret);
|
||||
|
||||
strcpy(outfn, av[i]);
|
||||
strcat(outfn, ".ppm");
|
||||
printf("Writing to %s\n", outfn);
|
||||
|
||||
ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn);
|
||||
HANDLE_FATAL_ERROR(ret);
|
||||
}
|
||||
libraw_close(iprc);
|
||||
return 0;
|
||||
}
|
178
samples/half_mt.c
Normal file
178
samples/half_mt.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/* -*- C++ -*-
|
||||
* File: halt_mt.c
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Sat Mar 8, 2008
|
||||
*
|
||||
* LibRaw C API mutithreaded sample: emulates call to "dcraw -h [-w] [-a]
|
||||
[-v]"
|
||||
*
|
||||
|
||||
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 <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "libraw/libraw.h"
|
||||
|
||||
#define HANDLE_ERRORS(ret) \
|
||||
do \
|
||||
{ \
|
||||
if (ret) \
|
||||
{ \
|
||||
fprintf(stderr, "%s: %s\n", fn, libraw_strerror(ret)); \
|
||||
if (LIBRAW_FATAL_ERROR(ret)) \
|
||||
{ \
|
||||
libraw_close(iprc); \
|
||||
return NULL; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int verbose = 0, use_camera_wb = 0, use_auto_wb = 0, tiff_mode = 0;
|
||||
|
||||
pthread_mutex_t qm;
|
||||
char **queue = NULL;
|
||||
size_t qsize = 0, qptr = 0;
|
||||
|
||||
char *get_next_file()
|
||||
{
|
||||
char *ret;
|
||||
if (!queue)
|
||||
return NULL;
|
||||
if (qptr >= qsize)
|
||||
return NULL;
|
||||
pthread_mutex_lock(&qm);
|
||||
ret = queue[qptr++];
|
||||
pthread_mutex_unlock(&qm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *process_files(void *q)
|
||||
{
|
||||
int ret;
|
||||
int count = 0;
|
||||
char outfn[1024], *fn;
|
||||
libraw_data_t *iprc = libraw_init(0);
|
||||
|
||||
if (!iprc)
|
||||
{
|
||||
fprintf(stderr, "Cannot create libraw handle\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((fn = get_next_file()))
|
||||
{
|
||||
|
||||
iprc->params.half_size = 1; /* dcraw -h */
|
||||
iprc->params.use_camera_wb = use_camera_wb;
|
||||
iprc->params.use_auto_wb = use_auto_wb;
|
||||
iprc->params.output_tiff = tiff_mode;
|
||||
|
||||
ret = libraw_open_file(iprc, fn);
|
||||
if (verbose)
|
||||
fprintf(stderr, "%s: %s/%s\n", fn, iprc->idata.make, iprc->idata.model);
|
||||
HANDLE_ERRORS(ret);
|
||||
|
||||
ret = libraw_unpack(iprc);
|
||||
HANDLE_ERRORS(ret);
|
||||
|
||||
ret = libraw_dcraw_process(iprc);
|
||||
HANDLE_ERRORS(ret);
|
||||
|
||||
snprintf(outfn, 1023, "%s.%s", fn, tiff_mode ? "tiff" : "ppm");
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "Writing file %s\n", outfn);
|
||||
ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn);
|
||||
HANDLE_ERRORS(ret);
|
||||
count++;
|
||||
}
|
||||
libraw_close(iprc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void usage(const char *p)
|
||||
{
|
||||
printf("%s: Multi-threaded LibRaw sample app. Emulates dcraw -h [-w] [-a]\n",
|
||||
p);
|
||||
printf("Options:\n"
|
||||
"-J n - set parallel job count (default 2)\n"
|
||||
"-v - verbose\n"
|
||||
"-w - use camera white balance\n"
|
||||
"-a - average image for white balance\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int show_files(void *q)
|
||||
{
|
||||
char *p;
|
||||
int cnt = 0;
|
||||
while ((p = get_next_file()))
|
||||
{
|
||||
printf("%s\n", p);
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
int i, max_threads = 2;
|
||||
pthread_t *threads;
|
||||
if (ac < 2)
|
||||
usage(av[0]);
|
||||
|
||||
queue = calloc(ac - 1, sizeof(queue[0]));
|
||||
|
||||
for (i = 1; i < ac; i++)
|
||||
{
|
||||
if (av[i][0] == '-')
|
||||
{
|
||||
if (av[i][1] == 'w')
|
||||
use_camera_wb = 1;
|
||||
if (av[i][1] == 'a')
|
||||
use_auto_wb = 1;
|
||||
if (av[i][1] == 'v')
|
||||
verbose = 1;
|
||||
if (av[i][1] == 'T')
|
||||
tiff_mode = 1;
|
||||
if (av[i][1] == 'J')
|
||||
{
|
||||
max_threads = atoi(av[++i]);
|
||||
if (max_threads < 1)
|
||||
{
|
||||
fprintf(stderr, "Job count should be at least 1\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
queue[qsize++] = av[i];
|
||||
}
|
||||
pthread_mutex_init(&qm, NULL);
|
||||
threads = calloc(max_threads, sizeof(threads[0]));
|
||||
for (i = 0; i < max_threads; i++)
|
||||
pthread_create(&threads[i], NULL, process_files, NULL);
|
||||
for (i = 0; i < max_threads; i++)
|
||||
{
|
||||
int *iptr;
|
||||
if (threads[i])
|
||||
{
|
||||
pthread_join(threads[i], (void *)&iptr);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
212
samples/half_mt_win32.c
Normal file
212
samples/half_mt_win32.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/* -*- C++ -*-
|
||||
* File: halt_mt_win32.c
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Sat Mar 8, 2008
|
||||
*
|
||||
* LibRaw C API mutithreaded sample: emulates call to "dcraw -h [-w] [-a]
|
||||
[-v]"
|
||||
* Win32 version
|
||||
|
||||
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 <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <windows.h>
|
||||
#include "libraw/libraw.h"
|
||||
|
||||
#ifdef LIBRAW_WIN32_CALLS
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#define HANDLE_ERRORS(ret) \
|
||||
do \
|
||||
{ \
|
||||
if (ret) \
|
||||
{ \
|
||||
fprintf(stderr, "%s: %s\n", fn, libraw_strerror(ret)); \
|
||||
if (LIBRAW_FATAL_ERROR(ret)) \
|
||||
{ \
|
||||
libraw_close(iprc); \
|
||||
return -1; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// global settings
|
||||
int verbose = 0, use_camera_wb = 0, use_auto_wb = 0, tiff_mode = 0;
|
||||
|
||||
// global file queue
|
||||
HANDLE qmutex;
|
||||
char **queue = NULL;
|
||||
size_t qsize = 0, qptr = 0;
|
||||
|
||||
char *get_next_file()
|
||||
{
|
||||
char *ret;
|
||||
DWORD dwWaitResult;
|
||||
if (!queue)
|
||||
return NULL;
|
||||
if (qptr >= qsize)
|
||||
return NULL;
|
||||
|
||||
dwWaitResult = WaitForSingleObject(qmutex, // handle to mutex
|
||||
INFINITE); // no time-out interval
|
||||
switch (dwWaitResult)
|
||||
{
|
||||
// The thread got ownership of the mutex
|
||||
case WAIT_OBJECT_0:
|
||||
ret = queue[qptr++];
|
||||
ReleaseMutex(qmutex);
|
||||
break;
|
||||
case WAIT_ABANDONED:
|
||||
return NULL; // cannot obtain the lock
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
// thread routine
|
||||
int process_files(void *q)
|
||||
{
|
||||
int ret;
|
||||
int count = 0;
|
||||
char outfn[1024], *fn;
|
||||
libraw_data_t *iprc = libraw_init(0);
|
||||
|
||||
if (!iprc)
|
||||
{
|
||||
fprintf(stderr, "Cannot create libraw handle\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((fn = get_next_file()))
|
||||
{
|
||||
|
||||
iprc->params.half_size = 1; /* dcraw -h */
|
||||
iprc->params.use_camera_wb = use_camera_wb;
|
||||
iprc->params.use_auto_wb = use_auto_wb;
|
||||
iprc->params.output_tiff = tiff_mode;
|
||||
|
||||
ret = libraw_open_file(iprc, fn);
|
||||
if (verbose)
|
||||
fprintf(stderr, "%s: %s/%s\n", fn, iprc->idata.make, iprc->idata.model);
|
||||
HANDLE_ERRORS(ret);
|
||||
|
||||
ret = libraw_unpack(iprc);
|
||||
HANDLE_ERRORS(ret);
|
||||
|
||||
ret = libraw_dcraw_process(iprc);
|
||||
HANDLE_ERRORS(ret);
|
||||
|
||||
snprintf(outfn, 1023, "%s.%s", fn, tiff_mode ? "tif" : "ppm");
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, "Writing file %s\n", outfn);
|
||||
ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn);
|
||||
HANDLE_ERRORS(ret);
|
||||
count++;
|
||||
}
|
||||
libraw_close(iprc);
|
||||
printf("Processed %d files\n", count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usage(const char *p)
|
||||
{
|
||||
printf("Options:\n"
|
||||
"-J n - set parallel job count (default 2)\n"
|
||||
"-v - verbose\n"
|
||||
"-w - use camera white balance\n"
|
||||
"-T - output TIFF instead of PPM\n"
|
||||
"-a - average image for white balance\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int show_files(void *q)
|
||||
{
|
||||
char *p;
|
||||
int cnt = 0;
|
||||
while (p = get_next_file())
|
||||
{
|
||||
printf("%s\n", p);
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
int i, max_threads = 2;
|
||||
HANDLE *threads;
|
||||
DWORD ThreadID;
|
||||
|
||||
if (ac < 2)
|
||||
usage(av[0]);
|
||||
|
||||
queue = calloc(ac - 1, sizeof(queue[0]));
|
||||
|
||||
for (i = 1; i < ac; i++)
|
||||
{
|
||||
if (av[i][0] == '-')
|
||||
{
|
||||
if (av[i][1] == 'w')
|
||||
use_camera_wb = 1;
|
||||
if (av[i][1] == 'a')
|
||||
use_auto_wb = 1;
|
||||
if (av[i][1] == 'v')
|
||||
verbose = 1;
|
||||
if (av[i][1] == 'T')
|
||||
tiff_mode = 1;
|
||||
if (av[i][1] == 'J')
|
||||
{
|
||||
max_threads = atoi(av[++i]);
|
||||
if (max_threads < 1)
|
||||
{
|
||||
fprintf(stderr, "Job count should be at least 1\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
queue[qsize++] = av[i];
|
||||
}
|
||||
qmutex = CreateMutex(NULL, FALSE, NULL);
|
||||
threads = calloc(max_threads, sizeof(threads[0]));
|
||||
for (i = 0; i < max_threads; i++)
|
||||
{
|
||||
|
||||
if (NULL ==
|
||||
(threads[i] = CreateThread(NULL, // default security attributes
|
||||
0, // default stack size
|
||||
(LPTHREAD_START_ROUTINE)process_files,
|
||||
NULL, // no thread function arguments
|
||||
0, // default creation flags
|
||||
&ThreadID) // receive thread identifier
|
||||
))
|
||||
{
|
||||
printf("CreateThread error: %d\n", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
WaitForMultipleObjects(max_threads, threads, TRUE, INFINITE);
|
||||
|
||||
// Close thread and mutex handles
|
||||
|
||||
for (i = 0; i < max_threads; i++)
|
||||
CloseHandle(threads[i]);
|
||||
|
||||
CloseHandle(qmutex);
|
||||
|
||||
return 0;
|
||||
}
|
282
samples/mem_image_sample.cpp
Normal file
282
samples/mem_image_sample.cpp
Normal file
@@ -0,0 +1,282 @@
|
||||
/* -*- C++ -*-
|
||||
* File: mem_image.cpp
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
*
|
||||
* LibRaw mem_image/mem_thumb API test. Results should be same (bitwise) to
|
||||
dcraw [-4] [-6] [-e]
|
||||
* Testing note: for ppm-thumbnails you should use dcraw -w -e for thumbnail
|
||||
extraction
|
||||
|
||||
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 "libraw/libraw.h"
|
||||
|
||||
#ifdef USE_JPEG
|
||||
#include "jpeglib.h"
|
||||
#endif
|
||||
|
||||
#ifdef LIBRAW_WIN32_CALLS
|
||||
#define snprintf _snprintf
|
||||
#include <winsock2.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_JPEG
|
||||
void write_jpeg(libraw_processed_image_t *img, const char *basename, int quality)
|
||||
{
|
||||
char fn[1024];
|
||||
if(img->colors != 1 && img->colors != 3)
|
||||
{
|
||||
printf("Only BW and 3-color images supported for JPEG output\n");
|
||||
return;
|
||||
}
|
||||
snprintf(fn, 1024, "%s.jpg", basename);
|
||||
FILE *f = fopen(fn, "wb");
|
||||
if (!f)
|
||||
return;
|
||||
struct jpeg_compress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
|
||||
int row_stride; /* physical row width in image buffer */
|
||||
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
jpeg_create_compress(&cinfo);
|
||||
jpeg_stdio_dest(&cinfo, f);
|
||||
cinfo.image_width = img->width; /* image width and height, in pixels */
|
||||
cinfo.image_height = img->height;
|
||||
cinfo.input_components = img->colors; /* # of color components per pixel */
|
||||
cinfo.in_color_space = img->colors==3?JCS_RGB:JCS_GRAYSCALE; /* colorspace of input image */
|
||||
jpeg_set_defaults(&cinfo);
|
||||
jpeg_set_quality(&cinfo, quality, TRUE);
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
row_stride = img->width * img->colors; /* JSAMPLEs per row in image_buffer */
|
||||
while (cinfo.next_scanline < cinfo.image_height) {
|
||||
row_pointer[0] = &img->data[cinfo.next_scanline * row_stride];
|
||||
(void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
||||
}
|
||||
jpeg_finish_compress(&cinfo);
|
||||
fclose(f);
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// no error reporting, only params check
|
||||
void write_ppm(libraw_processed_image_t *img, const char *basename)
|
||||
{
|
||||
if (!img)
|
||||
return;
|
||||
// type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check
|
||||
if (img->type != LIBRAW_IMAGE_BITMAP)
|
||||
return;
|
||||
if (img->colors != 3 && img->colors != 1)
|
||||
{
|
||||
printf("Only monochrome and 3-color images supported for PPM output\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char fn[1024];
|
||||
snprintf(fn, 1024, "%s.p%cm", basename, img->colors==1?'g':'p');
|
||||
FILE *f = fopen(fn, "wb");
|
||||
if (!f)
|
||||
return;
|
||||
fprintf(f, "P%d\n%d %d\n%d\n", img->colors/2 + 5, img->width, img->height, (1 << img->bits) - 1);
|
||||
/*
|
||||
NOTE:
|
||||
data in img->data is not converted to network byte order.
|
||||
So, we should swap values on some architectures for dcraw compatibility
|
||||
(unfortunately, xv cannot display 16-bit PPMs with network byte order data
|
||||
*/
|
||||
#define SWAP(a, b) \
|
||||
{ \
|
||||
a ^= b; \
|
||||
a ^= (b ^= a); \
|
||||
}
|
||||
if (img->bits == 16 && htons(0x55aa) != 0x55aa)
|
||||
for (unsigned i = 0; i < img->data_size-1; i += 2)
|
||||
SWAP(img->data[i], img->data[i + 1]);
|
||||
#undef SWAP
|
||||
|
||||
fwrite(img->data, img->data_size, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void write_thumb(libraw_processed_image_t *img, const char *basename)
|
||||
{
|
||||
if (!img)
|
||||
return;
|
||||
|
||||
if (img->type == LIBRAW_IMAGE_BITMAP)
|
||||
{
|
||||
char fnt[1024];
|
||||
snprintf(fnt, 1024, "%s.thumb", basename);
|
||||
write_ppm(img, fnt);
|
||||
}
|
||||
else if (img->type == LIBRAW_IMAGE_JPEG)
|
||||
{
|
||||
char fn[1024];
|
||||
snprintf(fn, 1024, "%s.thumb.jpg", basename);
|
||||
FILE *f = fopen(fn, "wb");
|
||||
if (!f)
|
||||
return;
|
||||
fwrite(img->data, img->data_size, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
int i, ret, output_thumbs = 0;
|
||||
#ifdef USE_JPEG
|
||||
int output_jpeg = 0, jpgqual = 90;
|
||||
#endif
|
||||
// don't use fixed size buffers in real apps!
|
||||
|
||||
LibRaw RawProcessor;
|
||||
|
||||
if (ac < 2)
|
||||
{
|
||||
printf("mem_image - LibRaw sample, to illustrate work for memory buffers.\n"
|
||||
"Emulates dcraw [-4] [-1] [-e] [-h]\n"
|
||||
#ifdef USE_JPEG
|
||||
"Usage: %s [-D] [-j[nn]] [-T] [-v] [-e] raw-files....\n"
|
||||
#else
|
||||
"Usage: %s [-D] [-T] [-v] [-e] raw-files....\n"
|
||||
#endif
|
||||
"\t-6 - output 16-bit PPM\n"
|
||||
"\t-4 - linear 16-bit data\n"
|
||||
"\t-e - extract thumbnails (same as dcraw -e in separate run)\n"
|
||||
#ifdef USE_JPEG
|
||||
"\t-j[qual] - output JPEG with qual quality (e.g. -j90)\n"
|
||||
#endif
|
||||
"\t-h - use half_size\n", av[0]);
|
||||
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] == '6' && av[i][2] == 0)
|
||||
OUT.output_bps = 16;
|
||||
if (av[i][1] == '4' && av[i][2] == 0)
|
||||
{
|
||||
OUT.output_bps = 16;
|
||||
OUT.gamm[0] = OUT.gamm[1] = OUT.no_auto_bright = 1;
|
||||
}
|
||||
if (av[i][1] == 'e' && av[i][2] == 0)
|
||||
output_thumbs++;
|
||||
if (av[i][1] == 'h' && av[i][2] == 0)
|
||||
OUT.half_size = 1;
|
||||
#ifdef USE_JPEG
|
||||
if (av[i][1] == 'j')
|
||||
{
|
||||
output_jpeg = 1;
|
||||
if(av[i][2] != 0)
|
||||
jpgqual = atoi(av[i]+2);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
#ifdef USE_JPEG
|
||||
if(output_jpeg && OUT.output_bps>8)
|
||||
{
|
||||
printf("JPEG is limited to 8 bit\n");
|
||||
OUT.output_bps = 8;
|
||||
}
|
||||
#endif
|
||||
printf("Processing %s\n", av[i]);
|
||||
if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret));
|
||||
continue; // no recycle b/c open file will recycle itself
|
||||
}
|
||||
|
||||
if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
|
||||
continue;
|
||||
}
|
||||
|
||||
// we should call dcraw_process before thumbnail extraction because for
|
||||
// some cameras (i.e. Kodak ones) white balance for thumbnail should be set
|
||||
// from main image settings
|
||||
|
||||
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;
|
||||
}
|
||||
libraw_processed_image_t *image = RawProcessor.dcraw_make_mem_image(&ret);
|
||||
if (image)
|
||||
{
|
||||
#ifdef USE_JPEG
|
||||
if(output_jpeg)
|
||||
write_jpeg(image, av[i], jpgqual);
|
||||
else
|
||||
#endif
|
||||
write_ppm(image, av[i]);
|
||||
LibRaw::dcraw_clear_mem(image);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Cannot unpack %s to memory buffer: %s\n", av[i],
|
||||
libraw_strerror(ret));
|
||||
|
||||
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
|
||||
{
|
||||
libraw_processed_image_t *thumb =
|
||||
RawProcessor.dcraw_make_mem_thumb(&ret);
|
||||
if (thumb)
|
||||
{
|
||||
write_thumb(thumb, av[i]);
|
||||
LibRaw::dcraw_clear_mem(thumb);
|
||||
}
|
||||
else
|
||||
fprintf(stderr,
|
||||
"Cannot unpack thumbnail of %s to memory buffer: %s\n", av[i],
|
||||
libraw_strerror(ret));
|
||||
}
|
||||
}
|
||||
|
||||
RawProcessor.recycle(); // just for show this call
|
||||
}
|
||||
return 0;
|
||||
}
|
107
samples/multirender_test.cpp
Normal file
107
samples/multirender_test.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/* -*- C++ -*-
|
||||
* File: multirender_test.cpp
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Jul 10, 2011
|
||||
*
|
||||
* LibRaw simple C++ API: creates 8 different renderings from 1 source file.
|
||||
The 1st and 4th one should be identical
|
||||
|
||||
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 "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 process_once(LibRaw &RawProcessor, int half_mode, int camera_wb,
|
||||
int auto_wb, int suffix, int user_flip, char *fname)
|
||||
{
|
||||
char outfn[1024];
|
||||
RawProcessor.imgdata.params.half_size = half_mode;
|
||||
RawProcessor.imgdata.params.use_camera_wb = camera_wb;
|
||||
RawProcessor.imgdata.params.use_auto_wb = auto_wb;
|
||||
RawProcessor.imgdata.params.user_flip = user_flip;
|
||||
|
||||
int ret = RawProcessor.dcraw_process();
|
||||
|
||||
if (LIBRAW_SUCCESS != ret)
|
||||
{
|
||||
fprintf(stderr, "Cannot do postprocessing on %s: %s\n", fname,
|
||||
libraw_strerror(ret));
|
||||
return ret;
|
||||
}
|
||||
snprintf(outfn, sizeof(outfn), "%s.%d.%s", fname, suffix,
|
||||
(RawProcessor.imgdata.idata.colors > 1 ? "ppm" : "pgm"));
|
||||
|
||||
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));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
LibRaw RawProcessor;
|
||||
if (ac < 2)
|
||||
{
|
||||
printf("multirender_test - LibRaw %s sample. Performs 4 different "
|
||||
"renderings of one file\n"
|
||||
" %d cameras supported\n"
|
||||
"Usage: %s raw-files....\n",
|
||||
LibRaw::version(), LibRaw::cameraCount(), av[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i < ac; i++)
|
||||
{
|
||||
|
||||
printf("Processing file %s\n", av[i]);
|
||||
|
||||
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 ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
|
||||
continue;
|
||||
}
|
||||
process_once(RawProcessor, 0, 0, 0, 1, -1, av[i]); // default flip
|
||||
process_once(RawProcessor, 1, 0, 1, 2, -1, av[i]);
|
||||
process_once(RawProcessor, 1, 1, 0, 3, -1, av[i]); // default flip
|
||||
process_once(RawProcessor, 1, 1, 0, 4, 1, av[i]); // flip 1
|
||||
process_once(RawProcessor, 1, 1, 0, 5, 3, av[i]); // flip 3
|
||||
process_once(RawProcessor, 1, 1, 0, 6, 1, av[i]); // 1 again same as 4
|
||||
process_once(RawProcessor, 1, 1, 0, 7, -1,
|
||||
av[i]); // default again, same as 3
|
||||
process_once(RawProcessor, 0, 0, 0, 8, -1, av[i]); // same as 1
|
||||
|
||||
RawProcessor.recycle(); // just for show this call
|
||||
}
|
||||
return 0;
|
||||
}
|
65
samples/openbayer_sample.cpp
Normal file
65
samples/openbayer_sample.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/* -*- C++ -*-
|
||||
* File: openvayer_sample.cpp
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Feb 11, 2020
|
||||
*
|
||||
* LibRaw simple C++ API: opens bayer data (Kodak KAI-0340 sensor) from buffer,
|
||||
dump as 8-bit tiff
|
||||
|
||||
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 "libraw/libraw.h"
|
||||
|
||||
#ifndef LIBRAW_WIN32_CALLS
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
if (ac != 2)
|
||||
return 1;
|
||||
FILE *in = fopen(av[1], "rb");
|
||||
fseek(in, 0, SEEK_END);
|
||||
unsigned fsz = ftell(in);
|
||||
unsigned char *buffer = (unsigned char *)malloc(fsz);
|
||||
if (!buffer)
|
||||
return 2;
|
||||
fseek(in, 0, SEEK_SET);
|
||||
unsigned readb = fread(buffer, 1, fsz, in);
|
||||
if (readb != fsz)
|
||||
return 3;
|
||||
LibRaw rp;
|
||||
rp.imgdata.params.output_tiff = 1;
|
||||
int ret = rp.open_bayer(buffer, fsz, 640, 480, 0, 0, 0, 0, 0,
|
||||
LIBRAW_OPENBAYER_RGGB, 0, 0, 1400);
|
||||
if (ret != LIBRAW_SUCCESS)
|
||||
return 4;
|
||||
if ((ret = rp.unpack()) != LIBRAW_SUCCESS)
|
||||
printf("Unpack error: %d\n", ret);
|
||||
|
||||
if ((ret = rp.dcraw_process()) != LIBRAW_SUCCESS)
|
||||
printf("Processing error: %d\n", ret);
|
||||
|
||||
char outfn[256];
|
||||
sprintf(outfn, "%s.tif", av[1]);
|
||||
if (LIBRAW_SUCCESS != (ret = rp.dcraw_ppm_tiff_writer(outfn)))
|
||||
printf("Cannot write %s: %s\n", outfn, libraw_strerror(ret));
|
||||
else
|
||||
printf("Created %s\n", outfn);
|
||||
}
|
223
samples/postprocessing_benchmark.cpp
Normal file
223
samples/postprocessing_benchmark.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
/* -*- C++ -*-
|
||||
* File: postprocessing_benchmark.cpp
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Jul 13, 2011
|
||||
*
|
||||
* LibRaw simple C++ API: creates 8 different renderings from 1 source file.
|
||||
The 1st and 4th one should be identical
|
||||
|
||||
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 "libraw/libraw.h"
|
||||
|
||||
#ifndef LIBRAW_WIN32_CALLS
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "libraw/libraw.h"
|
||||
|
||||
void timerstart(void);
|
||||
float timerend(void);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, ret, rep = 1;
|
||||
LibRaw RawProcessor;
|
||||
#ifdef OUT
|
||||
#undef OUT
|
||||
#endif
|
||||
#define OUT RawProcessor.imgdata.params
|
||||
#define OUTR RawProcessor.imgdata.rawparams
|
||||
#define S RawProcessor.imgdata.sizes
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
printf(
|
||||
"postprocessing benchmark: LibRaw %s sample, %d cameras supported\n"
|
||||
"Measures postprocessing speed with different options\n"
|
||||
"Usage: %s [-a] [-H N] [-q N] [-h] [-m N] [-n N] [-s N] [-B x y w h] "
|
||||
"[-R N]\n"
|
||||
"-a average image for white balance\n"
|
||||
"-H <num> Highlight mode (0=clip, 1=unclip, 2=blend, "
|
||||
"3+=rebuild)\n"
|
||||
"-q <num> Set the interpolation quality\n"
|
||||
"-h Half-size color image\n"
|
||||
"-m <num> Apply a num-passes 3x3 median filter to R-G and B-G\n"
|
||||
"-n <num> Set threshold for wavelet denoising\n"
|
||||
"-s <num> Select one raw image from input file\n"
|
||||
"-B <x y w h> Crop output image\n"
|
||||
"-R <num> Number of repetitions\n"
|
||||
"-c Do not use rawspeed\n",
|
||||
LibRaw::version(), LibRaw::cameraCount(), argv[0]);
|
||||
return 0;
|
||||
}
|
||||
char opm, opt, *cp, *sp;
|
||||
int arg, c;
|
||||
int shrink = 0;
|
||||
|
||||
argv[argc] = (char *)"";
|
||||
for (arg = 1; (((opm = argv[arg][0]) - 2) | 2) == '+';)
|
||||
{
|
||||
char *optstr = argv[arg];
|
||||
opt = argv[arg++][1];
|
||||
if ((cp = strchr(sp = (char *)"HqmnsBR", opt)) != 0)
|
||||
for (i = 0; i < "1111141"[cp - sp] - '0'; i++)
|
||||
if (!isdigit(argv[arg + i][0]) && !optstr[2])
|
||||
{
|
||||
fprintf(stderr, "Non-numeric argument to \"-%c\"\n", opt);
|
||||
return 1;
|
||||
}
|
||||
switch (opt)
|
||||
{
|
||||
case 'a':
|
||||
OUT.use_auto_wb = 1;
|
||||
break;
|
||||
case 'H':
|
||||
OUT.highlight = atoi(argv[arg++]);
|
||||
break;
|
||||
case 'q':
|
||||
OUT.user_qual = atoi(argv[arg++]);
|
||||
break;
|
||||
case 'h':
|
||||
OUT.half_size = 1;
|
||||
OUT.four_color_rgb = 1;
|
||||
shrink = 1;
|
||||
break;
|
||||
case 'm':
|
||||
OUT.med_passes = atoi(argv[arg++]);
|
||||
break;
|
||||
case 'n':
|
||||
OUT.threshold = (float)atof(argv[arg++]);
|
||||
break;
|
||||
case 's':
|
||||
OUTR.shot_select = abs(atoi(argv[arg++]));
|
||||
break;
|
||||
case 'B':
|
||||
for (c = 0; c < 4; c++)
|
||||
OUT.cropbox[c] = atoi(argv[arg++]);
|
||||
break;
|
||||
case 'R':
|
||||
rep = abs(atoi(argv[arg++]));
|
||||
if (rep < 1)
|
||||
rep = 1;
|
||||
break;
|
||||
case 'c':
|
||||
RawProcessor.imgdata.rawparams.use_rawspeed = 0;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown option \"-%c\".\n", opt);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (; arg < argc; arg++)
|
||||
{
|
||||
printf("Processing file %s\n", argv[arg]);
|
||||
timerstart();
|
||||
if ((ret = RawProcessor.open_file(argv[arg])) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot open_file %s: %s\n", argv[arg],
|
||||
libraw_strerror(ret));
|
||||
continue; // no recycle b/c open file will recycle itself
|
||||
}
|
||||
|
||||
if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot unpack %s: %s\n", argv[arg],
|
||||
libraw_strerror(ret));
|
||||
continue;
|
||||
}
|
||||
float qsec = timerend();
|
||||
printf("\n%.1f msec for unpack\n", qsec);
|
||||
float mpix, rmpix;
|
||||
timerstart();
|
||||
for (c = 0; c < rep; c++)
|
||||
{
|
||||
if ((ret = RawProcessor.dcraw_process()) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot postprocess %s: %s\n", argv[arg],
|
||||
libraw_strerror(ret));
|
||||
break;
|
||||
}
|
||||
libraw_processed_image_t *p = RawProcessor.dcraw_make_mem_image();
|
||||
if (p)
|
||||
RawProcessor.dcraw_clear_mem(p);
|
||||
RawProcessor.free_image();
|
||||
}
|
||||
float msec = timerend() / (float)rep;
|
||||
|
||||
if ((ret = RawProcessor.adjust_sizes_info_only()) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot adjust sizes for %s: %s\n", argv[arg],
|
||||
libraw_strerror(ret));
|
||||
break;
|
||||
}
|
||||
rmpix = (S.iwidth * S.iheight) / 1000000.0f;
|
||||
|
||||
if (c == rep) // no failure
|
||||
{
|
||||
unsigned int crop[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
crop[i] = (OUT.cropbox[i]) >> shrink;
|
||||
if (crop[0] + crop[2] > S.iwidth)
|
||||
crop[2] = S.iwidth - crop[0];
|
||||
if (crop[1] + crop[3] > S.iheight)
|
||||
crop[3] = S.iheight - crop[1];
|
||||
|
||||
mpix = float(crop[2] * crop[3]) / 1000000.0f;
|
||||
float mpixsec = mpix * 1000.0f / msec;
|
||||
|
||||
printf("Performance: %.2f Mpix/sec\n"
|
||||
"File: %s, Frame: %d %.1f total Mpix, %.1f msec\n"
|
||||
"Params: WB=%s Highlight=%d Qual=%d HalfSize=%s Median=%d "
|
||||
"Wavelet=%.0f\n"
|
||||
"Crop: %u-%u:%ux%u, active Mpix: %.2f, %.1f frames/sec\n",
|
||||
mpixsec, argv[arg], OUTR.shot_select, rmpix, msec,
|
||||
OUT.use_auto_wb ? "auto" : "default", OUT.highlight, OUT.user_qual,
|
||||
OUT.half_size ? "YES" : "No", OUT.med_passes, OUT.threshold,
|
||||
crop[0], crop[1], crop[2], crop[3], mpix, 1000.0f / msec);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef LIBRAW_WIN32_CALLS
|
||||
static struct timeval start, end;
|
||||
void timerstart(void) { gettimeofday(&start, NULL); }
|
||||
float timerend(void)
|
||||
{
|
||||
gettimeofday(&end, NULL);
|
||||
float msec = (end.tv_sec - start.tv_sec) * 1000.0f +
|
||||
(end.tv_usec - start.tv_usec) / 1000.0f;
|
||||
return msec;
|
||||
}
|
||||
#else
|
||||
LARGE_INTEGER start;
|
||||
void timerstart(void) { QueryPerformanceCounter(&start); }
|
||||
float timerend()
|
||||
{
|
||||
LARGE_INTEGER unit, end;
|
||||
QueryPerformanceCounter(&end);
|
||||
QueryPerformanceFrequency(&unit);
|
||||
float msec = (float)(end.QuadPart - start.QuadPart);
|
||||
msec /= (float)unit.QuadPart / 1000.0f;
|
||||
return msec;
|
||||
}
|
||||
|
||||
#endif
|
739
samples/raw-identify.cpp
Normal file
739
samples/raw-identify.cpp
Normal file
@@ -0,0 +1,739 @@
|
||||
/* -*- C++ -*-
|
||||
* File: identify.cpp
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Sat Mar 8, 2008
|
||||
*
|
||||
* LibRaw C++ demo: emulates dcraw -i [-v]
|
||||
*
|
||||
|
||||
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 <time.h>
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include "libraw/libraw.h"
|
||||
|
||||
#ifdef LIBRAW_WIN32_CALLS
|
||||
#define snprintf _snprintf
|
||||
#define strcasecmp stricmp
|
||||
#define strncasecmp strnicmp
|
||||
#endif
|
||||
|
||||
#ifndef LIBRAW_WIN32_CALLS
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH PATH_MAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER < 1800 /* below MSVC 2013 */
|
||||
float roundf(float f) { return floorf(f + 0.5); }
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define P1 MyCoolRawProcessor.imgdata.idata
|
||||
#define P2 MyCoolRawProcessor.imgdata.other
|
||||
#define P3 MyCoolRawProcessor.imgdata.makernotes.common
|
||||
|
||||
#define mnLens MyCoolRawProcessor.imgdata.lens.makernotes
|
||||
#define exifLens MyCoolRawProcessor.imgdata.lens
|
||||
#define ShootingInfo MyCoolRawProcessor.imgdata.shootinginfo
|
||||
|
||||
#define S MyCoolRawProcessor.imgdata.sizes
|
||||
#define O MyCoolRawProcessor.imgdata.params
|
||||
#define C MyCoolRawProcessor.imgdata.color
|
||||
#define T MyCoolRawProcessor.imgdata.thumbnail
|
||||
|
||||
void print_verbose(FILE *, LibRaw &MyCoolRawProcessor, std::string &fn);
|
||||
void print_wbfun(FILE *, LibRaw &MyCoolRawProcessor, std::string &fn);
|
||||
void print_szfun(FILE *, LibRaw &MyCoolRawProcessor, std::string &fn);
|
||||
void print_unpackfun(FILE *, LibRaw &MyCoolRawProcessor, int print_frame, std::string &fn);
|
||||
|
||||
/*
|
||||
table of fluorescents:
|
||||
12 = FL-D; Daylight fluorescent (D 5700K – 7100K) (F1,F5)
|
||||
13 = FL-N; Day white fluorescent (N 4600K – 5400K) (F7,F8)
|
||||
14 = FL-W; Cool white fluorescent (W 3900K – 4500K) (F2,F6, office,
|
||||
store,warehouse) 15 = FL-WW; White fluorescent (WW 3200K – 3700K) (F3,
|
||||
residential) 16 = FL-L; Soft/Warm white fluorescent (L 2600K - 3250K) (F4,
|
||||
kitchen, bath)
|
||||
*/
|
||||
|
||||
static const struct
|
||||
{
|
||||
const int NumId;
|
||||
const char *StrId;
|
||||
const char *hrStrId; // human-readable
|
||||
const int aux_setting;
|
||||
} WBToStr[] = {
|
||||
{LIBRAW_WBI_Unknown, "WBI_Unknown", "Unknown", 0},
|
||||
{LIBRAW_WBI_Daylight, "WBI_Daylight", "Daylight", 0},
|
||||
{LIBRAW_WBI_Fluorescent, "WBI_Fluorescent", "Fluorescent", 0},
|
||||
{LIBRAW_WBI_Tungsten, "WBI_Tungsten", "Tungsten (Incandescent)", 0},
|
||||
{LIBRAW_WBI_Flash, "WBI_Flash", "Flash", 0},
|
||||
{LIBRAW_WBI_FineWeather, "WBI_FineWeather", "Fine Weather", 0},
|
||||
{LIBRAW_WBI_Cloudy, "WBI_Cloudy", "Cloudy", 0},
|
||||
{LIBRAW_WBI_Shade, "WBI_Shade", "Shade", 0},
|
||||
{LIBRAW_WBI_FL_D, "WBI_FL_D", "Daylight Fluorescent", 0},
|
||||
{LIBRAW_WBI_FL_N, "WBI_FL_N", "Day White Fluorescent", 0},
|
||||
{LIBRAW_WBI_FL_W, "WBI_FL_W", "Cool White Fluorescent", 0},
|
||||
{LIBRAW_WBI_FL_WW, "WBI_FL_WW", "White Fluorescent", 0},
|
||||
{LIBRAW_WBI_FL_L, "WBI_FL_L", "Warm White Fluorescent", 0},
|
||||
{LIBRAW_WBI_Ill_A, "WBI_Ill_A", "Illuminant A", 0},
|
||||
{LIBRAW_WBI_Ill_B, "WBI_Ill_B", "Illuminant B", 0},
|
||||
{LIBRAW_WBI_Ill_C, "WBI_Ill_C", "Illuminant C", 0},
|
||||
{LIBRAW_WBI_D55, "WBI_D55", "D55", 0},
|
||||
{LIBRAW_WBI_D65, "WBI_D65", "D65", 0},
|
||||
{LIBRAW_WBI_D75, "WBI_D75", "D75", 0},
|
||||
{LIBRAW_WBI_D50, "WBI_D50", "D50", 0},
|
||||
{LIBRAW_WBI_StudioTungsten, "WBI_StudioTungsten", "ISO Studio Tungsten", 0},
|
||||
{LIBRAW_WBI_BW, "WBI_BW", "BW", 0},
|
||||
{LIBRAW_WBI_Other, "WBI_Other", "Other", 0},
|
||||
{LIBRAW_WBI_Sunset, "WBI_Sunset", "Sunset", 1},
|
||||
{LIBRAW_WBI_Underwater, "WBI_Underwater", "Underwater", 1},
|
||||
{LIBRAW_WBI_FluorescentHigh, "WBI_FluorescentHigh", "Fluorescent High", 1},
|
||||
{LIBRAW_WBI_HT_Mercury, "WBI_HT_Mercury", "HT Mercury", 1},
|
||||
{LIBRAW_WBI_AsShot, "WBI_AsShot", "As Shot", 1},
|
||||
{LIBRAW_WBI_Measured, "WBI_Measured", "Camera Measured", 1},
|
||||
{LIBRAW_WBI_Auto, "WBI_Auto", "Camera Auto", 1},
|
||||
{LIBRAW_WBI_Auto1, "WBI_Auto1", "Camera Auto 1", 1},
|
||||
{LIBRAW_WBI_Auto2, "WBI_Auto2", "Camera Auto 2", 1},
|
||||
{LIBRAW_WBI_Auto3, "WBI_Auto3", "Camera Auto 3", 1},
|
||||
{LIBRAW_WBI_Auto4, "WBI_Auto4", "Camera Auto 4", 1},
|
||||
{LIBRAW_WBI_Custom, "WBI_Custom", "Custom", 1},
|
||||
{LIBRAW_WBI_Custom1, "WBI_Custom1", "Custom 1", 1},
|
||||
{LIBRAW_WBI_Custom2, "WBI_Custom2", "Custom 2", 1},
|
||||
{LIBRAW_WBI_Custom3, "WBI_Custom3", "Custom 3", 1},
|
||||
{LIBRAW_WBI_Custom4, "WBI_Custom4", "Custom 4", 1},
|
||||
{LIBRAW_WBI_Custom5, "WBI_Custom5", "Custom 5", 1},
|
||||
{LIBRAW_WBI_Custom6, "WBI_Custom6", "Custom 6", 1},
|
||||
{LIBRAW_WBI_PC_Set1, "WBI_PC_Set1", "PC Set 1", 1},
|
||||
{LIBRAW_WBI_PC_Set2, "WBI_PC_Set2", "PC Set 2", 1},
|
||||
{LIBRAW_WBI_PC_Set3, "WBI_PC_Set3", "PC Set 3", 1},
|
||||
{LIBRAW_WBI_PC_Set4, "WBI_PC_Set4", "PC Set 4", 1},
|
||||
{LIBRAW_WBI_PC_Set5, "WBI_PC_Set5", "PC Set 5", 1},
|
||||
{LIBRAW_WBI_Kelvin, "WBI_Kelvin", "Kelvin", 1},
|
||||
};
|
||||
|
||||
const char *WB_idx2str(unsigned WBi)
|
||||
{
|
||||
for (int i = 0; i < int(sizeof WBToStr / sizeof *WBToStr); i++)
|
||||
if (WBToStr[i].NumId == (int)WBi)
|
||||
return WBToStr[i].StrId;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *WB_idx2hrstr(unsigned WBi)
|
||||
{
|
||||
for (int i = 0; i < int(sizeof WBToStr / sizeof *WBToStr); i++)
|
||||
if (WBToStr[i].NumId == (int)WBi)
|
||||
return WBToStr[i].hrStrId;
|
||||
return 0;
|
||||
}
|
||||
|
||||
double _log2(double a)
|
||||
{
|
||||
if(a > 0.00000000001) return log(a)/log(2.0);
|
||||
return -1000;
|
||||
}
|
||||
|
||||
void trimSpaces(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
if (!strncasecmp(p, "NO=", 3))
|
||||
p = p + 3; /* fix for Nikon D70, D70s */
|
||||
int l = strlen(p);
|
||||
if (!l)
|
||||
return;
|
||||
while (isspace(p[l - 1]))
|
||||
p[--l] = 0; /* trim trailing spaces */
|
||||
while (*p && isspace(*p))
|
||||
++p, --l; /* trim leading spaces */
|
||||
memmove(s, p, l + 1);
|
||||
}
|
||||
|
||||
void print_usage(const char *pname)
|
||||
{
|
||||
printf("Usage: %s [options] inputfiles\n", pname);
|
||||
printf("Options:\n"
|
||||
"\t-v\tverbose output\n"
|
||||
"\t-w\tprint white balance\n"
|
||||
"\t-u\tprint unpack function\n"
|
||||
"\t-f\tprint frame size (only w/ -u)\n"
|
||||
"\t-s\tprint output image size\n"
|
||||
"\t-h\tforce half-size mode (only for -s)\n"
|
||||
"\t-M\tdisable use of raw-embedded color data\n"
|
||||
"\t+M\tforce use of raw-embedded color data\n"
|
||||
"\t-L filename\tread input files list from filename\n"
|
||||
"\t-o filename\toutput to filename\n");
|
||||
}
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
int ret;
|
||||
int verbose = 0, print_sz = 0, print_unpack = 0, print_frame = 0, print_wb = 0;
|
||||
LibRaw MyCoolRawProcessor;
|
||||
char *filelistfile = NULL;
|
||||
char *outputfilename = NULL;
|
||||
FILE *outfile = stdout;
|
||||
std::vector<std::string> filelist;
|
||||
|
||||
filelist.reserve(ac - 1);
|
||||
|
||||
for (int i = 1; i < ac; i++)
|
||||
{
|
||||
if (av[i][0] == '-')
|
||||
{
|
||||
if (!strcmp(av[i], "-v"))
|
||||
verbose++;
|
||||
if (!strcmp(av[i], "-w"))
|
||||
print_wb++;
|
||||
if (!strcmp(av[i], "-u"))
|
||||
print_unpack++;
|
||||
if (!strcmp(av[i], "-s"))
|
||||
print_sz++;
|
||||
if (!strcmp(av[i], "-h"))
|
||||
O.half_size = 1;
|
||||
if (!strcmp(av[i], "-f"))
|
||||
print_frame++;
|
||||
if (!strcmp(av[i], "-M"))
|
||||
MyCoolRawProcessor.imgdata.params.use_camera_matrix = 0;
|
||||
if (!strcmp(av[i], "-L") && i < ac - 1)
|
||||
{
|
||||
filelistfile = av[i + 1];
|
||||
i++;
|
||||
}
|
||||
if (!strcmp(av[i], "-o") && i < ac - 1)
|
||||
{
|
||||
outputfilename = av[i + 1];
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(av[i], "+M"))
|
||||
{
|
||||
MyCoolRawProcessor.imgdata.params.use_camera_matrix = 3;
|
||||
continue;
|
||||
}
|
||||
filelist.push_back(av[i]);
|
||||
}
|
||||
if (filelistfile)
|
||||
{
|
||||
char *p;
|
||||
char path[MAX_PATH + 1];
|
||||
FILE *f = fopen(filelistfile, "r");
|
||||
if (f)
|
||||
{
|
||||
while (fgets(path, MAX_PATH, f))
|
||||
{
|
||||
if ((p = strchr(path, '\n')))
|
||||
*p = 0;
|
||||
if ((p = strchr(path, '\r')))
|
||||
*p = 0;
|
||||
filelist.push_back(path);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
if (filelist.size() < 1)
|
||||
{
|
||||
print_usage(av[0]);
|
||||
return 1;
|
||||
}
|
||||
if (outputfilename)
|
||||
outfile = fopen(outputfilename, "wt");
|
||||
|
||||
for (int i = 0; i < (int)filelist.size(); i++)
|
||||
{
|
||||
if ((ret = MyCoolRawProcessor.open_file(filelist[i].c_str())) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot decode %s: %s\n", filelist[i].c_str(), libraw_strerror(ret));
|
||||
continue; // no recycle, open_file will recycle
|
||||
}
|
||||
|
||||
if (print_sz)
|
||||
print_szfun(outfile, MyCoolRawProcessor, filelist[i]);
|
||||
else if (verbose)
|
||||
print_verbose(outfile, MyCoolRawProcessor, filelist[i]);
|
||||
else if (print_unpack)
|
||||
print_unpackfun(outfile, MyCoolRawProcessor, print_frame, filelist[i]);
|
||||
else if (print_wb)
|
||||
print_wbfun(outfile, MyCoolRawProcessor, filelist[i]);
|
||||
else
|
||||
fprintf(outfile, "%s is a %s %s image.\n", filelist[i].c_str(), P1.make, P1.model);
|
||||
|
||||
MyCoolRawProcessor.recycle();
|
||||
} // endfor
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PRINTMATRIX3x4(of, mat, clrs) \
|
||||
do \
|
||||
{ \
|
||||
for (int r = 0; r < 3; r++) \
|
||||
if (clrs == 4) \
|
||||
fprintf(of, "%6.4f\t%6.4f\t%6.4f\t%6.4f\n", mat[r][0], mat[r][1], mat[r][2], mat[r][3]); \
|
||||
else \
|
||||
fprintf(of, "%6.4f\t%6.4f\t%6.4f\n", mat[r][0], mat[r][1], mat[r][2]); \
|
||||
} while (0)
|
||||
|
||||
#define PRINTMATRIX4x3(of, mat, clrs) \
|
||||
do \
|
||||
{ \
|
||||
for (int r = 0; r < clrs && r < 4; r++) \
|
||||
fprintf(of, "%6.4f\t%6.4f\t%6.4f\n", mat[r][0], mat[r][1], mat[r][2]); \
|
||||
} while (0)
|
||||
|
||||
void print_verbose(FILE *outfile, LibRaw &MyCoolRawProcessor, std::string &fn)
|
||||
{
|
||||
int WBi;
|
||||
float denom;
|
||||
int ret;
|
||||
|
||||
if ((ret = MyCoolRawProcessor.adjust_sizes_info_only()))
|
||||
{
|
||||
fprintf(outfile, "Cannot decode %s: %s\n", fn.c_str(), libraw_strerror(ret));
|
||||
return; // no recycle, open_file will recycle
|
||||
}
|
||||
|
||||
fprintf(outfile, "\nFilename: %s\n", fn.c_str());
|
||||
if (C.OriginalRawFileName[0])
|
||||
fprintf(outfile, "OriginalRawFileName: =%s=\n", C.OriginalRawFileName);
|
||||
fprintf(outfile, "Timestamp: %s", ctime(&(P2.timestamp)));
|
||||
fprintf(outfile, "Camera: %s %s ID: 0x%llx\n", P1.make, P1.model, mnLens.CamID);
|
||||
fprintf(outfile, "Normalized Make/Model: =%s/%s= ", P1.normalized_make, P1.normalized_model);
|
||||
fprintf(outfile, "CamMaker ID: %d\n", P1.maker_index);
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
char sep[] = ", ";
|
||||
if (C.UniqueCameraModel[0])
|
||||
{
|
||||
i++;
|
||||
fprintf(outfile, "UniqueCameraModel: =%s=", C.UniqueCameraModel);
|
||||
}
|
||||
if (C.LocalizedCameraModel[0])
|
||||
{
|
||||
if (i)
|
||||
{
|
||||
fprintf(outfile, "%s", sep);
|
||||
i++;
|
||||
}
|
||||
fprintf(outfile, "LocalizedCameraModel: =%s=", C.LocalizedCameraModel);
|
||||
}
|
||||
if (i)
|
||||
{
|
||||
fprintf(outfile, "\n");
|
||||
i = 0;
|
||||
}
|
||||
if (C.ImageUniqueID[0])
|
||||
{
|
||||
if (i)
|
||||
fprintf(outfile, "%s", sep);
|
||||
i++;
|
||||
fprintf(outfile, "ImageUniqueID: =%s=", C.ImageUniqueID);
|
||||
}
|
||||
if (C.RawDataUniqueID[0])
|
||||
{
|
||||
if (i)
|
||||
fprintf(outfile, "%s", sep);
|
||||
i++;
|
||||
fprintf(outfile, "RawDataUniqueID: =%s=", C.RawDataUniqueID);
|
||||
}
|
||||
if (i)
|
||||
fprintf(outfile, "\n");
|
||||
}
|
||||
|
||||
if (ShootingInfo.BodySerial[0] && strcmp(ShootingInfo.BodySerial, "0"))
|
||||
{
|
||||
trimSpaces(ShootingInfo.BodySerial);
|
||||
fprintf(outfile, "Body#: %s", ShootingInfo.BodySerial);
|
||||
}
|
||||
else if (C.model2[0] && (!strncasecmp(P1.normalized_make, "Kodak", 5)))
|
||||
{
|
||||
trimSpaces(C.model2);
|
||||
fprintf(outfile, "Body#: %s", C.model2);
|
||||
}
|
||||
if (ShootingInfo.InternalBodySerial[0])
|
||||
{
|
||||
trimSpaces(ShootingInfo.InternalBodySerial);
|
||||
fprintf(outfile, " BodyAssy#: %s", ShootingInfo.InternalBodySerial);
|
||||
}
|
||||
if (exifLens.LensSerial[0])
|
||||
{
|
||||
trimSpaces(exifLens.LensSerial);
|
||||
fprintf(outfile, " Lens#: %s", exifLens.LensSerial);
|
||||
}
|
||||
if (exifLens.InternalLensSerial[0])
|
||||
{
|
||||
trimSpaces(exifLens.InternalLensSerial);
|
||||
fprintf(outfile, " LensAssy#: %s", exifLens.InternalLensSerial);
|
||||
}
|
||||
if (P2.artist[0])
|
||||
fprintf(outfile, " Owner: %s\n", P2.artist);
|
||||
if (P1.dng_version)
|
||||
{
|
||||
fprintf(outfile, " DNG Version: ");
|
||||
for (int i = 24; i >= 0; i -= 8)
|
||||
fprintf(outfile, "%d%c", P1.dng_version >> i & 255, i ? '.' : '\n');
|
||||
}
|
||||
fprintf(outfile, "\nEXIF:\n");
|
||||
fprintf(outfile, "\tMinFocal: %0.1f mm\n", exifLens.MinFocal);
|
||||
fprintf(outfile, "\tMaxFocal: %0.1f mm\n", exifLens.MaxFocal);
|
||||
fprintf(outfile, "\tMaxAp @MinFocal: f/%0.1f\n", exifLens.MaxAp4MinFocal);
|
||||
fprintf(outfile, "\tMaxAp @MaxFocal: f/%0.1f\n", exifLens.MaxAp4MaxFocal);
|
||||
fprintf(outfile, "\tCurFocal: %0.1f mm\n", P2.focal_len);
|
||||
fprintf(outfile, "\tMaxAperture @CurFocal: f/%0.1f\n", exifLens.EXIF_MaxAp);
|
||||
fprintf(outfile, "\tFocalLengthIn35mmFormat: %d mm\n", exifLens.FocalLengthIn35mmFormat);
|
||||
fprintf(outfile, "\tLensMake: %s\n", exifLens.LensMake);
|
||||
fprintf(outfile, "\tLens: %s\n", exifLens.Lens);
|
||||
fprintf(outfile, "\n");
|
||||
|
||||
fprintf(outfile, "\nMakernotes:\n");
|
||||
fprintf(outfile, "\tDriveMode: %d\n", ShootingInfo.DriveMode);
|
||||
fprintf(outfile, "\tFocusMode: %d\n", ShootingInfo.FocusMode);
|
||||
fprintf(outfile, "\tMeteringMode: %d\n", ShootingInfo.MeteringMode);
|
||||
fprintf(outfile, "\tAFPoint: %d\n", ShootingInfo.AFPoint);
|
||||
fprintf(outfile, "\tExposureMode: %d\n", ShootingInfo.ExposureMode);
|
||||
fprintf(outfile, "\tExposureProgram: %d\n", ShootingInfo.ExposureProgram);
|
||||
fprintf(outfile, "\tImageStabilization: %d\n", ShootingInfo.ImageStabilization);
|
||||
|
||||
fprintf(outfile, "\tLens: %s\n", mnLens.Lens);
|
||||
fprintf(outfile, "\tLensFormat: %d, ", mnLens.LensFormat);
|
||||
|
||||
fprintf(outfile, "\tLensMount: %d, ", mnLens.LensMount);
|
||||
fprintf(outfile, "\tFocalType: %d, ", mnLens.FocalType);
|
||||
switch (mnLens.FocalType)
|
||||
{
|
||||
case LIBRAW_FT_UNDEFINED:
|
||||
fprintf(outfile, "Undefined\n");
|
||||
break;
|
||||
case LIBRAW_FT_PRIME_LENS:
|
||||
fprintf(outfile, "Prime lens\n");
|
||||
break;
|
||||
case LIBRAW_FT_ZOOM_LENS:
|
||||
fprintf(outfile, "Zoom lens\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(outfile, "Unknown\n");
|
||||
break;
|
||||
}
|
||||
fprintf(outfile, "\tLensFeatures_pre: %s\n", mnLens.LensFeatures_pre);
|
||||
fprintf(outfile, "\tLensFeatures_suf: %s\n", mnLens.LensFeatures_suf);
|
||||
fprintf(outfile, "\tMinFocal: %0.1f mm\n", mnLens.MinFocal);
|
||||
fprintf(outfile, "\tMaxFocal: %0.1f mm\n", mnLens.MaxFocal);
|
||||
fprintf(outfile, "\tMaxAp @MinFocal: f/%0.1f\n", mnLens.MaxAp4MinFocal);
|
||||
fprintf(outfile, "\tMaxAp @MaxFocal: f/%0.1f\n", mnLens.MaxAp4MaxFocal);
|
||||
fprintf(outfile, "\tMinAp @MinFocal: f/%0.1f\n", mnLens.MinAp4MinFocal);
|
||||
fprintf(outfile, "\tMinAp @MaxFocal: f/%0.1f\n", mnLens.MinAp4MaxFocal);
|
||||
fprintf(outfile, "\tMaxAp: f/%0.1f\n", mnLens.MaxAp);
|
||||
fprintf(outfile, "\tMinAp: f/%0.1f\n", mnLens.MinAp);
|
||||
fprintf(outfile, "\tCurFocal: %0.1f mm\n", mnLens.CurFocal);
|
||||
fprintf(outfile, "\tCurAp: f/%0.1f\n", mnLens.CurAp);
|
||||
fprintf(outfile, "\tMaxAp @CurFocal: f/%0.1f\n", mnLens.MaxAp4CurFocal);
|
||||
fprintf(outfile, "\tMinAp @CurFocal: f/%0.1f\n", mnLens.MinAp4CurFocal);
|
||||
|
||||
if (exifLens.makernotes.FocalLengthIn35mmFormat > 1.0f)
|
||||
fprintf(outfile, "\tFocalLengthIn35mmFormat: %0.1f mm\n", exifLens.makernotes.FocalLengthIn35mmFormat);
|
||||
|
||||
if (exifLens.nikon.EffectiveMaxAp > 0.1f)
|
||||
fprintf(outfile, "\tEffectiveMaxAp: f/%0.1f\n", exifLens.nikon.EffectiveMaxAp);
|
||||
|
||||
if (exifLens.makernotes.LensFStops > 0.1f)
|
||||
fprintf(outfile, "\tLensFStops @CurFocal: %0.2f\n", exifLens.makernotes.LensFStops);
|
||||
|
||||
fprintf(outfile, "\tTeleconverterID: %lld\n", mnLens.TeleconverterID);
|
||||
fprintf(outfile, "\tTeleconverter: %s\n", mnLens.Teleconverter);
|
||||
fprintf(outfile, "\tAdapterID: %lld\n", mnLens.AdapterID);
|
||||
fprintf(outfile, "\tAdapter: %s\n", mnLens.Adapter);
|
||||
fprintf(outfile, "\tAttachmentID: %lld\n", mnLens.AttachmentID);
|
||||
fprintf(outfile, "\tAttachment: %s\n", mnLens.Attachment);
|
||||
fprintf(outfile, "\n");
|
||||
|
||||
fprintf(outfile, "ISO speed: %d\n", (int)P2.iso_speed);
|
||||
if (P3.real_ISO > 0.1f)
|
||||
fprintf(outfile, "real ISO speed: %d\n", (int)P3.real_ISO);
|
||||
fprintf(outfile, "Shutter: ");
|
||||
if (P2.shutter > 0 && P2.shutter < 1)
|
||||
P2.shutter = fprintf(outfile, "1/%0.1f\n", 1.0f / P2.shutter);
|
||||
else if (P2.shutter >= 1)
|
||||
fprintf(outfile, "%0.1f sec\n", P2.shutter);
|
||||
else /* negative*/
|
||||
fprintf(outfile, " negative value\n");
|
||||
fprintf(outfile, "Aperture: f/%0.1f\n", P2.aperture);
|
||||
fprintf(outfile, "Focal length: %0.1f mm\n", P2.focal_len);
|
||||
if (P3.exifAmbientTemperature > -273.15f)
|
||||
fprintf(outfile, "Ambient temperature (exif data): %6.2f° C\n", P3.exifAmbientTemperature);
|
||||
if (P3.CameraTemperature > -273.15f)
|
||||
fprintf(outfile, "Camera temperature: %6.2f° C\n", P3.CameraTemperature);
|
||||
if (P3.SensorTemperature > -273.15f)
|
||||
fprintf(outfile, "Sensor temperature: %6.2f° C\n", P3.SensorTemperature);
|
||||
if (P3.SensorTemperature2 > -273.15f)
|
||||
fprintf(outfile, "Sensor temperature2: %6.2f° C\n", P3.SensorTemperature2);
|
||||
if (P3.LensTemperature > -273.15f)
|
||||
fprintf(outfile, "Lens temperature: %6.2f° C\n", P3.LensTemperature);
|
||||
if (P3.AmbientTemperature > -273.15f)
|
||||
fprintf(outfile, "Ambient temperature: %6.2f° C\n", P3.AmbientTemperature);
|
||||
if (P3.BatteryTemperature > -273.15f)
|
||||
fprintf(outfile, "Battery temperature: %6.2f° C\n", P3.BatteryTemperature);
|
||||
if (P3.FlashGN > 1.0f)
|
||||
fprintf(outfile, "Flash Guide Number: %6.2f\n", P3.FlashGN);
|
||||
fprintf(outfile, "Flash exposure compensation: %0.2f EV\n", P3.FlashEC);
|
||||
if (C.profile)
|
||||
fprintf(outfile, "Embedded ICC profile: yes, %d bytes\n", C.profile_length);
|
||||
else
|
||||
fprintf(outfile, "Embedded ICC profile: no\n");
|
||||
|
||||
if (C.dng_levels.baseline_exposure > -999.f)
|
||||
fprintf(outfile, "Baseline exposure: %04.3f\n", C.dng_levels.baseline_exposure);
|
||||
|
||||
fprintf(outfile, "Number of raw images: %d\n", P1.raw_count);
|
||||
|
||||
if (S.pixel_aspect != 1)
|
||||
fprintf(outfile, "Pixel Aspect Ratio: %0.6f\n", S.pixel_aspect);
|
||||
if (T.tlength)
|
||||
fprintf(outfile, "Thumb size: %4d x %d\n", T.twidth, T.theight);
|
||||
fprintf(outfile, "Full size: %4d x %d\n", S.raw_width, S.raw_height);
|
||||
|
||||
if (S.raw_inset_crops[0].cwidth)
|
||||
{
|
||||
fprintf(outfile, "Raw inset, width x height: %4d x %d ", S.raw_inset_crops[0].cwidth, S.raw_inset_crops[0].cheight);
|
||||
if (S.raw_inset_crops[0].cleft != 0xffff)
|
||||
fprintf(outfile, "left: %d ", S.raw_inset_crops[0].cleft);
|
||||
if (S.raw_inset_crops[0].ctop != 0xffff)
|
||||
fprintf(outfile, "top: %d", S.raw_inset_crops[0].ctop);
|
||||
fprintf(outfile, "\n");
|
||||
}
|
||||
|
||||
fprintf(outfile, "Image size: %4d x %d\n", S.width, S.height);
|
||||
fprintf(outfile, "Output size: %4d x %d\n", S.iwidth, S.iheight);
|
||||
fprintf(outfile, "Image flip: %d\n", S.flip);
|
||||
|
||||
fprintf(outfile, "Raw colors: %d", P1.colors);
|
||||
if (P1.filters)
|
||||
{
|
||||
fprintf(outfile, "\nFilter pattern: ");
|
||||
if (!P1.cdesc[3])
|
||||
P1.cdesc[3] = 'G';
|
||||
for (int i = 0; i < 16; i++)
|
||||
putchar(P1.cdesc[MyCoolRawProcessor.fcol(i >> 1, i & 1)]);
|
||||
}
|
||||
|
||||
if (C.black)
|
||||
{
|
||||
fprintf(outfile, "\nblack: %d", C.black);
|
||||
}
|
||||
if (C.cblack[0] != 0)
|
||||
{
|
||||
fprintf(outfile, "\ncblack[0 .. 3]:");
|
||||
for (int c = 0; c < 4; c++)
|
||||
fprintf(outfile, " %d", C.cblack[c]);
|
||||
}
|
||||
if ((C.cblack[4] * C.cblack[5]) > 0)
|
||||
{
|
||||
fprintf(outfile, "\nBlackLevelRepeatDim: %d x %d\n", C.cblack[4], C.cblack[5]);
|
||||
int n = C.cblack[4] * C.cblack[5];
|
||||
fprintf(outfile, "cblack[6 .. %d]:", 6 + n - 1);
|
||||
for (int c = 6; c < 6 + n; c++)
|
||||
fprintf(outfile, " %d", C.cblack[c]);
|
||||
}
|
||||
|
||||
if (C.linear_max[0] != 0)
|
||||
{
|
||||
fprintf(outfile, "\nHighlight linearity limits:");
|
||||
for (int c = 0; c < 4; c++)
|
||||
fprintf(outfile, " %ld", C.linear_max[c]);
|
||||
}
|
||||
|
||||
if (P1.colors > 1)
|
||||
{
|
||||
fprintf(outfile, "\nMakernotes WB data: coeffs EVs");
|
||||
if ((C.cam_mul[0] > 0) && (C.cam_mul[1] > 0))
|
||||
{
|
||||
fprintf(outfile, "\n %-23s %g %g %g %g %5.2f %5.2f %5.2f %5.2f", "As shot", C.cam_mul[0], C.cam_mul[1],
|
||||
C.cam_mul[2], C.cam_mul[3], roundf(_log2(C.cam_mul[0] / C.cam_mul[1]) * 100.0f) / 100.0f, 0.0f,
|
||||
roundf(_log2(C.cam_mul[2] / C.cam_mul[1]) * 100.0f) / 100.0f,
|
||||
C.cam_mul[3] ? roundf(_log2(C.cam_mul[3] / C.cam_mul[1]) * 100.0f) / 100.0f : 0.0f);
|
||||
}
|
||||
|
||||
for (int cnt = 0; cnt < int(sizeof WBToStr / sizeof *WBToStr); cnt++)
|
||||
{
|
||||
WBi = WBToStr[cnt].NumId;
|
||||
if ((C.WB_Coeffs[WBi][0] > 0) && (C.WB_Coeffs[WBi][1] > 0))
|
||||
{
|
||||
denom = (float)C.WB_Coeffs[WBi][1];
|
||||
fprintf(outfile, "\n %-23s %4d %4d %4d %4d %5.2f %5.2f %5.2f %5.2f", WBToStr[cnt].hrStrId,
|
||||
C.WB_Coeffs[WBi][0], C.WB_Coeffs[WBi][1], C.WB_Coeffs[WBi][2], C.WB_Coeffs[WBi][3],
|
||||
roundf(_log2((float)C.WB_Coeffs[WBi][0] / denom) * 100.0f) / 100.0f, 0.0f,
|
||||
roundf(_log2((float)C.WB_Coeffs[WBi][2] / denom) * 100.0f) / 100.0f,
|
||||
C.WB_Coeffs[3] ? roundf(_log2((float)C.WB_Coeffs[WBi][3] / denom) * 100.0f) / 100.0f : 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (C.rgb_cam[0][0] > 0.0001)
|
||||
{
|
||||
fprintf(outfile, "\n\nCamera2RGB matrix (mode: %d):\n", MyCoolRawProcessor.imgdata.params.use_camera_matrix);
|
||||
PRINTMATRIX3x4(outfile, C.rgb_cam, P1.colors);
|
||||
}
|
||||
|
||||
fprintf(outfile, "\nXYZ->CamRGB matrix:\n");
|
||||
PRINTMATRIX4x3(outfile, C.cam_xyz, P1.colors);
|
||||
|
||||
for (int cnt = 0; cnt < 2; cnt++)
|
||||
{
|
||||
if (fabsf(C.P1_color[cnt].romm_cam[0]) > 0)
|
||||
{
|
||||
fprintf(outfile, "\nPhaseOne Matrix %d:\n", cnt + 1);
|
||||
for (int i = 0; i < 3; i++)
|
||||
fprintf(outfile, "%6.4f\t%6.4f\t%6.4f\n", C.P1_color[cnt].romm_cam[i * 3],
|
||||
C.P1_color[cnt].romm_cam[i * 3 + 1], C.P1_color[cnt].romm_cam[i * 3 + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (fabsf(C.cmatrix[0][0]) > 0)
|
||||
{
|
||||
fprintf(outfile, "\ncamRGB -> sRGB Matrix:\n");
|
||||
PRINTMATRIX3x4(outfile, C.cmatrix, P1.colors);
|
||||
}
|
||||
|
||||
if (fabsf(C.ccm[0][0]) > 0)
|
||||
{
|
||||
fprintf(outfile, "\nColor Correction Matrix:\n");
|
||||
PRINTMATRIX3x4(outfile, C.ccm, P1.colors);
|
||||
}
|
||||
|
||||
for (int cnt = 0; cnt < 2; cnt++)
|
||||
{
|
||||
if (C.dng_color[cnt].illuminant != LIBRAW_WBI_None)
|
||||
{
|
||||
if (C.dng_color[cnt].illuminant <= LIBRAW_WBI_StudioTungsten)
|
||||
{
|
||||
fprintf(outfile, "\nDNG Illuminant %d: %s", cnt + 1, WB_idx2hrstr(C.dng_color[cnt].illuminant));
|
||||
}
|
||||
else if (C.dng_color[cnt].illuminant == LIBRAW_WBI_Other)
|
||||
{
|
||||
fprintf(outfile, "\nDNG Illuminant %d: Other", cnt + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(outfile,
|
||||
"\nDNG Illuminant %d is out of EXIF LightSources range "
|
||||
"[0:24, 255]: %d",
|
||||
cnt + 1, C.dng_color[cnt].illuminant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int n = 0; n < 2; n++)
|
||||
{
|
||||
if (fabsf(C.dng_color[n].colormatrix[0][0]) > 0)
|
||||
{
|
||||
fprintf(outfile, "\nDNG color matrix %d:\n", n + 1);
|
||||
PRINTMATRIX4x3(outfile, C.dng_color[n].colormatrix, P1.colors);
|
||||
}
|
||||
}
|
||||
|
||||
for (int n = 0; n < 2; n++)
|
||||
{
|
||||
if (fabsf(C.dng_color[n].calibration[0][0]) > 0)
|
||||
{
|
||||
fprintf(outfile, "\nDNG calibration matrix %d:\n", n + 1);
|
||||
for (int i = 0; i < P1.colors && i < 4; i++)
|
||||
{
|
||||
for (int j = 0; j < P1.colors && j < 4; j++)
|
||||
fprintf(outfile, "%6.4f\t", C.dng_color[n].calibration[j][i]);
|
||||
fprintf(outfile, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int n = 0; n < 2; n++)
|
||||
{
|
||||
if (fabsf(C.dng_color[n].forwardmatrix[0][0]) > 0)
|
||||
{
|
||||
fprintf(outfile, "\nDNG forward matrix %d:\n", n + 1);
|
||||
PRINTMATRIX3x4(outfile, C.dng_color[n].forwardmatrix, P1.colors);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(outfile, "\nDerived D65 multipliers:");
|
||||
for (int c = 0; c < P1.colors; c++)
|
||||
fprintf(outfile, " %f", C.pre_mul[c]);
|
||||
fprintf(outfile, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void print_wbfun(FILE *outfile, LibRaw &MyCoolRawProcessor, std::string &fn)
|
||||
{
|
||||
int WBi;
|
||||
float denom;
|
||||
fprintf(outfile, "// %s %s\n", P1.make, P1.model);
|
||||
for (int cnt = 0; cnt < int(sizeof WBToStr / sizeof *WBToStr); cnt++)
|
||||
{
|
||||
WBi = WBToStr[cnt].NumId;
|
||||
if (C.WB_Coeffs[WBi][0] && C.WB_Coeffs[WBi][1] && !WBToStr[cnt].aux_setting)
|
||||
{
|
||||
denom = (float)C.WB_Coeffs[WBi][1];
|
||||
fprintf(outfile, "{\"%s\", \"%s\", %s, {%6.5ff, 1.0f, %6.5ff, ", P1.normalized_make, P1.normalized_model,
|
||||
WBToStr[cnt].StrId, C.WB_Coeffs[WBi][0] / denom, C.WB_Coeffs[WBi][2] / denom);
|
||||
if (C.WB_Coeffs[WBi][1] == C.WB_Coeffs[WBi][3])
|
||||
fprintf(outfile, "1.0f}},\n");
|
||||
else
|
||||
fprintf(outfile, "%6.5ff}},\n", C.WB_Coeffs[WBi][3] / denom);
|
||||
}
|
||||
}
|
||||
|
||||
for (int cnt = 0; cnt < 64; cnt++)
|
||||
if (C.WBCT_Coeffs[cnt][0])
|
||||
{
|
||||
fprintf(outfile, "{\"%s\", \"%s\", %d, {%6.5ff, 1.0f, %6.5ff, ", P1.normalized_make, P1.normalized_model,
|
||||
(int)C.WBCT_Coeffs[cnt][0], C.WBCT_Coeffs[cnt][1] / C.WBCT_Coeffs[cnt][2],
|
||||
C.WBCT_Coeffs[cnt][3] / C.WBCT_Coeffs[cnt][2]);
|
||||
if (C.WBCT_Coeffs[cnt][2] == C.WBCT_Coeffs[cnt][4])
|
||||
fprintf(outfile, "1.0f}},\n");
|
||||
else
|
||||
fprintf(outfile, "%6.5ff}},\n", C.WBCT_Coeffs[cnt][4] / C.WBCT_Coeffs[cnt][2]);
|
||||
}
|
||||
else
|
||||
break;
|
||||
fprintf(outfile, "\n");
|
||||
}
|
||||
|
||||
void print_szfun(FILE *outfile, LibRaw &MyCoolRawProcessor, std::string &fn)
|
||||
{
|
||||
fprintf(outfile, "%s\t%s\t%s\t%d\t%d\n", fn.c_str(), P1.make, P1.model, S.width, S.height);
|
||||
}
|
||||
|
||||
void print_unpackfun(FILE *outfile, LibRaw &MyCoolRawProcessor, int print_frame, std::string &fn)
|
||||
{
|
||||
char frame[48] = "";
|
||||
if (print_frame)
|
||||
{
|
||||
ushort right_margin = S.raw_width - S.width - S.left_margin;
|
||||
ushort bottom_margin = S.raw_height - S.height - S.top_margin;
|
||||
snprintf(frame, 48, "F=%dx%dx%dx%d RS=%dx%d", S.left_margin, S.top_margin, right_margin, bottom_margin, S.raw_width,
|
||||
S.raw_height);
|
||||
}
|
||||
fprintf(outfile, "%s\t%s\t%s\t%s/%s\n", fn.c_str(), MyCoolRawProcessor.unpack_function_name(), frame, P1.make,
|
||||
P1.model);
|
||||
}
|
144
samples/rawtextdump.cpp
Normal file
144
samples/rawtextdump.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/* -*- C++ -*-
|
||||
* File: raw2text.cpp
|
||||
* Copyright 2008-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Sun Sept 01, 2020
|
||||
*
|
||||
* LibRaw sample
|
||||
* Dumps (small) selection of RAW data to text file
|
||||
*
|
||||
|
||||
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>
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "libraw/libraw.h"
|
||||
|
||||
void usage(const char *av)
|
||||
{
|
||||
printf(
|
||||
"Dump (small) selection of RAW file as tab-separated text file\n"
|
||||
"Usage: %s inputfile COL ROW [CHANNEL] [width] [height]\n"
|
||||
" COL - start column\n"
|
||||
" ROW - start row\n"
|
||||
" CHANNEL - raw channel to dump, default is 0 (red for rggb)\n"
|
||||
" width - area width to dump, default is 16\n"
|
||||
" height - area height to dump, default is 4\n"
|
||||
, av);
|
||||
}
|
||||
|
||||
unsigned subtract_bl(unsigned int val, int bl)
|
||||
{
|
||||
return val > (unsigned)bl ? val - (unsigned)bl : 0;
|
||||
}
|
||||
|
||||
class LibRaw_bl : public LibRaw
|
||||
{
|
||||
public:
|
||||
void adjust_blacklevel() { LibRaw::adjust_bl(); }
|
||||
};
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
if (ac < 4)
|
||||
{
|
||||
usage(av[0]);
|
||||
exit(1);
|
||||
}
|
||||
int colstart = atoi(av[2]);
|
||||
int rowstart = atoi(av[3]);
|
||||
int channel = 0;
|
||||
if (ac > 4) channel = atoi(av[4]);
|
||||
int width = 16;
|
||||
if (ac > 5) width = atoi(av[5]);
|
||||
int height = 4;
|
||||
if (ac > 6) height = atoi(av[6]);
|
||||
if (width <1 || height<1)
|
||||
{
|
||||
usage(av[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
LibRaw_bl lr;
|
||||
|
||||
if (lr.open_file(av[1]) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Unable to open file %s\n", av[1]);
|
||||
exit(1);
|
||||
}
|
||||
if ((lr.imgdata.idata.colors == 1 && channel>0) || (channel >3))
|
||||
{
|
||||
fprintf(stderr, "Incorrect CHANNEL specified: %d\n", channel);
|
||||
exit(1);
|
||||
}
|
||||
if (lr.unpack() != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Unable to unpack raw data from %s\n", av[1]);
|
||||
exit(1);
|
||||
}
|
||||
lr.adjust_blacklevel();
|
||||
printf("%s\t%d-%d-%dx%d\tchannel: %d\n", av[1], colstart, rowstart, width, height, channel);
|
||||
|
||||
printf("%6s", "R\\C");
|
||||
for (int col = colstart; col < colstart + width && col < lr.imgdata.sizes.raw_width; col++)
|
||||
printf("%6u", col);
|
||||
printf("\n");
|
||||
|
||||
if (lr.imgdata.rawdata.raw_image)
|
||||
{
|
||||
for (int row = rowstart; row < rowstart + height && row < lr.imgdata.sizes.raw_height; row++)
|
||||
{
|
||||
unsigned rcolors[48];
|
||||
if (lr.imgdata.idata.colors > 1)
|
||||
for (int c = 0; c < 48; c++)
|
||||
rcolors[c] = lr.COLOR(row, c);
|
||||
else
|
||||
memset(rcolors, 0, sizeof(rcolors));
|
||||
unsigned short *rowdata = &lr.imgdata.rawdata.raw_image[row * lr.imgdata.sizes.raw_pitch / 2];
|
||||
printf("%6u", row);
|
||||
for (int col = colstart; col < colstart + width && col < lr.imgdata.sizes.raw_width; col++)
|
||||
if (rcolors[col % 48] == (unsigned)channel) printf("%6u", subtract_bl(rowdata[col],lr.imgdata.color.cblack[channel]));
|
||||
else printf(" -");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
else if (lr.imgdata.rawdata.color4_image && channel < 4)
|
||||
{
|
||||
for (int row = rowstart; row < rowstart + height && row < lr.imgdata.sizes.raw_height; row++)
|
||||
{
|
||||
unsigned short(*rowdata)[4] = &lr.imgdata.rawdata.color4_image[row * lr.imgdata.sizes.raw_pitch / 8];
|
||||
printf("%6u", row);
|
||||
for (int col = colstart; col < colstart + width && col < lr.imgdata.sizes.raw_width; col++)
|
||||
printf("%6u", subtract_bl(rowdata[col][channel],lr.imgdata.color.cblack[channel]));
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
else if (lr.imgdata.rawdata.color3_image && channel < 3)
|
||||
{
|
||||
for (int row = rowstart; row < rowstart + height && row < lr.imgdata.sizes.raw_height; row++)
|
||||
{
|
||||
unsigned short(*rowdata)[3] = &lr.imgdata.rawdata.color3_image[row * lr.imgdata.sizes.raw_pitch / 6];
|
||||
printf("%6u", row);
|
||||
for (int col = colstart; col < colstart + width && col < lr.imgdata.sizes.raw_width; col++)
|
||||
printf("%6u", subtract_bl(rowdata[col][channel],lr.imgdata.color.cblack[channel]));
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("Unsupported file data (e.g. floating point format), or incorrect channel specified\n");
|
||||
}
|
217
samples/simple_dcraw.cpp
Normal file
217
samples/simple_dcraw.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/* -*- C++ -*-
|
||||
* File: simple_dcraw.cpp
|
||||
* Copyright 2008-2021 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 "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]);
|
||||
|
||||
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" : "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.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;
|
||||
}
|
319
samples/unprocessed_raw.cpp
Normal file
319
samples/unprocessed_raw.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
/* -*- C++ -*-
|
||||
* File: unprocessed_raw.cpp
|
||||
* Copyright 2009-2021 LibRaw LLC (info@libraw.org)
|
||||
* Created: Fri Jan 02, 2009
|
||||
*
|
||||
* LibRaw sample
|
||||
* Generates unprocessed raw image: with masked pixels and without black
|
||||
subtraction
|
||||
*
|
||||
|
||||
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 <time.h>
|
||||
|
||||
#include "libraw/libraw.h"
|
||||
|
||||
#ifndef LIBRAW_WIN32_CALLS
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#include <sys/utime.h>
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef LIBRAW_WIN32_CALLS
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#if !(LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0, 14))
|
||||
#error This code is for LibRaw 0.14+ only
|
||||
#endif
|
||||
|
||||
void gamma_curve(unsigned short curve[]);
|
||||
void write_ppm(unsigned width, unsigned height, unsigned short *bitmap,
|
||||
const char *basename);
|
||||
void write_tiff(int width, int height, unsigned short *bitmap,
|
||||
const char *basename);
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
int i, ret;
|
||||
int verbose = 1, autoscale = 0, use_gamma = 0, out_tiff = 0;
|
||||
char outfn[1024];
|
||||
|
||||
LibRaw RawProcessor;
|
||||
if (ac < 2)
|
||||
{
|
||||
usage:
|
||||
printf("unprocessed_raw - LibRaw %s sample. %d cameras supported\n"
|
||||
"Usage: %s [-q] [-A] [-g] [-s N] raw-files....\n"
|
||||
"\t-q - be quiet\n"
|
||||
"\t-s N - select Nth image in file (default=0)\n"
|
||||
"\t-g - use gamma correction with gamma 2.2 (not precise,use for "
|
||||
"visual inspection only)\n"
|
||||
"\t-A - autoscaling (by integer factor)\n"
|
||||
"\t-T - write tiff instead of pgm\n",
|
||||
LibRaw::version(), LibRaw::cameraCount(), av[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define S RawProcessor.imgdata.sizes
|
||||
#define OUT RawProcessor.imgdata.params
|
||||
#define OUTR RawProcessor.imgdata.rawparams
|
||||
|
||||
for (i = 1; i < ac; i++)
|
||||
{
|
||||
if (av[i][0] == '-')
|
||||
{
|
||||
if (av[i][1] == 'q' && av[i][2] == 0)
|
||||
verbose = 0;
|
||||
else if (av[i][1] == 'A' && av[i][2] == 0)
|
||||
autoscale = 1;
|
||||
else if (av[i][1] == 'g' && av[i][2] == 0)
|
||||
use_gamma = 1;
|
||||
else if (av[i][1] == 'T' && av[i][2] == 0)
|
||||
out_tiff = 1;
|
||||
else if (av[i][1] == 's' && av[i][2] == 0)
|
||||
{
|
||||
i++;
|
||||
OUTR.shot_select = av[i] ? atoi(av[i]) : 0;
|
||||
}
|
||||
else
|
||||
goto usage;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printf("Processing file %s\n", av[i]);
|
||||
if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret));
|
||||
continue; // no recycle b/c open file will recycle itself
|
||||
}
|
||||
if (verbose)
|
||||
{
|
||||
printf("Image size: %dx%d\nRaw size: %dx%d\n", S.width, S.height,
|
||||
S.raw_width, S.raw_height);
|
||||
printf("Margins: top=%d, left=%d\n", S.top_margin, S.left_margin);
|
||||
}
|
||||
|
||||
if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printf("Unpacked....\n");
|
||||
|
||||
if (!(RawProcessor.imgdata.idata.filters ||
|
||||
RawProcessor.imgdata.idata.colors == 1))
|
||||
{
|
||||
printf("Only Bayer-pattern RAW files supported, sorry....\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (autoscale)
|
||||
{
|
||||
unsigned max = 0, scale;
|
||||
for (int j = 0; j < S.raw_height * S.raw_width; j++)
|
||||
if (max < RawProcessor.imgdata.rawdata.raw_image[j])
|
||||
max = RawProcessor.imgdata.rawdata.raw_image[j];
|
||||
if (max > 0 && max < 1 << 15)
|
||||
{
|
||||
scale = (1 << 16) / max;
|
||||
if (verbose)
|
||||
printf("Scaling with multiplier=%d (max=%d)\n", scale, max);
|
||||
|
||||
for (int j = 0; j < S.raw_height * S.raw_width; j++)
|
||||
RawProcessor.imgdata.rawdata.raw_image[j] *= scale;
|
||||
}
|
||||
}
|
||||
if (use_gamma)
|
||||
{
|
||||
unsigned short curve[0x10000];
|
||||
gamma_curve(curve);
|
||||
for (int j = 0; j < S.raw_height * S.raw_width; j++)
|
||||
RawProcessor.imgdata.rawdata.raw_image[j] =
|
||||
curve[RawProcessor.imgdata.rawdata.raw_image[j]];
|
||||
if (verbose)
|
||||
printf("Gamma-corrected....\n");
|
||||
}
|
||||
|
||||
if (OUTR.shot_select)
|
||||
snprintf(outfn, sizeof(outfn), "%s-%d.%s", av[i], OUTR.shot_select,
|
||||
out_tiff ? "tiff" : "pgm");
|
||||
else
|
||||
snprintf(outfn, sizeof(outfn), "%s.%s", av[i], out_tiff ? "tiff" : "pgm");
|
||||
|
||||
if (out_tiff)
|
||||
write_tiff(S.raw_width, S.raw_height,
|
||||
RawProcessor.imgdata.rawdata.raw_image, outfn);
|
||||
else
|
||||
write_ppm(S.raw_width, S.raw_height,
|
||||
RawProcessor.imgdata.rawdata.raw_image, outfn);
|
||||
|
||||
if (verbose)
|
||||
printf("Stored to file %s\n", outfn);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void write_ppm(unsigned width, unsigned height, unsigned short *bitmap,
|
||||
const char *fname)
|
||||
{
|
||||
if (!bitmap)
|
||||
return;
|
||||
|
||||
FILE *f = fopen(fname, "wb");
|
||||
if (!f)
|
||||
return;
|
||||
int bits = 16;
|
||||
fprintf(f, "P5\n%d %d\n%d\n", width, height, (1 << bits) - 1);
|
||||
unsigned char *data = (unsigned char *)bitmap;
|
||||
unsigned data_size = width * height * 2;
|
||||
#define SWAP(a, b) \
|
||||
{ \
|
||||
a ^= b; \
|
||||
a ^= (b ^= a); \
|
||||
}
|
||||
for (unsigned i = 0; i < data_size; i += 2)
|
||||
SWAP(data[i], data[i + 1]);
|
||||
#undef SWAP
|
||||
fwrite(data, data_size, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
/* == gamma curve and tiff writer - simplified cut'n'paste from dcraw.c */
|
||||
|
||||
#define SQR(x) ((x) * (x))
|
||||
|
||||
void gamma_curve(unsigned short *curve)
|
||||
{
|
||||
|
||||
double pwr = 1.0 / 2.2;
|
||||
double ts = 0.0;
|
||||
int imax = 0xffff;
|
||||
int mode = 2;
|
||||
int i;
|
||||
double g[6], bnd[2] = {0, 0}, r;
|
||||
|
||||
g[0] = pwr;
|
||||
g[1] = ts;
|
||||
g[2] = g[3] = g[4] = 0;
|
||||
bnd[g[1] >= 1] = 1;
|
||||
if (g[1] && (g[1] - 1) * (g[0] - 1) <= 0)
|
||||
{
|
||||
for (i = 0; i < 48; i++)
|
||||
{
|
||||
g[2] = (bnd[0] + bnd[1]) / 2;
|
||||
if (g[0])
|
||||
bnd[(pow(g[2] / g[1], -g[0]) - 1) / g[0] - 1 / g[2] > -1] = g[2];
|
||||
else
|
||||
bnd[g[2] / exp(1 - 1 / g[2]) < g[1]] = g[2];
|
||||
}
|
||||
g[3] = g[2] / g[1];
|
||||
if (g[0])
|
||||
g[4] = g[2] * (1 / g[0] - 1);
|
||||
}
|
||||
if (g[0])
|
||||
g[5] = 1 / (g[1] * SQR(g[3]) / 2 - g[4] * (1 - g[3]) +
|
||||
(1 - pow(g[3], 1 + g[0])) * (1 + g[4]) / (1 + g[0])) -
|
||||
1;
|
||||
else
|
||||
g[5] = 1 / (g[1] * SQR(g[3]) / 2 + 1 - g[2] - g[3] -
|
||||
g[2] * g[3] * (log(g[3]) - 1)) -
|
||||
1;
|
||||
for (i = 0; i < 0x10000; i++)
|
||||
{
|
||||
curve[i] = 0xffff;
|
||||
if ((r = (double)i / imax) < 1)
|
||||
curve[i] =
|
||||
0x10000 *
|
||||
(mode ? (r < g[3] ? r * g[1]
|
||||
: (g[0] ? pow(r, g[0]) * (1 + g[4]) - g[4]
|
||||
: log(r) * g[2] + 1))
|
||||
: (r < g[2] ? r / g[1]
|
||||
: (g[0] ? pow((r + g[4]) / (1 + g[4]), 1 / g[0])
|
||||
: exp((r - 1) / g[2]))));
|
||||
}
|
||||
}
|
||||
|
||||
void tiff_set(ushort *ntag, ushort tag, ushort type, int count, int val)
|
||||
{
|
||||
struct libraw_tiff_tag *tt;
|
||||
int c;
|
||||
|
||||
tt = (struct libraw_tiff_tag *)(ntag + 1) + (*ntag)++;
|
||||
tt->tag = tag;
|
||||
tt->type = type;
|
||||
tt->count = count;
|
||||
if ((type < LIBRAW_EXIFTAG_TYPE_SHORT) && (count <= 4))
|
||||
for (c = 0; c < 4; c++)
|
||||
tt->val.c[c] = val >> (c << 3);
|
||||
else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SHORT) && (count <= 2))
|
||||
for (c = 0; c < 2; c++)
|
||||
tt->val.s[c] = val >> (c << 4);
|
||||
else
|
||||
tt->val.i = val;
|
||||
}
|
||||
#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
|
||||
|
||||
void tiff_head(int width, int height, struct tiff_hdr *th)
|
||||
{
|
||||
int c;
|
||||
time_t timestamp = time(NULL);
|
||||
struct tm *t;
|
||||
|
||||
memset(th, 0, sizeof *th);
|
||||
th->t_order = htonl(0x4d4d4949) >> 16;
|
||||
th->magic = 42;
|
||||
th->ifd = 10;
|
||||
tiff_set(&th->ntag, 254, 4, 1, 0);
|
||||
tiff_set(&th->ntag, 256, 4, 1, width);
|
||||
tiff_set(&th->ntag, 257, 4, 1, height);
|
||||
tiff_set(&th->ntag, 258, 3, 1, 16);
|
||||
for (c = 0; c < 4; c++)
|
||||
th->bps[c] = 16;
|
||||
tiff_set(&th->ntag, 259, 3, 1, 1);
|
||||
tiff_set(&th->ntag, 262, 3, 1, 1);
|
||||
tiff_set(&th->ntag, 273, 4, 1, sizeof *th);
|
||||
tiff_set(&th->ntag, 277, 3, 1, 1);
|
||||
tiff_set(&th->ntag, 278, 4, 1, height);
|
||||
tiff_set(&th->ntag, 279, 4, 1, height * width * 2);
|
||||
tiff_set(&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
|
||||
tiff_set(&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
|
||||
tiff_set(&th->ntag, 284, 3, 1, 1);
|
||||
tiff_set(&th->ntag, 296, 3, 1, 2);
|
||||
tiff_set(&th->ntag, 306, 2, 20, TOFF(th->date));
|
||||
th->rat[0] = th->rat[2] = 300;
|
||||
th->rat[1] = th->rat[3] = 1;
|
||||
t = localtime(×tamp);
|
||||
if (t)
|
||||
sprintf(th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year + 1900,
|
||||
t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
}
|
||||
|
||||
void write_tiff(int width, int height, unsigned short *bitmap, const char *fn)
|
||||
{
|
||||
struct tiff_hdr th;
|
||||
|
||||
FILE *ofp = fopen(fn, "wb");
|
||||
if (!ofp)
|
||||
return;
|
||||
tiff_head(width, height, &th);
|
||||
fwrite(&th, sizeof th, 1, ofp);
|
||||
fwrite(bitmap, 2, width * height, ofp);
|
||||
fclose(ofp);
|
||||
}
|
Reference in New Issue
Block a user