diff --git a/libkdcraw/libraw/samples/mem_image.cpp b/libkdcraw/libraw/samples/mem_image.cpp new file mode 100644 index 0000000..1ce5b8c --- /dev/null +++ b/libkdcraw/libraw/samples/mem_image.cpp @@ -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 +#include +#include + +#include "libraw/libraw.h" + +#ifdef USE_JPEG +#include "jpeglib.h" +#endif + +#ifdef LIBRAW_WIN32_CALLS +#define snprintf _snprintf +#include +#pragma comment(lib, "ws2_32.lib") +#else +#include +#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; +}