File indexing completed on 2025-01-05 03:56:48
0001 /* -*- C++ -*- 0002 * File: mem_image.cpp 0003 * Copyright 2008-2021 LibRaw LLC (info@libraw.org) 0004 * 0005 * LibRaw mem_image/mem_thumb API test. Results should be same (bitwise) to 0006 dcraw [-4] [-6] [-e] 0007 * Testing note: for ppm-thumbnails you should use dcraw -w -e for thumbnail 0008 extraction 0009 0010 LibRaw is free software; you can redistribute it and/or modify 0011 it under the terms of the one of two licenses as you choose: 0012 0013 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 0014 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 0015 0016 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 0017 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). 0018 0019 0020 */ 0021 #include <stdio.h> 0022 #include <string.h> 0023 #include <math.h> 0024 0025 #include "libraw/libraw.h" 0026 0027 #ifdef USE_JPEG 0028 #include "jpeglib.h" 0029 #endif 0030 0031 #ifdef LIBRAW_WIN32_CALLS 0032 #define snprintf _snprintf 0033 #include <winsock2.h> 0034 #pragma comment(lib, "ws2_32.lib") 0035 #else 0036 #include <netinet/in.h> 0037 #endif 0038 0039 #ifdef USE_JPEG 0040 void write_jpeg(libraw_processed_image_t *img, const char *basename, int quality) 0041 { 0042 char fn[1024]; 0043 if(img->colors != 1 && img->colors != 3) 0044 { 0045 printf("Only BW and 3-color images supported for JPEG output\n"); 0046 return; 0047 } 0048 snprintf(fn, 1024, "%s.jpg", basename); 0049 FILE *f = fopen(fn, "wb"); 0050 if (!f) 0051 return; 0052 struct jpeg_compress_struct cinfo; 0053 struct jpeg_error_mgr jerr; 0054 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ 0055 int row_stride; /* physical row width in image buffer */ 0056 0057 cinfo.err = jpeg_std_error(&jerr); 0058 jpeg_create_compress(&cinfo); 0059 jpeg_stdio_dest(&cinfo, f); 0060 cinfo.image_width = img->width; /* image width and height, in pixels */ 0061 cinfo.image_height = img->height; 0062 cinfo.input_components = img->colors; /* # of color components per pixel */ 0063 cinfo.in_color_space = img->colors==3?JCS_RGB:JCS_GRAYSCALE; /* colorspace of input image */ 0064 jpeg_set_defaults(&cinfo); 0065 jpeg_set_quality(&cinfo, quality, TRUE); 0066 jpeg_start_compress(&cinfo, TRUE); 0067 row_stride = img->width * img->colors; /* JSAMPLEs per row in image_buffer */ 0068 while (cinfo.next_scanline < cinfo.image_height) { 0069 row_pointer[0] = &img->data[cinfo.next_scanline * row_stride]; 0070 (void)jpeg_write_scanlines(&cinfo, row_pointer, 1); 0071 } 0072 jpeg_finish_compress(&cinfo); 0073 fclose(f); 0074 jpeg_destroy_compress(&cinfo); 0075 } 0076 0077 #endif 0078 0079 // no error reporting, only params check 0080 void write_ppm(libraw_processed_image_t *img, const char *basename) 0081 { 0082 if (!img) 0083 return; 0084 // type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check 0085 if (img->type != LIBRAW_IMAGE_BITMAP) 0086 return; 0087 if (img->colors != 3 && img->colors != 1) 0088 { 0089 printf("Only monochrome and 3-color images supported for PPM output\n"); 0090 return; 0091 } 0092 0093 char fn[1024]; 0094 snprintf(fn, 1024, "%s.p%cm", basename, img->colors==1?'g':'p'); 0095 FILE *f = fopen(fn, "wb"); 0096 if (!f) 0097 return; 0098 fprintf(f, "P%d\n%d %d\n%d\n", img->colors/2 + 5, img->width, img->height, (1 << img->bits) - 1); 0099 /* 0100 NOTE: 0101 data in img->data is not converted to network byte order. 0102 So, we should swap values on some architectures for dcraw compatibility 0103 (unfortunately, xv cannot display 16-bit PPMs with network byte order data 0104 */ 0105 #define SWAP(a, b) \ 0106 { \ 0107 a ^= b; \ 0108 a ^= (b ^= a); \ 0109 } 0110 if (img->bits == 16 && htons(0x55aa) != 0x55aa) 0111 for (unsigned i = 0; i < img->data_size-1; i += 2) 0112 SWAP(img->data[i], img->data[i + 1]); 0113 #undef SWAP 0114 0115 fwrite(img->data, img->data_size, 1, f); 0116 fclose(f); 0117 } 0118 0119 void write_thumb(libraw_processed_image_t *img, const char *basename) 0120 { 0121 if (!img) 0122 return; 0123 0124 if (img->type == LIBRAW_IMAGE_BITMAP) 0125 { 0126 char fnt[1024]; 0127 snprintf(fnt, 1024, "%s.thumb", basename); 0128 write_ppm(img, fnt); 0129 } 0130 else if (img->type == LIBRAW_IMAGE_JPEG) 0131 { 0132 char fn[1024]; 0133 snprintf(fn, 1024, "%s.thumb.jpg", basename); 0134 FILE *f = fopen(fn, "wb"); 0135 if (!f) 0136 return; 0137 fwrite(img->data, img->data_size, 1, f); 0138 fclose(f); 0139 } 0140 } 0141 0142 int main(int ac, char *av[]) 0143 { 0144 int i, ret, output_thumbs = 0; 0145 #ifdef USE_JPEG 0146 int output_jpeg = 0, jpgqual = 90; 0147 #endif 0148 // don't use fixed size buffers in real apps! 0149 0150 LibRaw RawProcessor; 0151 0152 if (ac < 2) 0153 { 0154 printf("mem_image - LibRaw sample, to illustrate work for memory buffers.\n" 0155 "Emulates dcraw [-4] [-1] [-e] [-h]\n" 0156 #ifdef USE_JPEG 0157 "Usage: %s [-D] [-j[nn]] [-T] [-v] [-e] raw-files....\n" 0158 #else 0159 "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n" 0160 #endif 0161 "\t-6 - output 16-bit PPM\n" 0162 "\t-4 - linear 16-bit data\n" 0163 "\t-e - extract thumbnails (same as dcraw -e in separate run)\n" 0164 #ifdef USE_JPEG 0165 "\t-j[qual] - output JPEG with qual quality (e.g. -j90)\n" 0166 #endif 0167 "\t-h - use half_size\n", av[0]); 0168 return 0; 0169 } 0170 0171 putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field 0172 0173 #define P1 RawProcessor.imgdata.idata 0174 #define S RawProcessor.imgdata.sizes 0175 #define C RawProcessor.imgdata.color 0176 #define T RawProcessor.imgdata.thumbnail 0177 #define P2 RawProcessor.imgdata.other 0178 #define OUT RawProcessor.imgdata.params 0179 0180 for (i = 1; i < ac; i++) 0181 { 0182 if (av[i][0] == '-') 0183 { 0184 if (av[i][1] == '6' && av[i][2] == 0) 0185 OUT.output_bps = 16; 0186 if (av[i][1] == '4' && av[i][2] == 0) 0187 { 0188 OUT.output_bps = 16; 0189 OUT.gamm[0] = OUT.gamm[1] = OUT.no_auto_bright = 1; 0190 } 0191 if (av[i][1] == 'e' && av[i][2] == 0) 0192 output_thumbs++; 0193 if (av[i][1] == 'h' && av[i][2] == 0) 0194 OUT.half_size = 1; 0195 #ifdef USE_JPEG 0196 if (av[i][1] == 'j') 0197 { 0198 output_jpeg = 1; 0199 if(av[i][2] != 0) 0200 jpgqual = atoi(av[i]+2); 0201 } 0202 #endif 0203 continue; 0204 } 0205 #ifdef USE_JPEG 0206 if(output_jpeg && OUT.output_bps>8) 0207 { 0208 printf("JPEG is limited to 8 bit\n"); 0209 OUT.output_bps = 8; 0210 } 0211 #endif 0212 printf("Processing %s\n", av[i]); 0213 if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS) 0214 { 0215 fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret)); 0216 continue; // no recycle b/c open file will recycle itself 0217 } 0218 0219 if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS) 0220 { 0221 fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret)); 0222 continue; 0223 } 0224 0225 // we should call dcraw_process before thumbnail extraction because for 0226 // some cameras (i.e. Kodak ones) white balance for thumbnail should be set 0227 // from main image settings 0228 0229 ret = RawProcessor.dcraw_process(); 0230 0231 if (LIBRAW_SUCCESS != ret) 0232 { 0233 fprintf(stderr, "Cannot do postprocessing on %s: %s\n", av[i], 0234 libraw_strerror(ret)); 0235 if (LIBRAW_FATAL_ERROR(ret)) 0236 continue; 0237 } 0238 libraw_processed_image_t *image = RawProcessor.dcraw_make_mem_image(&ret); 0239 if (image) 0240 { 0241 #ifdef USE_JPEG 0242 if(output_jpeg) 0243 write_jpeg(image, av[i], jpgqual); 0244 else 0245 #endif 0246 write_ppm(image, av[i]); 0247 LibRaw::dcraw_clear_mem(image); 0248 } 0249 else 0250 fprintf(stderr, "Cannot unpack %s to memory buffer: %s\n", av[i], 0251 libraw_strerror(ret)); 0252 0253 if (output_thumbs) 0254 { 0255 0256 if ((ret = RawProcessor.unpack_thumb()) != LIBRAW_SUCCESS) 0257 { 0258 fprintf(stderr, "Cannot unpack_thumb %s: %s\n", av[i], 0259 libraw_strerror(ret)); 0260 if (LIBRAW_FATAL_ERROR(ret)) 0261 continue; // skip to next file 0262 } 0263 else 0264 { 0265 libraw_processed_image_t *thumb = 0266 RawProcessor.dcraw_make_mem_thumb(&ret); 0267 if (thumb) 0268 { 0269 write_thumb(thumb, av[i]); 0270 LibRaw::dcraw_clear_mem(thumb); 0271 } 0272 else 0273 fprintf(stderr, 0274 "Cannot unpack thumbnail of %s to memory buffer: %s\n", av[i], 0275 libraw_strerror(ret)); 0276 } 0277 } 0278 0279 RawProcessor.recycle(); // just for show this call 0280 } 0281 return 0; 0282 }