parent
446c9b6741
commit
80c17255d5
@ -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;
|
||||||
|
}
|
Loading…
Reference in new issue