3 * Copyright 2008-2009 Alex Tutubalin <lexa@lexa.ru>
4 * Created: Sat Mar 8 , 2008
6 * LibRaw C++ interface (implementation)
13 #include <netinet/in.h>
17 #define LIBRAW_LIBRARY_BUILD
18 #include "libraw/libraw.h"
24 void default_memory_callback(void *,const char *file
,const char *where
)
26 fprintf (stderr
,"%s: Out of memory in %s\n", file
?file
:"unknown file", where
);
29 void default_data_callback(void*,const char *file
, const int offset
)
32 fprintf (stderr
,"%s: Unexpected end of file\n", file
?file
:"unknown file");
34 fprintf (stderr
,"%s: data corrupted at %d\n",file
?file
:"unknown file",offset
);
36 const char *libraw_strerror(int e
)
38 enum LibRaw_errors errorcode
= (LibRaw_errors
)e
;
43 case LIBRAW_UNSPECIFIED_ERROR
:
44 return "Unspecified error";
45 case LIBRAW_FILE_UNSUPPORTED
:
46 return "Unsupported file format or not RAW file";
47 case LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE
:
48 return "Request for nonexisting image number";
49 case LIBRAW_OUT_OF_ORDER_CALL
:
50 return "Out of order call of libraw function";
51 case LIBRAW_NO_THUMBNAIL
:
52 return "No thumbnail in file";
53 case LIBRAW_UNSUPPORTED_THUMBNAIL
:
54 return "Unsupported thumbnail format";
55 case LIBRAW_CANNOT_ADDMASK
:
56 return "Cannot add masked pixels to resized image";
57 case LIBRAW_UNSUFFICIENT_MEMORY
:
58 return "Unsufficient memory";
59 case LIBRAW_DATA_ERROR
:
60 return "Corrupted data or unexpected EOF";
62 return "Input/output error";
63 case LIBRAW_CANCELLED_BY_CALLBACK
:
64 return "Cancelled by user callback";
66 return "Unknown error code";
75 const double LibRaw_constants::xyz_rgb
[3][3] =
77 { 0.412453, 0.357580, 0.180423 },
78 { 0.212671, 0.715160, 0.072169 },
79 { 0.019334, 0.119193, 0.950227 }
82 const float LibRaw_constants::d65_white
[3] = { 0.950456, 1, 1.088754 };
84 #define P1 imgdata.idata
85 #define S imgdata.sizes
86 #define O imgdata.params
87 #define C imgdata.color
88 #define M imgdata.masked_pixels
89 #define T imgdata.thumbnail
90 #define IO libraw_internal_data.internal_output_params
91 #define ID libraw_internal_data.internal_data
93 #define EXCEPTION_HANDLER(e) do{ \
94 fprintf(stderr,"Exception %d caught\n",e); \
97 case LIBRAW_EXCEPTION_ALLOC: \
99 return LIBRAW_UNSUFFICIENT_MEMORY; \
100 case LIBRAW_EXCEPTION_DECODE_RAW: \
101 case LIBRAW_EXCEPTION_DECODE_JPEG: \
103 return LIBRAW_DATA_ERROR; \
104 case LIBRAW_EXCEPTION_IO_EOF: \
105 case LIBRAW_EXCEPTION_IO_CORRUPT: \
107 return LIBRAW_IO_ERROR; \
108 case LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK:\
110 return LIBRAW_CANCELLED_BY_CALLBACK; \
112 return LIBRAW_UNSPECIFIED_ERROR; \
116 void LibRaw::derror()
118 if (!libraw_internal_data
.unpacker_data
.data_error
&& libraw_internal_data
.internal_data
.input
)
120 if (libraw_internal_data
.internal_data
.input
->eof())
122 if(callbacks
.data_cb
)(*callbacks
.data_cb
)(callbacks
.datacb_data
,
123 libraw_internal_data
.internal_data
.input
->fname(),-1);
124 throw LIBRAW_EXCEPTION_IO_EOF
;
128 if(callbacks
.data_cb
)(*callbacks
.data_cb
)(callbacks
.datacb_data
,
129 libraw_internal_data
.internal_data
.input
->fname(),
130 libraw_internal_data
.internal_data
.input
->tell());
131 throw LIBRAW_EXCEPTION_IO_CORRUPT
;
134 libraw_internal_data
.unpacker_data
.data_error
= 1;
136 LibRaw:: LibRaw(unsigned int flags
)
138 double aber
[4] = {1,1,1,1};
139 unsigned greybox
[4] = { 0, 0, UINT_MAX
, UINT_MAX
};
145 bzero(&imgdata
,sizeof(imgdata
));
146 bzero(&libraw_internal_data
,sizeof(libraw_internal_data
));
147 bzero(&callbacks
,sizeof(callbacks
));
148 callbacks
.mem_cb
= (flags
& LIBRAW_OPIONS_NO_MEMERR_CALLBACK
) ? NULL
: &default_memory_callback
;
149 callbacks
.data_cb
= (flags
& LIBRAW_OPIONS_NO_DATAERR_CALLBACK
)? NULL
: &default_data_callback
;
150 memmove(&imgdata
.params
.aber
,&aber
,sizeof(aber
));
151 memmove(&imgdata
.params
.greybox
,&greybox
,sizeof(greybox
));
153 imgdata
.params
.bright
=1;
154 imgdata
.params
.use_camera_matrix
=-1;
155 imgdata
.params
.user_flip
=-1;
156 imgdata
.params
.user_black
=-1;
157 imgdata
.params
.user_sat
=-1;
158 imgdata
.params
.user_qual
=-1;
159 imgdata
.params
.output_color
=1;
160 imgdata
.params
.output_bps
=8;
161 imgdata
.params
.use_fuji_rotate
=1;
162 imgdata
.parent_class
= this;
163 imgdata
.progress_flags
= 0;
164 tls
= new LibRaw_TLS
;
169 void* LibRaw:: malloc(size_t t
)
171 void *p
= memmgr
.malloc(t
);
174 void* LibRaw:: calloc(size_t n
,size_t t
)
176 void *p
= memmgr
.calloc(n
,t
);
179 void LibRaw:: free(void *p
)
185 int LibRaw:: fc (int row
, int col
)
187 static const char filter
[16][16] =
188 { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
189 { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
190 { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
191 { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
192 { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
193 { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
194 { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
195 { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
196 { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
197 { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
198 { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
199 { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
200 { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
201 { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
202 { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
203 { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
205 if (imgdata
.idata
.filters
!= 1) return FC(row
,col
);
206 return filter
[(row
+imgdata
.sizes
.top_margin
) & 15][(col
+imgdata
.sizes
.left_margin
) & 15];
209 void LibRaw:: recycle()
211 if(libraw_internal_data
.internal_data
.input
&& libraw_internal_data
.internal_data
.input_internal
)
213 delete libraw_internal_data
.internal_data
.input
;
214 libraw_internal_data
.internal_data
.input
= NULL
;
216 libraw_internal_data
.internal_data
.input_internal
= 0;
217 #define FREE(a) do { if(a) { free(a); a = NULL;} }while(0)
220 FREE(imgdata
.thumbnail
.thumb
);
221 FREE(libraw_internal_data
.internal_data
.meta_data
);
222 FREE(libraw_internal_data
.output_data
.histogram
);
223 FREE(libraw_internal_data
.output_data
.oprof
);
224 FREE(imgdata
.color
.profile
);
225 FREE(imgdata
.masked_pixels
.buffer
);
226 FREE(imgdata
.masked_pixels
.ph1_black
);
228 #define ZERO(a) bzero(&a,sizeof(a))
229 ZERO(imgdata
.masked_pixels
);
231 ZERO(libraw_internal_data
.internal_output_params
);
234 imgdata
.thumbnail
.tformat
= LIBRAW_THUMBNAIL_UNKNOWN
;
235 imgdata
.progress_flags
= 0;
240 const char * LibRaw::unpack_function_name()
242 if(!load_raw
) return "Function not set";
244 // sorted names order
245 if (load_raw
== &LibRaw::adobe_dng_load_raw_lj
) return "adobe_dng_load_raw_lj()";
246 if (load_raw
== &LibRaw::adobe_dng_load_raw_nc
) return "adobe_dng_load_raw_nc()";
247 if (load_raw
== &LibRaw::canon_600_load_raw
) return "canon_600_load_raw()";
249 if (load_raw
== &LibRaw::canon_a5_load_raw
) return "canon_a5_load_raw()";
250 if (load_raw
== &LibRaw::canon_compressed_load_raw
) return "canon_compressed_load_raw()";
251 if (load_raw
== &LibRaw::canon_sraw_load_raw
) return "canon_sraw_load_raw()";
253 if (load_raw
== &LibRaw::casio_qv5700_load_raw
) return "casio_qv5700_load_raw()";
254 if (load_raw
== &LibRaw::eight_bit_load_raw
) return "eight_bit_load_raw()";
255 if (load_raw
== &LibRaw::foveon_load_raw
) return "foveon_load_raw()";
256 if (load_raw
== &LibRaw::fuji_load_raw
) return "fuji_load_raw()";
258 if (load_raw
== &LibRaw::hasselblad_load_raw
) return "hasselblad_load_raw()";
259 if (load_raw
== &LibRaw::imacon_full_load_raw
) return "imacon_full_load_raw()";
260 if (load_raw
== &LibRaw::kodak_262_load_raw
) return "kodak_262_load_raw()";
262 if (load_raw
== &LibRaw::kodak_65000_load_raw
) return "kodak_65000_load_raw()";
263 if (load_raw
== &LibRaw::kodak_dc120_load_raw
) return "kodak_dc120_load_raw()";
264 if (load_raw
== &LibRaw::kodak_jpeg_load_raw
) return "kodak_jpeg_load_raw()";
266 if (load_raw
== &LibRaw::kodak_radc_load_raw
) return "kodak_radc_load_raw()";
267 if (load_raw
== &LibRaw::kodak_rgb_load_raw
) return "kodak_rgb_load_raw()";
268 if (load_raw
== &LibRaw::kodak_yrgb_load_raw
) return "kodak_yrgb_load_raw()";
269 if (load_raw
== &LibRaw::kodak_ycbcr_load_raw
) return "kodak_ycbcr_load_raw()";
271 if (load_raw
== &LibRaw::leaf_hdr_load_raw
) return "leaf_hdr_load_raw()";
272 if (load_raw
== &LibRaw::lossless_jpeg_load_raw
) return "lossless_jpeg_load_raw()";
273 if (load_raw
== &LibRaw::minolta_rd175_load_raw
) return "minolta_rd175_load_raw()";
275 if (load_raw
== &LibRaw::nikon_compressed_load_raw
) return "nikon_compressed_load_raw()";
276 if (load_raw
== &LibRaw::nikon_e900_load_raw
) return "nikon_e900_load_raw()";
277 if (load_raw
== &LibRaw::nokia_load_raw
) return "nokia_load_raw()";
279 if (load_raw
== &LibRaw::olympus_e300_load_raw
) return "olympus_e300_load_raw()";
280 if (load_raw
== &LibRaw::olympus_e410_load_raw
) return "olympus_e410_load_raw()";
281 if (load_raw
== &LibRaw::packed_12_load_raw
) return "packed_12_load_raw()";
282 if (load_raw
== &LibRaw::panasonic_load_raw
) return "panasonic_load_raw()";
284 if (load_raw
== &LibRaw::pentax_k10_load_raw
) return "pentax_k10_load_raw()";
285 if (load_raw
== &LibRaw::phase_one_load_raw
) return "phase_one_load_raw()";
286 if (load_raw
== &LibRaw::phase_one_load_raw_c
) return "phase_one_load_raw_c()";
288 if (load_raw
== &LibRaw::quicktake_100_load_raw
) return "quicktake_100_load_raw()";
289 if (load_raw
== &LibRaw::rollei_load_raw
) return "rollei_load_raw()";
290 if (load_raw
== &LibRaw::sinar_4shot_load_raw
) return "sinar_4shot_load_raw()";
292 if (load_raw
== &LibRaw::smal_v6_load_raw
) return "smal_v6_load_raw()";
293 if (load_raw
== &LibRaw::smal_v9_load_raw
) return "smal_v9_load_raw()";
294 if (load_raw
== &LibRaw::sony_load_raw
) return "sony_load_raw()";
295 if (load_raw
== &LibRaw::sony_arw_load_raw
) return "sony_arw_load_raw()";
297 if (load_raw
== &LibRaw::sony_arw2_load_raw
) return "sony_arw2_load_raw()";
298 if (load_raw
== &LibRaw::unpacked_load_raw
) return "unpacked_load_raw()";
301 return "Unknown unpack function";
305 void LibRaw:: merror (void *ptr
, const char *where
)
308 if(callbacks
.mem_cb
)(*callbacks
.mem_cb
)(callbacks
.memcb_data
,
309 libraw_internal_data
.internal_data
.input
310 ?libraw_internal_data
.internal_data
.input
->fname()
313 throw LIBRAW_EXCEPTION_ALLOC
;
316 ushort
* LibRaw::get_masked_pointer(int row
, int col
)
318 if(row
<0 || col
< 0) return NULL
;
319 if(!M
.buffer
) return NULL
;
320 if(row
< S
.top_margin
)
323 if(col
< S
.left_margin
)
325 return &(M
.tl
[row
*S
.left_margin
+col
]);
327 else if (col
< S
.left_margin
+ S
.width
)
329 int icol
= col
- S
.left_margin
;
330 return &(M
.top
[row
*S
.width
+icol
]);
332 else if (col
< S
.raw_width
)
334 int icol
= col
- S
.left_margin
- S
.width
;
335 return &(M
.tr
[row
*S
.right_margin
+icol
]);
338 return NULL
; // out of bounds
340 else if (row
< S
.top_margin
+ S
.height
)
342 //normal image height
343 int irow
= row
- S
.top_margin
;
344 if(col
< S
.left_margin
)
346 return &M
.left
[irow
*S
.left_margin
+ col
];
348 else if (col
< S
.left_margin
+ S
.width
)
353 else if (col
< S
.raw_width
)
355 int icol
= col
- S
.left_margin
- S
.width
;
356 return &M
.right
[irow
*S
.right_margin
+icol
];
359 return NULL
; // out of bounds
361 else if (row
< S
.raw_height
)
363 int irow
= row
- S
.top_margin
- S
.height
;
365 if(col
< S
.left_margin
)
367 return &M
.bl
[irow
*S
.left_margin
+col
];
369 else if (col
< S
.left_margin
+ S
.width
)
371 int icol
= col
- S
.left_margin
;
372 return &M
.bottom
[irow
*S
.width
+ icol
];
374 else if (col
< S
.raw_width
)
376 int icol
= col
- S
.left_margin
- S
.width
;
377 return &M
.br
[irow
*S
.right_margin
+ icol
];
380 return NULL
; // out of bounds
391 void LibRaw:: init_masked_ptrs()
393 if(!M
.buffer
) return;
397 M
.top
= M
.tl
+(S
.top_margin
*S
.left_margin
);
398 M
.tr
= M
.top
+ (S
.top_margin
*S
.width
);
401 M
.left
= M
.tr
+ (S
.top_margin
* S
.right_margin
);
402 M
.right
= M
.left
+ (S
.left_margin
* S
.height
);
405 M
.bl
= M
.right
+ (S
.right_margin
* S
.height
);
406 M
.bottom
= M
.bl
+ (S
.left_margin
* S
.bottom_margin
);
407 M
.br
= M
.bottom
+ (S
.width
* S
.bottom_margin
);
411 int LibRaw::add_masked_borders_to_bitmap()
413 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
414 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW
);
416 if(S
.width
!= S
.iwidth
|| S
.height
!=S
.iheight
)
417 return LIBRAW_CANNOT_ADDMASK
;
419 if(P1
.is_foveon
|| !P1
.filters
)
420 return LIBRAW_CANNOT_ADDMASK
;
423 return LIBRAW_OUT_OF_ORDER_CALL
;
425 if(S
.raw_width
< S
.width
|| S
.raw_height
< S
.height
)
426 return LIBRAW_SUCCESS
; // nothing to do or already called
428 if(S
.width
== S
.raw_width
&& S
.height
== S
.raw_height
)
429 return LIBRAW_SUCCESS
; // nothing to do or already called
431 ushort (*newimage
)[4];
433 newimage
= (ushort (*)[4]) calloc (S
.raw_height
*S
.raw_width
, sizeof (*newimage
));
434 merror (newimage
, "add_masked_borders_to_bitmap()");
438 for (r
=0; r
<S
.top_margin
;r
++)
439 for(c
=0;c
<S
.raw_width
;c
++)
441 ushort
*p
= get_masked_pointer(r
,c
);
443 newimage
[r
*S
.raw_width
+c
][FC(r
,c
)] = *p
;
446 for (r
=S
.top_margin
; r
<S
.top_margin
+S
.height
;r
++)
448 int row
= r
-S
.top_margin
;
449 for(c
=0;c
<S
.left_margin
;c
++)
451 ushort
*p
= get_masked_pointer(r
,c
);
453 newimage
[r
*S
.raw_width
+c
][FC(r
,c
)] = *p
;
455 for(c
=S
.left_margin
; c
<S
.left_margin
+S
.iwidth
;c
++)
457 int col
= c
- S
.left_margin
;
458 newimage
[r
*S
.raw_width
+c
][FC(r
,c
)] = imgdata
.image
[row
*S
.iwidth
+col
][FC(row
,col
)];
460 for(c
=S
.left_margin
+S
.iwidth
;c
<S
.raw_width
;c
++)
462 ushort
*p
= get_masked_pointer(r
,c
);
464 newimage
[r
*S
.raw_width
+c
][FC(r
,c
)] = *p
;
468 for (r
=S
.top_margin
+S
.height
; r
<S
.raw_height
;r
++)
469 for(c
=0;c
<S
.raw_width
;c
++)
471 ushort
*p
= get_masked_pointer(r
,c
);
473 newimage
[r
*S
.raw_width
+c
][FC(r
,c
)] = *p
;
476 imgdata
.image
=newimage
;
477 S
.iwidth
= S
.width
= S
.raw_width
;
478 S
.iheight
= S
.height
= S
.raw_height
;
479 return LIBRAW_SUCCESS
;
482 int LibRaw::open_file(const char *fname
)
484 // this stream will close on recycle()
485 LibRaw_file_datastream
*stream
= new LibRaw_file_datastream(fname
);
489 return LIBRAW_IO_ERROR
;
491 ID
.input_internal
= 0; // preserve from deletion on error
492 int ret
= open_datastream(stream
);
493 if (ret
== LIBRAW_SUCCESS
)
495 ID
.input_internal
=1 ; // flag to delete datastream on recycle
500 ID
.input_internal
= 0;
505 int LibRaw::open_buffer(void *buffer
, size_t size
)
507 // this stream will close on recycle()
508 if(!buffer
|| buffer
==(void*)-1)
509 return LIBRAW_IO_ERROR
;
511 LibRaw_buffer_datastream
*stream
= new LibRaw_buffer_datastream(buffer
,size
);
515 return LIBRAW_IO_ERROR
;
517 ID
.input_internal
= 0; // preserve from deletion on error
518 int ret
= open_datastream(stream
);
519 if (ret
== LIBRAW_SUCCESS
)
521 ID
.input_internal
=1 ; // flag to delete datastream on recycle
526 ID
.input_internal
= 0;
532 int LibRaw::open_datastream(LibRaw_abstract_datastream
*stream
)
538 return LIBRAW_IO_ERROR
;
543 SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN
);
545 if (O
.use_camera_matrix
< 0)
546 O
.use_camera_matrix
= O
.use_camera_wb
;
553 IO
.fheight
= S
.height
;
554 S
.iwidth
= S
.width
= IO
.fuji_width
<< !libraw_internal_data
.unpacker_data
.fuji_layout
;
555 S
.iheight
= S
.height
= S
.raw_height
;
556 S
.raw_height
+= 2*S
.top_margin
;
559 int saved_raw_width
= S
.raw_width
;
560 int saved_width
= S
.width
;
561 // from packed_12_load_raw
562 if ((load_raw
== &LibRaw:: packed_12_load_raw
) && (S
.raw_width
* 2 >= S
.width
* 3))
564 // raw_width is in bytes!
565 S
.raw_width
= S
.raw_width
* 2 / 3;
567 else if (S
.pixel_aspect
< 0.95 || S
.pixel_aspect
> 1.05)
569 S
.width
*=S
.pixel_aspect
;
572 if(S
.raw_width
>S
.width
+ S
.left_margin
)
573 S
.right_margin
= S
.raw_width
- S
.width
- S
.left_margin
;
575 if(S
.raw_height
> S
.height
+ S
.top_margin
)
576 S
.bottom_margin
= S
.raw_height
- S
.height
- S
.top_margin
;
578 S
.raw_width
= saved_raw_width
;
579 S
.width
= saved_width
;
583 if(C
.profile
) free(C
.profile
);
584 C
.profile
= malloc(C
.profile_length
);
585 merror(C
.profile
,"LibRaw::open_file()");
586 ID
.input
->seek(ID
.profile_offset
,SEEK_SET
);
587 ID
.input
->read(C
.profile
,C
.profile_length
,1);
590 SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY
);
592 catch ( LibRaw_exceptions err
) {
593 EXCEPTION_HANDLER(err
);
597 return LIBRAW_FILE_UNSUPPORTED
;
599 if (O
.user_flip
>= 0)
600 S
.flip
= O
.user_flip
;
602 switch ((S
.flip
+3600) % 360)
604 case 270: S
.flip
= 5; break;
605 case 180: S
.flip
= 3; break;
606 case 90: S
.flip
= 6; break;
609 write_fun
= &LibRaw::write_ppm_tiff
;
611 if (load_raw
== &LibRaw::kodak_ycbcr_load_raw
)
613 S
.height
+= S
.height
& 1;
614 S
.width
+= S
.width
& 1;
617 IO
.shrink
= P1
.filters
&& (O
.half_size
|| O
.threshold
|| O
.aber
[0] != 1 || O
.aber
[2] != 1);
618 S
.iheight
= (S
.height
+ IO
.shrink
) >> IO
.shrink
;
619 S
.iwidth
= (S
.width
+ IO
.shrink
) >> IO
.shrink
;
621 SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST
);
624 return LIBRAW_SUCCESS
;
627 int LibRaw::unpack(void)
629 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_LOAD_RAW
);
630 CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY
);
633 RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW
,0,2);
634 if (O
.shot_select
>= P1
.raw_count
)
635 return LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE
;
638 return LIBRAW_UNSPECIFIED_ERROR
;
640 if (O
.use_camera_matrix
&& C
.cmatrix
[0][0] > 0.25)
642 memcpy (C
.rgb_cam
, C
.cmatrix
, sizeof (C
.cmatrix
));
645 // already allocated ?
646 if(imgdata
.image
) free(imgdata
.image
);
648 imgdata
.image
= (ushort (*)[4]) calloc (S
.iheight
*S
.iwidth
, sizeof (*imgdata
.image
));
649 merror (imgdata
.image
, "unpack()");
652 if(S
.top_margin
|| S
.left_margin
|| S
.right_margin
|| S
.bottom_margin
)
654 unsigned sz
= S
.raw_height
*(S
.left_margin
+S
.right_margin
)
655 + S
.width
*(S
.top_margin
+S
.bottom_margin
);
656 imgdata
.masked_pixels
.buffer
= (ushort
*) calloc(sz
, sizeof(ushort
));
657 merror (imgdata
.masked_pixels
.buffer
, "unpack()");
660 if (libraw_internal_data
.unpacker_data
.meta_length
)
662 libraw_internal_data
.internal_data
.meta_data
=
663 (char *) malloc (libraw_internal_data
.unpacker_data
.meta_length
);
664 merror (libraw_internal_data
.internal_data
.meta_data
, "LibRaw::unpack()");
666 ID
.input
->seek(libraw_internal_data
.unpacker_data
.data_offset
, SEEK_SET
);
667 // foveon_load_raw produces different data for document_mode, we'll
668 // deal with it in dcraw_document_mode_processing
669 int save_document_mode
= O
.document_mode
;
672 if(!own_filtering_supported() && (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
))
673 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC_BIT
; // turn on black and zeroes filtering
677 O
.document_mode
= save_document_mode
;
679 if (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
)
680 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC
; // restore automated mode
682 SET_PROC_FLAG(LIBRAW_PROGRESS_LOAD_RAW
);
683 RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW
,1,2);
687 catch ( LibRaw_exceptions err
) {
688 EXCEPTION_HANDLER(err
);
692 int LibRaw::dcraw_document_mode_processing(void)
694 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
695 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW
);
702 if(!own_filtering_supported() && (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
))
703 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC_BIT
; // turn on black and zeroes filtering
708 // filter image data for foveon document mode
709 short *iptr
= (short *)imgdata
.image
;
710 for (int i
=0; i
< S
.height
*S
.width
*4; i
++)
712 if ((short) iptr
[i
] < 0)
715 SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
);
718 O
.use_fuji_rotate
= 0;
719 if (!(O
.filtering_mode
& LIBRAW_FILTERING_NOZEROES
) && IO
.zero_is_bad
)
722 SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES
);
726 bad_pixels(O
.bad_pixels
);
727 SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS
);
731 subtract (O
.dark_frame
);
732 SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME
);
734 if(O
.filtering_mode
& LIBRAW_FILTERING_NOBLACKS
)
737 if (O
.user_black
>= 0)
738 C
.black
= O
.user_black
;
741 C
.maximum
= O
.user_sat
;
744 SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
746 if (libraw_internal_data
.internal_output_params
.mix_green
)
749 for (P1
.colors
=3, i
=0; i
< S
.height
*S
.width
; i
++)
750 imgdata
.image
[i
][1] = (imgdata
.image
[i
][1] + imgdata
.image
[i
][3]) >> 1;
752 SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN
);
754 if (!P1
.is_foveon
&& P1
.colors
== 3)
756 SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER
);
758 if (!P1
.is_foveon
&& O
.highlight
== 2)
761 if (!P1
.is_foveon
&& O
.highlight
> 2)
762 recover_highlights();
763 SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS
);
765 if (O
.use_fuji_rotate
)
767 SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE
);
771 apply_profile(O
.camera_profile
,O
.output_profile
);
772 SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE
);
775 if(!libraw_internal_data
.output_data
.histogram
)
777 libraw_internal_data
.output_data
.histogram
= (int (*)[LIBRAW_HISTOGRAM_SIZE
]) malloc(sizeof(*libraw_internal_data
.output_data
.histogram
)*4);
778 merror(libraw_internal_data
.output_data
.histogram
,"LibRaw::dcraw_document_mode_processing()");
781 SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB
);
783 if (O
.use_fuji_rotate
)
785 SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH
);
787 if (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
)
788 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC
; // restore automated mode
792 catch ( LibRaw_exceptions err
) {
793 EXCEPTION_HANDLER(err
);
799 #define FORC(cnt) for (c=0; c < cnt; c++)
800 #define FORCC FORC(ret->colors)
801 #define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
803 libraw_processed_image_t
* LibRaw::dcraw_make_mem_thumb(int *errcode
)
809 if(errcode
) *errcode
= LIBRAW_NO_THUMBNAIL
;
813 if(errcode
) *errcode
= LIBRAW_OUT_OF_ORDER_CALL
;
818 if (T
.tformat
== LIBRAW_THUMBNAIL_BITMAP
)
820 libraw_processed_image_t
* ret
=
821 (libraw_processed_image_t
*)::malloc(sizeof(libraw_processed_image_t
)+T
.tlength
);
825 if(errcode
) *errcode
= ENOMEM
;
829 bzero(ret
,sizeof(libraw_processed_image_t
));
830 ret
->type
= LIBRAW_IMAGE_BITMAP
;
831 ret
->height
= T
.theight
;
832 ret
->width
= T
.twidth
;
835 ret
->gamma_corrected
= 1;
836 ret
->data_size
= T
.tlength
;
837 memmove(ret
->data
,T
.thumb
,T
.tlength
);
838 if(errcode
) *errcode
= 0;
841 else if (T
.tformat
== LIBRAW_THUMBNAIL_JPEG
)
845 if(strcmp(T
.thumb
+6,"Exif")) mk_exif
= 1;
847 int dsize
= T
.tlength
+ mk_exif
* (sizeof(exif
)+sizeof(tiff_hdr
));
849 libraw_processed_image_t
* ret
=
850 (libraw_processed_image_t
*)::malloc(sizeof(libraw_processed_image_t
)+dsize
);
854 if(errcode
) *errcode
= ENOMEM
;
858 bzero(ret
,sizeof(libraw_processed_image_t
));
860 ret
->type
= LIBRAW_IMAGE_JPEG
;
861 ret
->data_size
= dsize
;
868 memcpy (exif
, "\xff\xe1 Exif\0\0", 10);
869 exif
[1] = htons (8 + sizeof th
);
870 memmove(ret
->data
+2,exif
,sizeof(exif
));
872 memmove(ret
->data
+(2+sizeof(exif
)),&th
,sizeof(th
));
873 memmove(ret
->data
+(2+sizeof(exif
)+sizeof(th
)),T
.thumb
+2,T
.tlength
-2);
877 memmove(ret
->data
+2,T
.thumb
+2,T
.tlength
-2);
879 if(errcode
) *errcode
= 0;
885 if(errcode
) *errcode
= LIBRAW_UNSUPPORTED_THUMBNAIL
;
893 libraw_processed_image_t
*LibRaw::dcraw_make_mem_image(int *errcode
)
895 if((imgdata
.progress_flags
& LIBRAW_PROGRESS_THUMB_MASK
) < LIBRAW_PROGRESS_PRE_INTERPOLATE
)
897 if(errcode
) *errcode
= LIBRAW_OUT_OF_ORDER_CALL
;
901 if(!libraw_internal_data
.output_data
.histogram
)
903 libraw_internal_data
.output_data
.histogram
=
904 (int (*)[LIBRAW_HISTOGRAM_SIZE
]) malloc(sizeof(*libraw_internal_data
.output_data
.histogram
)*4);
905 merror(libraw_internal_data
.output_data
.histogram
,"LibRaw::dcraw_make_mem_image()");
908 unsigned ds
= S
.height
* S
.width
* (O
.output_bps
/8) * P1
.colors
;
909 libraw_processed_image_t
*ret
= (libraw_processed_image_t
*)::malloc(sizeof(libraw_processed_image_t
)+ds
);
912 if(errcode
) *errcode
= ENOMEM
;
915 bzero(ret
,sizeof(libraw_processed_image_t
));
918 int s_iheight
= S
.iheight
;
919 int s_iwidth
= S
.iwidth
;
920 int s_width
= S
.width
;
921 int s_hwight
= S
.height
;
923 S
.iheight
= S
.height
;
927 if (S
.flip
& 4) SWAP(S
.height
,S
.width
);
930 ret
->type
= LIBRAW_IMAGE_BITMAP
;
931 ret
->height
= S
.height
;
932 ret
->width
= S
.width
;
933 ret
->colors
= P1
.colors
;
934 ret
->bits
= O
.output_bps
;
935 ret
->gamma_corrected
= (O
.output_bps
== 8)?1:O
.gamma_16bit
;
939 // Cut'n'paste from write_tiff_ppm, should be generalized later
940 uchar
*bufp
= ret
->data
;
942 ushort
*ppm2
,lut16
[0x10000];
943 int c
, row
, col
, soff
, rstep
, cstep
;
946 if (ret
->bits
== 8 || ret
->gamma_corrected
) gamma_lut (lut16
);
947 soff
= flip_index (0, 0);
948 cstep
= flip_index (0, 1) - soff
;
949 rstep
= flip_index (1, 0) - flip_index (0, S
.width
);
952 for (row
=0; row
< ret
->height
; row
++, soff
+= rstep
)
954 ppm2
= (ushort
*) (ppm
= bufp
);
955 for (col
=0; col
< ret
->width
; col
++, soff
+= cstep
)
957 FORCC ppm
[col
*ret
->colors
+c
] = lut16
[imgdata
.image
[soff
][c
]]/256;
958 else if(ret
->gamma_corrected
)
959 FORCC ppm2
[col
*ret
->colors
+c
] = lut16
[imgdata
.image
[soff
][c
]];
961 FORCC ppm2
[col
*ret
->colors
+c
] = imgdata
.image
[soff
][c
];
962 bufp
+=ret
->colors
*(ret
->bits
/8)*ret
->width
;
964 if(errcode
) *errcode
= 0;
966 S
.iheight
= s_iheight
;
980 int LibRaw::dcraw_ppm_tiff_writer(const char *filename
)
982 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW
);
985 return LIBRAW_OUT_OF_ORDER_CALL
;
989 FILE *f
= fopen(filename
,"wb");
995 if(!libraw_internal_data
.output_data
.histogram
)
997 libraw_internal_data
.output_data
.histogram
=
998 (int (*)[LIBRAW_HISTOGRAM_SIZE
]) malloc(sizeof(*libraw_internal_data
.output_data
.histogram
)*4);
999 merror(libraw_internal_data
.output_data
.histogram
,"LibRaw::dcraw_ppm_tiff_writer()");
1002 SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP
);
1006 catch ( LibRaw_exceptions err
) {
1008 EXCEPTION_HANDLER(err
);
1012 void LibRaw::kodak_thumb_loader()
1014 // some kodak cameras
1015 ushort s_height
= S
.height
, s_width
= S
.width
,s_iwidth
= S
.iwidth
,s_iheight
=S
.iheight
;
1016 int s_colors
= P1
.colors
;
1017 unsigned s_filters
= P1
.filters
;
1018 ushort (*s_image
)[4] = imgdata
.image
;
1021 S
.height
= T
.theight
;
1025 if (thumb_load_raw
== &CLASS kodak_ycbcr_load_raw
)
1027 S
.height
+= S
.height
& 1;
1028 S
.width
+= S
.width
& 1;
1031 imgdata
.image
= (ushort (*)[4]) calloc (S
.iheight
*S
.iwidth
, sizeof (*imgdata
.image
));
1032 merror (imgdata
.image
, "LibRaw::kodak_thumb_loader()");
1034 ID
.input
->seek(ID
.toffset
, SEEK_SET
);
1035 // read kodak thumbnail into T.image[]
1036 (this->*thumb_load_raw
)();
1038 // copy-n-paste from image pipe
1039 #define MIN(a,b) ((a) < (b) ? (a) : (b))
1040 #define MAX(a,b) ((a) > (b) ? (a) : (b))
1041 #define LIM(x,min,max) MAX(min,MIN(x,max))
1042 #define CLIP(x) LIM(x,0,65535)
1043 #define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
1045 // from scale_colors
1050 for (dmax
=DBL_MAX
, c
=0; c
< 3; c
++)
1051 if (dmax
> C
.pre_mul
[c
])
1052 dmax
= C
.pre_mul
[c
];
1054 for( c
=0; c
< 3; c
++)
1055 scale_mul
[c
] = (C
.pre_mul
[c
] / dmax
) * 65535.0 / C
.maximum
;
1056 scale_mul
[3] = scale_mul
[1];
1058 size_t size
= S
.height
* S
.width
;
1059 for (int i
=0; i
< size
*4 ; i
++)
1061 val
= imgdata
.image
[0][i
];
1063 val
*= scale_mul
[i
& 3];
1064 imgdata
.image
[0][i
] = CLIP(val
);
1068 // from convert_to_rgb
1072 int (*t_hist
)[LIBRAW_HISTOGRAM_SIZE
] = (int (*)[LIBRAW_HISTOGRAM_SIZE
]) calloc(sizeof(*t_hist
),4);
1073 merror (t_hist
, "LibRaw::kodak_thumb_loader()");
1078 {2.81761312, -1.98369181, 0.166078627, 0},
1079 {-0.111855984, 1.73688626, -0.625030339, 0},
1080 {-0.0379119813, -0.891268849, 1.92918086, 0}
1083 for (img
=imgdata
.image
[0], row
=0; row
< S
.height
; row
++)
1084 for (col
=0; col
< S
.width
; col
++, img
+=4)
1086 out
[0] = out
[1] = out
[2] = 0;
1087 for(int c
=0;c
<3;c
++)
1089 out
[0] += out_cam
[0][c
] * img
[c
];
1090 out
[1] += out_cam
[1][c
] * img
[c
];
1091 out
[2] += out_cam
[2][c
] * img
[c
];
1093 for(int c
=0; c
<3; c
++)
1094 img
[c
] = CLIP((int) out
[c
]);
1095 for(int c
=0; c
<P1
.colors
;c
++)
1096 t_hist
[c
][img
[c
] >> 3]++;
1101 int (*save_hist
)[LIBRAW_HISTOGRAM_SIZE
] = libraw_internal_data
.output_data
.histogram
;
1102 libraw_internal_data
.output_data
.histogram
= t_hist
;
1104 ushort
*lut16
= (ushort
*)calloc(0x10000,sizeof(ushort
));
1105 merror(lut16
,"LibRaw::kodak_thumb_loader()");
1108 libraw_internal_data
.output_data
.histogram
= save_hist
;
1112 // from write_ppm_tiff - copy pixels into bitmap
1114 S
.iheight
= S
.height
;
1116 if (S
.flip
& 4) SWAP(S
.height
,S
.width
);
1118 if(T
.thumb
) free(T
.thumb
);
1119 T
.thumb
= (char*) calloc (S
.width
* S
.height
, P1
.colors
);
1120 merror (T
.thumb
, "LibRaw::kodak_thumb_loader()");
1121 T
.tlength
= S
.width
* S
.height
* P1
.colors
;
1123 // from write_tiff_ppm
1125 int soff
= flip_index (0, 0);
1126 int cstep
= flip_index (0, 1) - soff
;
1127 int rstep
= flip_index (1, 0) - flip_index (0, S
.width
);
1129 for (int row
=0; row
< S
.height
; row
++, soff
+= rstep
)
1131 char *ppm
= T
.thumb
+ row
*S
.width
*P1
.colors
;
1132 for (int col
=0; col
< S
.width
; col
++, soff
+= cstep
)
1133 for(int c
= 0; c
< P1
.colors
; c
++)
1134 ppm
[col
*P1
.colors
+c
] = lut16
[imgdata
.image
[soff
][c
]]/256;
1138 // restore variables
1139 free(imgdata
.image
);
1140 imgdata
.image
= s_image
;
1145 S
.iwidth
= s_iwidth
;
1146 S
.iheight
= s_iheight
;
1148 T
.theight
= S
.height
;
1149 S
.height
= s_height
;
1151 T
.tcolors
= P1
.colors
;
1152 P1
.colors
= s_colors
;
1154 P1
.filters
= s_filters
;
1163 void LibRaw::foveon_thumb_loader (void)
1165 unsigned bwide
, row
, col
, bitbuf
=0, bit
=1, c
, i
;
1166 struct decode
*dindex
;
1169 if(T
.thumb
) free(T
.thumb
);
1175 if (bwide
< T
.twidth
*3) return;
1176 T
.thumb
= (char*)malloc(3*T
.twidth
* T
.theight
);
1177 merror (T
.thumb
, "foveon_thumb()");
1178 char *buf
= (char*)malloc(bwide
);
1179 merror (buf
, "foveon_thumb()");
1180 for (row
=0; row
< T
.theight
; row
++)
1182 ID
.input
->read(buf
, 1, bwide
);
1183 memmove(T
.thumb
+(row
*T
.twidth
*3),buf
,T
.twidth
*3);
1186 T
.tlength
= 3*T
.twidth
* T
.theight
;
1187 T
.tformat
= LIBRAW_THUMBNAIL_BITMAP
;
1192 foveon_decoder (256, 0);
1193 T
.thumb
= (char*)malloc(3*T
.twidth
* T
.theight
);
1194 char *bufp
= T
.thumb
;
1195 merror (T
.thumb
, "foveon_thumb()");
1196 for (row
=0; row
< T
.theight
; row
++)
1198 memset (pred
, 0, sizeof pred
);
1200 for (bit
=col
=0; col
< T
.twidth
; col
++)
1203 for (dindex
=first_decode
; dindex
->branch
[0]; )
1205 if ((bit
= (bit
-1) & 31) == 31)
1206 for (i
=0; i
< 4; i
++)
1207 bitbuf
= (bitbuf
<< 8) + ID
.input
->get_char();
1208 dindex
= dindex
->branch
[bitbuf
>> bit
& 1];
1210 pred
[c
] += dindex
->leaf
;
1214 T
.tformat
= LIBRAW_THUMBNAIL_BITMAP
;
1215 T
.tlength
= 3*T
.twidth
* T
.theight
;
1221 // Äîñòà åò thumbnail èç ôà éëà , ñòà âèò thumb_format â ñîîòâåòñòâèè ñ ôîðìà òîì
1222 int LibRaw::unpack_thumb(void)
1224 CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY
);
1225 CHECK_ORDER_BIT(LIBRAW_PROGRESS_THUMB_LOAD
);
1230 return LIBRAW_NO_THUMBNAIL
;
1232 else if (thumb_load_raw
)
1234 kodak_thumb_loader();
1235 T
.tformat
= LIBRAW_THUMBNAIL_BITMAP
;
1236 SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD
);
1241 ID
.input
->seek(ID
.toffset
, SEEK_SET
);
1242 if ( write_thumb
== &LibRaw::jpeg_thumb
)
1244 if(T
.thumb
) free(T
.thumb
);
1245 T
.thumb
= (char *) malloc (T
.tlength
);
1246 merror (T
.thumb
, "jpeg_thumb()");
1247 ID
.input
->read (T
.thumb
, 1, T
.tlength
);
1249 T
.tformat
= LIBRAW_THUMBNAIL_JPEG
;
1250 SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD
);
1253 else if (write_thumb
== &LibRaw::ppm_thumb
)
1255 T
.tlength
= T
.twidth
* T
.theight
*3;
1256 if(T
.thumb
) free(T
.thumb
);
1258 T
.thumb
= (char *) malloc (T
.tlength
);
1259 merror (T
.thumb
, "ppm_thumb()");
1261 ID
.input
->read(T
.thumb
, 1, T
.tlength
);
1263 T
.tformat
= LIBRAW_THUMBNAIL_BITMAP
;
1264 SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD
);
1268 else if (write_thumb
== &LibRaw::foveon_thumb
)
1270 foveon_thumb_loader();
1271 // may return with error, so format is set in
1272 // foveon thumb loader itself
1273 SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD
);
1276 // else if -- all other write_thumb cases!
1279 return LIBRAW_UNSUPPORTED_THUMBNAIL
;
1283 return LIBRAW_UNSUPPORTED_THUMBNAIL
;
1285 catch ( LibRaw_exceptions err
) {
1286 EXCEPTION_HANDLER(err
);
1291 int LibRaw::dcraw_thumb_writer(const char *fname
)
1293 // CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD);
1298 FILE *tfp
= fopen(fname
,"wb");
1306 return LIBRAW_OUT_OF_ORDER_CALL
;
1312 case LIBRAW_THUMBNAIL_JPEG
:
1313 jpeg_thumb_writer (tfp
,T
.thumb
,T
.tlength
);
1315 case LIBRAW_THUMBNAIL_BITMAP
:
1316 fprintf (tfp
, "P6\n%d %d\n255\n", T
.twidth
, T
.theight
);
1317 fwrite (T
.thumb
, 1, T
.tlength
, tfp
);
1321 return LIBRAW_UNSUPPORTED_THUMBNAIL
;
1326 catch ( LibRaw_exceptions err
) {
1328 EXCEPTION_HANDLER(err
);
1332 int LibRaw::adjust_sizes_info_only(void)
1334 CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY
);
1335 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_FUJI_ROTATE
);
1336 if (O
.use_fuji_rotate
)
1340 // restore saved values
1343 S
.height
= IO
.fheight
;
1344 S
.width
= IO
.fwidth
;
1345 S
.iheight
= (S
.height
+ IO
.shrink
) >> IO
.shrink
;
1346 S
.iwidth
= (S
.width
+ IO
.shrink
) >> IO
.shrink
;
1347 S
.raw_height
-= 2*S
.top_margin
;
1348 IO
.fheight
= IO
.fwidth
= 0; // prevent repeated calls
1351 IO
.fuji_width
= (IO
.fuji_width
- 1 + IO
.shrink
) >> IO
.shrink
;
1352 S
.iwidth
= (ushort
)(IO
.fuji_width
/ sqrt(0.5));
1353 S
.iheight
= (ushort
)( (S
.iheight
- IO
.fuji_width
) / sqrt(0.5));
1357 if (S
.pixel_aspect
< 1) S
.iheight
= (ushort
)( S
.iheight
/ S
.pixel_aspect
+ 0.5);
1358 if (S
.pixel_aspect
> 1) S
.iwidth
= (ushort
) (S
.iwidth
* S
.pixel_aspect
+ 0.5);
1361 SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE
);
1364 unsigned short t
= S
.iheight
;
1367 SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP
);
1372 int LibRaw::rotate_fuji_raw(void)
1374 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW
);
1375 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
1378 if(!IO
.fwidth
) return LIBRAW_SUCCESS
;
1380 ushort (*newimage
)[4];
1381 ushort fiwidth
,fiheight
;
1383 fiheight
= (IO
.fheight
+ IO
.shrink
) >> IO
.shrink
;
1384 fiwidth
= (IO
.fwidth
+ IO
.shrink
) >> IO
.shrink
;
1386 newimage
= (ushort (*)[4]) calloc (fiheight
*fiwidth
, sizeof (*newimage
));
1387 merror(newimage
,"rotate_fuji_raw()");
1388 for(row
=0;row
<S
.height
;row
++)
1390 for(col
=0;col
<S
.width
;col
++)
1393 if (libraw_internal_data
.unpacker_data
.fuji_layout
) {
1394 r
= IO
.fuji_width
- 1 - col
+ (row
>> 1);
1395 c
= col
+ ((row
+1) >> 1);
1397 r
= IO
.fuji_width
- 1 + row
- (col
>> 1);
1398 c
= row
+ ((col
+1) >> 1);
1400 newimage
[((r
) >> IO
.shrink
)*fiwidth
+ ((c
) >> IO
.shrink
)][FC(r
,c
)] =
1401 imgdata
.image
[((row
) >> IO
.shrink
)*S
.iwidth
+ ((col
) >> IO
.shrink
)][FC(row
,col
)];
1404 // restore fuji sizes!
1405 S
.height
= IO
.fheight
;
1406 S
.width
= IO
.fwidth
;
1407 S
.iheight
= (S
.height
+ IO
.shrink
) >> IO
.shrink
;
1408 S
.iwidth
= (S
.width
+ IO
.shrink
) >> IO
.shrink
;
1409 S
.raw_height
-= 2*S
.top_margin
;
1410 IO
.fheight
= IO
.fwidth
= 0; // prevent repeated calls
1412 free(imgdata
.image
);
1413 imgdata
.image
= newimage
;
1414 return LIBRAW_SUCCESS
;
1419 int LibRaw::dcraw_process(void)
1424 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW
);
1425 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
1433 if(!own_filtering_supported() && (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
))
1434 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC_BIT
; // turn on black and zeroes filtering
1437 O
.four_color_rgb
= 1;
1439 if (!(O
.filtering_mode
& LIBRAW_FILTERING_NOZEROES
) && IO
.zero_is_bad
)
1442 SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES
);
1446 bad_pixels(O
.bad_pixels
);
1447 SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS
);
1451 subtract (O
.dark_frame
);
1452 SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME
);
1455 quality
= 2 + !IO
.fuji_width
;
1457 if(O
.filtering_mode
& LIBRAW_FILTERING_NOBLACKS
)
1460 if (O
.user_qual
>= 0) quality
= O
.user_qual
;
1461 if (O
.user_black
>= 0) C
.black
= O
.user_black
;
1462 if (O
.user_sat
> 0) C
.maximum
= O
.user_sat
;
1464 if (P1
.is_foveon
&& !O
.document_mode
)
1466 foveon_interpolate();
1467 SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
);
1470 if (!P1
.is_foveon
&& O
.document_mode
< 2)
1473 SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS
);
1477 SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
1479 if (P1
.filters
&& !O
.document_mode
)
1483 else if (quality
== 1 || P1
.colors
> 3)
1485 else if (quality
== 2)
1489 SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE
);
1493 for (P1
.colors
=3, i
=0; i
< S
.height
* S
.width
; i
++)
1494 imgdata
.image
[i
][1] = (imgdata
.image
[i
][1] + imgdata
.image
[i
][3]) >> 1;
1495 SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN
);
1503 SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER
);
1506 if (O
.highlight
== 2)
1509 SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS
);
1512 if (O
.highlight
> 2)
1514 recover_highlights();
1515 SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS
);
1518 if (O
.use_fuji_rotate
)
1521 SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE
);
1524 if(!libraw_internal_data
.output_data
.histogram
)
1526 libraw_internal_data
.output_data
.histogram
= (int (*)[LIBRAW_HISTOGRAM_SIZE
]) malloc(sizeof(*libraw_internal_data
.output_data
.histogram
)*4);
1527 merror(libraw_internal_data
.output_data
.histogram
,"LibRaw::dcraw_process()");
1530 if(O
.camera_profile
)
1532 apply_profile(O
.camera_profile
,O
.output_profile
);
1533 SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE
);
1538 SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB
);
1540 if (O
.use_fuji_rotate
)
1543 SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH
);
1545 if (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
)
1546 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC
; // restore automated mode
1549 catch ( LibRaw_exceptions err
) {
1550 EXCEPTION_HANDLER(err
);
1554 // Supported cameras:
1555 static const char *static_camera_list
[] =
1557 "Adobe Digital Negative (DNG)",
1558 "Apple QuickTake 100",
1559 "Apple QuickTake 150",
1560 "Apple QuickTake 200",
1566 "Canon PowerShot 600",
1567 "Canon PowerShot A5",
1568 "Canon PowerShot A5 Zoom",
1569 "Canon PowerShot A50",
1570 "Canon PowerShot A460 (CHDK hack)",
1571 "Canon PowerShot A530 (CHDK hack)",
1572 "Canon PowerShot A610 (CHDK hack)",
1573 "Canon PowerShot A620 (CHDK hack)",
1574 "Canon PowerShot A630 (CHDK hack)",
1575 "Canon PowerShot A640 (CHDK hack)",
1576 "Canon PowerShot A650 (CHDK hack)",
1577 "Canon PowerShot A710 IS (CHDK hack)",
1578 "Canon PowerShot A720 IS (CHDK hack)",
1579 "Canon PowerShot Pro70",
1580 "Canon PowerShot Pro90 IS",
1581 "Canon PowerShot G1",
1582 "Canon PowerShot G2",
1583 "Canon PowerShot G3",
1584 "Canon PowerShot G5",
1585 "Canon PowerShot G6",
1586 "Canon PowerShot G7 (CHDK hack)",
1587 "Canon PowerShot G9",
1588 "Canon PowerShot G10",
1589 "Canon PowerShot S2 IS (CHDK hack)",
1590 "Canon PowerShot S3 IS (CHDK hack)",
1591 "Canon PowerShot S5 IS (CHDK hack)",
1592 "Canon PowerShot SD300 (CHDK hack)",
1593 "Canon PowerShot S30",
1594 "Canon PowerShot S40",
1595 "Canon PowerShot S45",
1596 "Canon PowerShot S50",
1597 "Canon PowerShot S60",
1598 "Canon PowerShot S70",
1599 "Canon PowerShot Pro1",
1603 "Canon EOS 5D Mark II",
1609 "Canon EOS 300D / Digital Rebel / Kiss Digital",
1610 "Canon EOS 350D / Digital Rebel XT / Kiss Digital N",
1611 "Canon EOS 400D / Digital Rebel XTi / Kiss Digital X",
1612 "Canon EOS 450D / Digital Rebel XSi / Kiss Digital X2",
1613 "Canon EOS 1000D / Digital Rebel XS / Kiss Digital F",
1617 "Canon EOS-1D Mark II",
1618 "Canon EOS-1D Mark III",
1619 "Canon EOS-1D Mark II N",
1620 "Canon EOS-1Ds Mark II",
1621 "Canon EOS-1Ds Mark III",
1634 "Casio Exlim Pro 505",
1635 "Casio Exlim Pro 600",
1636 "Casio Exlim Pro 700",
1638 "Creative PC-CAM 600",
1641 "Fuji FinePix E550",
1642 "Fuji FinePix E900",
1643 "Fuji FinePix F700",
1644 "Fuji FinePix F710",
1645 "Fuji FinePix F800",
1646 "Fuji FinePix F810",
1647 "Fuji FinePix S2Pro",
1648 "Fuji FinePix S3Pro",
1649 "Fuji FinePix S5Pro",
1650 "Fuji FinePix S20Pro",
1651 "Fuji FinePix S100FS",
1652 "Fuji FinePix S5000",
1653 "Fuji FinePix S5100/S5500",
1654 "Fuji FinePix S5200/S5600",
1655 "Fuji FinePix S6000fd",
1656 "Fuji FinePix S7000",
1657 "Fuji FinePix S9000/S9500",
1658 "Fuji FinePix S9100/S9600",
1663 "Imacon Ixpress 16-megapixel",
1664 "Imacon Ixpress 22-megapixel",
1665 "Imacon Ixpress 39-megapixel",
1667 "Kodak DC20 (see Oliver Hartman's page)",
1668 "Kodak DC25 (see Jun-ichiro Itoh's page)",
1671 "Kodak DC120 (also try kdc2tiff)",
1694 "Kodak DCS Pro 14n",
1695 "Kodak DCS Pro 14nx",
1696 "Kodak DCS Pro SLR/c",
1697 "Kodak DCS Pro SLR/n",
1727 "Logitech Fotoman Pixtura",
1733 "Minolta DiMAGE 7i",
1734 "Minolta DiMAGE 7Hi",
1735 "Minolta DiMAGE A1",
1736 "Minolta DiMAGE A2",
1737 "Minolta DiMAGE A200",
1738 "Minolta DiMAGE G400",
1739 "Minolta DiMAGE G500",
1740 "Minolta DiMAGE G530",
1741 "Minolta DiMAGE G600",
1742 "Minolta DiMAGE Z2",
1743 "Minolta Alpha/Dynax/Maxxum 5D",
1744 "Minolta Alpha/Dynax/Maxxum 7D",
1765 "Nikon E700 (\"DIAG RAW\" hack)",
1766 "Nikon E800 (\"DIAG RAW\" hack)",
1767 "Nikon E880 (\"DIAG RAW\" hack)",
1768 "Nikon E900 (\"DIAG RAW\" hack)",
1769 "Nikon E950 (\"DIAG RAW\" hack)",
1770 "Nikon E990 (\"DIAG RAW\" hack)",
1771 "Nikon E995 (\"DIAG RAW\" hack)",
1772 "Nikon E2100 (\"DIAG RAW\" hack)",
1773 "Nikon E2500 (\"DIAG RAW\" hack)",
1774 "Nikon E3200 (\"DIAG RAW\" hack)",
1775 "Nikon E3700 (\"DIAG RAW\" hack)",
1776 "Nikon E4300 (\"DIAG RAW\" hack)",
1777 "Nikon E4500 (\"DIAG RAW\" hack)",
1784 "Nikon Coolpix P6000",
1785 "Nikon Coolpix S6 (\"DIAG RAW\" hack)",
1791 "Olympus C70Z,C7000Z",
1815 "Panasonic DMC-FZ8",
1816 "Panasonic DMC-FZ18",
1817 "Panasonic DMC-FZ28",
1818 "Panasonic DMC-FZ30",
1819 "Panasonic DMC-FZ50",
1820 "Panasonic DMC-FX150",
1823 "Panasonic DMC-L10",
1824 "Panasonic DMC-LC1",
1825 "Panasonic DMC-LX1",
1826 "Panasonic DMC-LX2",
1827 "Panasonic DMC-LX3",
1836 "Pentax K100D Super",
1840 "Pentax Optio 33WR",
1841 "Pentax Optio 750Z",
1842 "Phase One LightPhase",
1856 "Samsung S85 (hacked)",
1857 "Sarnoff 4096x5440",
1865 "SMaL Ultra-Pocket 3",
1866 "SMaL Ultra-Pocket 4",
1867 "SMaL Ultra-Pocket 5",
1882 const char** LibRaw::cameraList() { return static_camera_list
;}
1883 int LibRaw::cameraCount() { return (sizeof(static_camera_list
)/sizeof(static_camera_list
[0]))-1; }
1886 const char * LibRaw::strprogress(enum LibRaw_progress p
)
1890 case LIBRAW_PROGRESS_START
:
1892 case LIBRAW_PROGRESS_OPEN
:
1893 return "Opening file";
1894 case LIBRAW_PROGRESS_IDENTIFY
:
1895 return "Reading metadata";
1896 case LIBRAW_PROGRESS_SIZE_ADJUST
:
1897 return "Adjusting size";
1898 case LIBRAW_PROGRESS_LOAD_RAW
:
1899 return "Reading RAW data";
1900 case LIBRAW_PROGRESS_REMOVE_ZEROES
:
1901 return "Clearing zero values";
1902 case LIBRAW_PROGRESS_BAD_PIXELS
:
1903 return "Removing dead pixels";
1904 case LIBRAW_PROGRESS_DARK_FRAME
:
1905 return "Subtracting dark frame data";
1906 case LIBRAW_PROGRESS_FOVEON_INTERPOLATE
:
1907 return "Interpolating Foveon sensor data";
1908 case LIBRAW_PROGRESS_SCALE_COLORS
:
1909 return "Scaling colors";
1910 case LIBRAW_PROGRESS_PRE_INTERPOLATE
:
1911 return "Pre-interpolating";
1912 case LIBRAW_PROGRESS_INTERPOLATE
:
1913 return "Interpolating";
1914 case LIBRAW_PROGRESS_MIX_GREEN
:
1915 return "Mixing green channels";
1916 case LIBRAW_PROGRESS_MEDIAN_FILTER
:
1917 return "Median filter";
1918 case LIBRAW_PROGRESS_HIGHLIGHTS
:
1919 return "Highlight recovery";
1920 case LIBRAW_PROGRESS_FUJI_ROTATE
:
1921 return "Rotating Fuji diagonal data";
1922 case LIBRAW_PROGRESS_FLIP
:
1923 return "Flipping image";
1924 case LIBRAW_PROGRESS_APPLY_PROFILE
:
1925 return "ICC conversion";
1926 case LIBRAW_PROGRESS_CONVERT_RGB
:
1927 return "Converting to RGB";
1928 case LIBRAW_PROGRESS_STRETCH
:
1929 return "Stretching image";
1930 case LIBRAW_PROGRESS_THUMB_LOAD
:
1931 return "Loading thumbnail";
1933 return "Some strange things";