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 double gamm
[5] = { 0.45,4.5,0,0,0 };
140 unsigned greybox
[4] = { 0, 0, UINT_MAX
, UINT_MAX
};
146 bzero(&imgdata
,sizeof(imgdata
));
147 bzero(&libraw_internal_data
,sizeof(libraw_internal_data
));
148 bzero(&callbacks
,sizeof(callbacks
));
149 callbacks
.mem_cb
= (flags
& LIBRAW_OPIONS_NO_MEMERR_CALLBACK
) ? NULL
: &default_memory_callback
;
150 callbacks
.data_cb
= (flags
& LIBRAW_OPIONS_NO_DATAERR_CALLBACK
)? NULL
: &default_data_callback
;
151 memmove(&imgdata
.params
.aber
,&aber
,sizeof(aber
));
152 memmove(&imgdata
.params
.gamm
,&gamm
,sizeof(gamm
));
153 memmove(&imgdata
.params
.greybox
,&greybox
,sizeof(greybox
));
155 imgdata
.params
.bright
=1;
156 imgdata
.params
.use_camera_matrix
=-1;
157 imgdata
.params
.user_flip
=-1;
158 imgdata
.params
.user_black
=-1;
159 imgdata
.params
.user_sat
=-1;
160 imgdata
.params
.user_qual
=-1;
161 imgdata
.params
.output_color
=1;
162 imgdata
.params
.output_bps
=8;
163 imgdata
.params
.use_fuji_rotate
=1;
164 imgdata
.parent_class
= this;
165 imgdata
.progress_flags
= 0;
166 tls
= new LibRaw_TLS
;
171 void* LibRaw:: malloc(size_t t
)
173 void *p
= memmgr
.malloc(t
);
176 void* LibRaw:: calloc(size_t n
,size_t t
)
178 void *p
= memmgr
.calloc(n
,t
);
181 void LibRaw:: free(void *p
)
187 int LibRaw:: fc (int row
, int col
)
189 static const char filter
[16][16] =
190 { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
191 { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
192 { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
193 { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
194 { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
195 { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
196 { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
197 { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
198 { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
199 { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
200 { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
201 { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
202 { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
203 { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
204 { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
205 { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
207 if (imgdata
.idata
.filters
!= 1) return FC(row
,col
);
208 return filter
[(row
+imgdata
.sizes
.top_margin
) & 15][(col
+imgdata
.sizes
.left_margin
) & 15];
211 void LibRaw:: recycle()
213 if(libraw_internal_data
.internal_data
.input
&& libraw_internal_data
.internal_data
.input_internal
)
215 delete libraw_internal_data
.internal_data
.input
;
216 libraw_internal_data
.internal_data
.input
= NULL
;
218 libraw_internal_data
.internal_data
.input_internal
= 0;
219 #define FREE(a) do { if(a) { free(a); a = NULL;} }while(0)
222 FREE(imgdata
.thumbnail
.thumb
);
223 FREE(libraw_internal_data
.internal_data
.meta_data
);
224 FREE(libraw_internal_data
.output_data
.histogram
);
225 FREE(libraw_internal_data
.output_data
.oprof
);
226 FREE(imgdata
.color
.profile
);
227 FREE(imgdata
.masked_pixels
.buffer
);
228 FREE(imgdata
.masked_pixels
.ph1_black
);
230 #define ZERO(a) bzero(&a,sizeof(a))
231 ZERO(imgdata
.masked_pixels
);
233 ZERO(libraw_internal_data
.internal_output_params
);
236 imgdata
.thumbnail
.tformat
= LIBRAW_THUMBNAIL_UNKNOWN
;
237 imgdata
.progress_flags
= 0;
242 const char * LibRaw::unpack_function_name()
244 if(!load_raw
) return "Function not set";
246 // sorted names order
247 if (load_raw
== &LibRaw::adobe_dng_load_raw_lj
) return "adobe_dng_load_raw_lj()";
248 if (load_raw
== &LibRaw::adobe_dng_load_raw_nc
) return "adobe_dng_load_raw_nc()";
249 if (load_raw
== &LibRaw::canon_600_load_raw
) return "canon_600_load_raw()";
251 if (load_raw
== &LibRaw::canon_a5_load_raw
) return "canon_a5_load_raw()";
252 if (load_raw
== &LibRaw::canon_compressed_load_raw
) return "canon_compressed_load_raw()";
253 if (load_raw
== &LibRaw::canon_sraw_load_raw
) return "canon_sraw_load_raw()";
255 if (load_raw
== &LibRaw::casio_qv5700_load_raw
) return "casio_qv5700_load_raw()";
256 if (load_raw
== &LibRaw::eight_bit_load_raw
) return "eight_bit_load_raw()";
257 if (load_raw
== &LibRaw::foveon_load_raw
) return "foveon_load_raw()";
258 if (load_raw
== &LibRaw::fuji_load_raw
) return "fuji_load_raw()";
260 if (load_raw
== &LibRaw::hasselblad_load_raw
) return "hasselblad_load_raw()";
261 if (load_raw
== &LibRaw::imacon_full_load_raw
) return "imacon_full_load_raw()";
262 if (load_raw
== &LibRaw::kodak_262_load_raw
) return "kodak_262_load_raw()";
264 if (load_raw
== &LibRaw::kodak_65000_load_raw
) return "kodak_65000_load_raw()";
265 if (load_raw
== &LibRaw::kodak_dc120_load_raw
) return "kodak_dc120_load_raw()";
266 if (load_raw
== &LibRaw::kodak_jpeg_load_raw
) return "kodak_jpeg_load_raw()";
268 if (load_raw
== &LibRaw::kodak_radc_load_raw
) return "kodak_radc_load_raw()";
269 if (load_raw
== &LibRaw::kodak_rgb_load_raw
) return "kodak_rgb_load_raw()";
270 if (load_raw
== &LibRaw::kodak_yrgb_load_raw
) return "kodak_yrgb_load_raw()";
271 if (load_raw
== &LibRaw::kodak_ycbcr_load_raw
) return "kodak_ycbcr_load_raw()";
273 if (load_raw
== &LibRaw::leaf_hdr_load_raw
) return "leaf_hdr_load_raw()";
274 if (load_raw
== &LibRaw::lossless_jpeg_load_raw
) return "lossless_jpeg_load_raw()";
275 if (load_raw
== &LibRaw::minolta_rd175_load_raw
) return "minolta_rd175_load_raw()";
277 if (load_raw
== &LibRaw::nikon_compressed_load_raw
) return "nikon_compressed_load_raw()";
278 if (load_raw
== &LibRaw::nikon_e900_load_raw
) return "nikon_e900_load_raw()";
279 if (load_raw
== &LibRaw::nokia_load_raw
) return "nokia_load_raw()";
281 if (load_raw
== &LibRaw::olympus_e300_load_raw
) return "olympus_e300_load_raw()";
282 if (load_raw
== &LibRaw::olympus_e410_load_raw
) return "olympus_e410_load_raw()";
283 if (load_raw
== &LibRaw::packed_12_load_raw
) return "packed_12_load_raw()";
284 if (load_raw
== &LibRaw::panasonic_load_raw
) return "panasonic_load_raw()";
286 if (load_raw
== &LibRaw::pentax_k10_load_raw
) return "pentax_k10_load_raw()";
287 if (load_raw
== &LibRaw::phase_one_load_raw
) return "phase_one_load_raw()";
288 if (load_raw
== &LibRaw::phase_one_load_raw_c
) return "phase_one_load_raw_c()";
290 if (load_raw
== &LibRaw::quicktake_100_load_raw
) return "quicktake_100_load_raw()";
291 if (load_raw
== &LibRaw::rollei_load_raw
) return "rollei_load_raw()";
292 if (load_raw
== &LibRaw::sinar_4shot_load_raw
) return "sinar_4shot_load_raw()";
294 if (load_raw
== &LibRaw::smal_v6_load_raw
) return "smal_v6_load_raw()";
295 if (load_raw
== &LibRaw::smal_v9_load_raw
) return "smal_v9_load_raw()";
296 if (load_raw
== &LibRaw::sony_load_raw
) return "sony_load_raw()";
297 if (load_raw
== &LibRaw::sony_arw_load_raw
) return "sony_arw_load_raw()";
299 if (load_raw
== &LibRaw::sony_arw2_load_raw
) return "sony_arw2_load_raw()";
300 if (load_raw
== &LibRaw::unpacked_load_raw
) return "unpacked_load_raw()";
303 return "Unknown unpack function";
307 void LibRaw:: merror (void *ptr
, const char *where
)
310 if(callbacks
.mem_cb
)(*callbacks
.mem_cb
)(callbacks
.memcb_data
,
311 libraw_internal_data
.internal_data
.input
312 ?libraw_internal_data
.internal_data
.input
->fname()
315 throw LIBRAW_EXCEPTION_ALLOC
;
318 ushort
* LibRaw::get_masked_pointer(int row
, int col
)
320 if(row
<0 || col
< 0) return NULL
;
321 if(!M
.buffer
) return NULL
;
322 if(row
< S
.top_margin
)
325 if(col
< S
.left_margin
)
327 return &(M
.tl
[row
*S
.left_margin
+col
]);
329 else if (col
< S
.left_margin
+ S
.width
)
331 int icol
= col
- S
.left_margin
;
332 return &(M
.top
[row
*S
.width
+icol
]);
334 else if (col
< S
.raw_width
)
336 int icol
= col
- S
.left_margin
- S
.width
;
337 return &(M
.tr
[row
*S
.right_margin
+icol
]);
340 return NULL
; // out of bounds
342 else if (row
< S
.top_margin
+ S
.height
)
344 //normal image height
345 int irow
= row
- S
.top_margin
;
346 if(col
< S
.left_margin
)
348 return &M
.left
[irow
*S
.left_margin
+ col
];
350 else if (col
< S
.left_margin
+ S
.width
)
355 else if (col
< S
.raw_width
)
357 int icol
= col
- S
.left_margin
- S
.width
;
358 return &M
.right
[irow
*S
.right_margin
+icol
];
361 return NULL
; // out of bounds
363 else if (row
< S
.raw_height
)
365 int irow
= row
- S
.top_margin
- S
.height
;
367 if(col
< S
.left_margin
)
369 return &M
.bl
[irow
*S
.left_margin
+col
];
371 else if (col
< S
.left_margin
+ S
.width
)
373 int icol
= col
- S
.left_margin
;
374 return &M
.bottom
[irow
*S
.width
+ icol
];
376 else if (col
< S
.raw_width
)
378 int icol
= col
- S
.left_margin
- S
.width
;
379 return &M
.br
[irow
*S
.right_margin
+ icol
];
382 return NULL
; // out of bounds
393 void LibRaw:: init_masked_ptrs()
395 if(!M
.buffer
) return;
399 M
.top
= M
.tl
+(S
.top_margin
*S
.left_margin
);
400 M
.tr
= M
.top
+ (S
.top_margin
*S
.width
);
403 M
.left
= M
.tr
+ (S
.top_margin
* S
.right_margin
);
404 M
.right
= M
.left
+ (S
.left_margin
* S
.height
);
407 M
.bl
= M
.right
+ (S
.right_margin
* S
.height
);
408 M
.bottom
= M
.bl
+ (S
.left_margin
* S
.bottom_margin
);
409 M
.br
= M
.bottom
+ (S
.width
* S
.bottom_margin
);
413 int LibRaw::add_masked_borders_to_bitmap()
415 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
416 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW
);
418 if(S
.width
!= S
.iwidth
|| S
.height
!=S
.iheight
)
419 return LIBRAW_CANNOT_ADDMASK
;
421 if(P1
.is_foveon
|| !P1
.filters
)
422 return LIBRAW_CANNOT_ADDMASK
;
425 return LIBRAW_OUT_OF_ORDER_CALL
;
427 if(S
.raw_width
< S
.width
|| S
.raw_height
< S
.height
)
428 return LIBRAW_SUCCESS
; // nothing to do or already called
430 if(S
.width
== S
.raw_width
&& S
.height
== S
.raw_height
)
431 return LIBRAW_SUCCESS
; // nothing to do or already called
433 ushort (*newimage
)[4];
435 newimage
= (ushort (*)[4]) calloc (S
.raw_height
*S
.raw_width
, sizeof (*newimage
));
436 merror (newimage
, "add_masked_borders_to_bitmap()");
440 for (r
=0; r
<S
.top_margin
;r
++)
441 for(c
=0;c
<S
.raw_width
;c
++)
443 ushort
*p
= get_masked_pointer(r
,c
);
445 newimage
[r
*S
.raw_width
+c
][FC(r
,c
)] = *p
;
448 for (r
=S
.top_margin
; r
<S
.top_margin
+S
.height
;r
++)
450 int row
= r
-S
.top_margin
;
451 for(c
=0;c
<S
.left_margin
;c
++)
453 ushort
*p
= get_masked_pointer(r
,c
);
455 newimage
[r
*S
.raw_width
+c
][FC(r
,c
)] = *p
;
457 for(c
=S
.left_margin
; c
<S
.left_margin
+S
.iwidth
;c
++)
459 int col
= c
- S
.left_margin
;
460 newimage
[r
*S
.raw_width
+c
][FC(r
,c
)] = imgdata
.image
[row
*S
.iwidth
+col
][FC(row
,col
)];
462 for(c
=S
.left_margin
+S
.iwidth
;c
<S
.raw_width
;c
++)
464 ushort
*p
= get_masked_pointer(r
,c
);
466 newimage
[r
*S
.raw_width
+c
][FC(r
,c
)] = *p
;
470 for (r
=S
.top_margin
+S
.height
; r
<S
.raw_height
;r
++)
471 for(c
=0;c
<S
.raw_width
;c
++)
473 ushort
*p
= get_masked_pointer(r
,c
);
475 newimage
[r
*S
.raw_width
+c
][FC(r
,c
)] = *p
;
478 imgdata
.image
=newimage
;
479 S
.iwidth
= S
.width
= S
.raw_width
;
480 S
.iheight
= S
.height
= S
.raw_height
;
481 return LIBRAW_SUCCESS
;
484 int LibRaw::open_file(const char *fname
)
486 // this stream will close on recycle()
487 LibRaw_file_datastream
*stream
= new LibRaw_file_datastream(fname
);
491 return LIBRAW_IO_ERROR
;
493 ID
.input_internal
= 0; // preserve from deletion on error
494 int ret
= open_datastream(stream
);
495 if (ret
== LIBRAW_SUCCESS
)
497 ID
.input_internal
=1 ; // flag to delete datastream on recycle
502 ID
.input_internal
= 0;
507 int LibRaw::open_buffer(void *buffer
, size_t size
)
509 // this stream will close on recycle()
510 if(!buffer
|| buffer
==(void*)-1)
511 return LIBRAW_IO_ERROR
;
513 LibRaw_buffer_datastream
*stream
= new LibRaw_buffer_datastream(buffer
,size
);
517 return LIBRAW_IO_ERROR
;
519 ID
.input_internal
= 0; // preserve from deletion on error
520 int ret
= open_datastream(stream
);
521 if (ret
== LIBRAW_SUCCESS
)
523 ID
.input_internal
=1 ; // flag to delete datastream on recycle
528 ID
.input_internal
= 0;
534 int LibRaw::open_datastream(LibRaw_abstract_datastream
*stream
)
540 return LIBRAW_IO_ERROR
;
545 SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN
);
547 if (O
.use_camera_matrix
< 0)
548 O
.use_camera_matrix
= O
.use_camera_wb
;
555 IO
.fheight
= S
.height
;
556 S
.iwidth
= S
.width
= IO
.fuji_width
<< !libraw_internal_data
.unpacker_data
.fuji_layout
;
557 S
.iheight
= S
.height
= S
.raw_height
;
558 S
.raw_height
+= 2*S
.top_margin
;
561 int saved_raw_width
= S
.raw_width
;
562 int saved_width
= S
.width
;
563 // from packed_12_load_raw
564 if ((load_raw
== &LibRaw:: packed_12_load_raw
) && (S
.raw_width
* 2 >= S
.width
* 3))
566 // raw_width is in bytes!
567 S
.raw_width
= S
.raw_width
* 2 / 3;
569 else if (S
.pixel_aspect
< 0.95 || S
.pixel_aspect
> 1.05)
571 S
.width
*=S
.pixel_aspect
;
574 if(S
.raw_width
>S
.width
+ S
.left_margin
)
575 S
.right_margin
= S
.raw_width
- S
.width
- S
.left_margin
;
577 if(S
.raw_height
> S
.height
+ S
.top_margin
)
578 S
.bottom_margin
= S
.raw_height
- S
.height
- S
.top_margin
;
580 S
.raw_width
= saved_raw_width
;
581 S
.width
= saved_width
;
585 if(C
.profile
) free(C
.profile
);
586 C
.profile
= malloc(C
.profile_length
);
587 merror(C
.profile
,"LibRaw::open_file()");
588 ID
.input
->seek(ID
.profile_offset
,SEEK_SET
);
589 ID
.input
->read(C
.profile
,C
.profile_length
,1);
592 SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY
);
594 catch ( LibRaw_exceptions err
) {
595 EXCEPTION_HANDLER(err
);
599 return LIBRAW_FILE_UNSUPPORTED
;
601 if (O
.user_flip
>= 0)
602 S
.flip
= O
.user_flip
;
604 switch ((S
.flip
+3600) % 360)
606 case 270: S
.flip
= 5; break;
607 case 180: S
.flip
= 3; break;
608 case 90: S
.flip
= 6; break;
611 write_fun
= &LibRaw::write_ppm_tiff
;
613 if (load_raw
== &LibRaw::kodak_ycbcr_load_raw
)
615 S
.height
+= S
.height
& 1;
616 S
.width
+= S
.width
& 1;
619 IO
.shrink
= P1
.filters
&& (O
.half_size
|| O
.threshold
|| O
.aber
[0] != 1 || O
.aber
[2] != 1);
620 S
.iheight
= (S
.height
+ IO
.shrink
) >> IO
.shrink
;
621 S
.iwidth
= (S
.width
+ IO
.shrink
) >> IO
.shrink
;
623 SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST
);
626 return LIBRAW_SUCCESS
;
629 int LibRaw::unpack(void)
631 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_LOAD_RAW
);
632 CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY
);
635 RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW
,0,2);
636 if (O
.shot_select
>= P1
.raw_count
)
637 return LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE
;
640 return LIBRAW_UNSPECIFIED_ERROR
;
642 if (O
.use_camera_matrix
&& C
.cmatrix
[0][0] > 0.25)
644 memcpy (C
.rgb_cam
, C
.cmatrix
, sizeof (C
.cmatrix
));
647 // already allocated ?
648 if(imgdata
.image
) free(imgdata
.image
);
650 imgdata
.image
= (ushort (*)[4]) calloc (S
.iheight
*S
.iwidth
, sizeof (*imgdata
.image
));
651 merror (imgdata
.image
, "unpack()");
654 if(S
.top_margin
|| S
.left_margin
|| S
.right_margin
|| S
.bottom_margin
)
656 unsigned sz
= S
.raw_height
*(S
.left_margin
+S
.right_margin
)
657 + S
.width
*(S
.top_margin
+S
.bottom_margin
);
658 imgdata
.masked_pixels
.buffer
= (ushort
*) calloc(sz
, sizeof(ushort
));
659 merror (imgdata
.masked_pixels
.buffer
, "unpack()");
662 if (libraw_internal_data
.unpacker_data
.meta_length
)
664 libraw_internal_data
.internal_data
.meta_data
=
665 (char *) malloc (libraw_internal_data
.unpacker_data
.meta_length
);
666 merror (libraw_internal_data
.internal_data
.meta_data
, "LibRaw::unpack()");
668 ID
.input
->seek(libraw_internal_data
.unpacker_data
.data_offset
, SEEK_SET
);
669 // foveon_load_raw produces different data for document_mode, we'll
670 // deal with it in dcraw_document_mode_processing
671 int save_document_mode
= O
.document_mode
;
674 if(!own_filtering_supported() && (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
))
675 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC_BIT
; // turn on black and zeroes filtering
679 O
.document_mode
= save_document_mode
;
681 if (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
)
682 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC
; // restore automated mode
684 SET_PROC_FLAG(LIBRAW_PROGRESS_LOAD_RAW
);
685 RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW
,1,2);
689 catch ( LibRaw_exceptions err
) {
690 EXCEPTION_HANDLER(err
);
694 int LibRaw::dcraw_document_mode_processing(void)
696 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
697 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW
);
704 if(!own_filtering_supported() && (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
))
705 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC_BIT
; // turn on black and zeroes filtering
710 // filter image data for foveon document mode
711 short *iptr
= (short *)imgdata
.image
;
712 for (int i
=0; i
< S
.height
*S
.width
*4; i
++)
714 if ((short) iptr
[i
] < 0)
717 SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
);
720 O
.use_fuji_rotate
= 0;
721 if (!(O
.filtering_mode
& LIBRAW_FILTERING_NOZEROES
) && IO
.zero_is_bad
)
724 SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES
);
728 bad_pixels(O
.bad_pixels
);
729 SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS
);
733 subtract (O
.dark_frame
);
734 SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME
);
736 if(O
.filtering_mode
& LIBRAW_FILTERING_NOBLACKS
)
739 if (O
.user_black
>= 0)
740 C
.black
= O
.user_black
;
743 C
.maximum
= O
.user_sat
;
746 SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
748 if (libraw_internal_data
.internal_output_params
.mix_green
)
751 for (P1
.colors
=3, i
=0; i
< S
.height
*S
.width
; i
++)
752 imgdata
.image
[i
][1] = (imgdata
.image
[i
][1] + imgdata
.image
[i
][3]) >> 1;
754 SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN
);
756 if (!P1
.is_foveon
&& P1
.colors
== 3)
758 SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER
);
760 if (!P1
.is_foveon
&& O
.highlight
== 2)
763 if (!P1
.is_foveon
&& O
.highlight
> 2)
764 recover_highlights();
765 SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS
);
767 if (O
.use_fuji_rotate
)
769 SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE
);
773 apply_profile(O
.camera_profile
,O
.output_profile
);
774 SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE
);
777 if(!libraw_internal_data
.output_data
.histogram
)
779 libraw_internal_data
.output_data
.histogram
= (int (*)[LIBRAW_HISTOGRAM_SIZE
]) malloc(sizeof(*libraw_internal_data
.output_data
.histogram
)*4);
780 merror(libraw_internal_data
.output_data
.histogram
,"LibRaw::dcraw_document_mode_processing()");
783 SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB
);
785 if (O
.use_fuji_rotate
)
787 SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH
);
789 if (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
)
790 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC
; // restore automated mode
794 catch ( LibRaw_exceptions err
) {
795 EXCEPTION_HANDLER(err
);
801 #define FORC(cnt) for (c=0; c < cnt; c++)
802 #define FORCC FORC(ret->colors)
803 #define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
805 libraw_processed_image_t
* LibRaw::dcraw_make_mem_thumb(int *errcode
)
811 if(errcode
) *errcode
= LIBRAW_NO_THUMBNAIL
;
815 if(errcode
) *errcode
= LIBRAW_OUT_OF_ORDER_CALL
;
820 if (T
.tformat
== LIBRAW_THUMBNAIL_BITMAP
)
822 libraw_processed_image_t
* ret
=
823 (libraw_processed_image_t
*)::malloc(sizeof(libraw_processed_image_t
)+T
.tlength
);
827 if(errcode
) *errcode
= ENOMEM
;
831 bzero(ret
,sizeof(libraw_processed_image_t
));
832 ret
->type
= LIBRAW_IMAGE_BITMAP
;
833 ret
->height
= T
.theight
;
834 ret
->width
= T
.twidth
;
837 ret
->gamma_corrected
= 1;
838 ret
->data_size
= T
.tlength
;
839 memmove(ret
->data
,T
.thumb
,T
.tlength
);
840 if(errcode
) *errcode
= 0;
843 else if (T
.tformat
== LIBRAW_THUMBNAIL_JPEG
)
847 if(strcmp(T
.thumb
+6,"Exif")) mk_exif
= 1;
849 int dsize
= T
.tlength
+ mk_exif
* (sizeof(exif
)+sizeof(tiff_hdr
));
851 libraw_processed_image_t
* ret
=
852 (libraw_processed_image_t
*)::malloc(sizeof(libraw_processed_image_t
)+dsize
);
856 if(errcode
) *errcode
= ENOMEM
;
860 bzero(ret
,sizeof(libraw_processed_image_t
));
862 ret
->type
= LIBRAW_IMAGE_JPEG
;
863 ret
->data_size
= dsize
;
870 memcpy (exif
, "\xff\xe1 Exif\0\0", 10);
871 exif
[1] = htons (8 + sizeof th
);
872 memmove(ret
->data
+2,exif
,sizeof(exif
));
874 memmove(ret
->data
+(2+sizeof(exif
)),&th
,sizeof(th
));
875 memmove(ret
->data
+(2+sizeof(exif
)+sizeof(th
)),T
.thumb
+2,T
.tlength
-2);
879 memmove(ret
->data
+2,T
.thumb
+2,T
.tlength
-2);
881 if(errcode
) *errcode
= 0;
887 if(errcode
) *errcode
= LIBRAW_UNSUPPORTED_THUMBNAIL
;
895 libraw_processed_image_t
*LibRaw::dcraw_make_mem_image(int *errcode
)
897 if((imgdata
.progress_flags
& LIBRAW_PROGRESS_THUMB_MASK
) < LIBRAW_PROGRESS_PRE_INTERPOLATE
)
899 if(errcode
) *errcode
= LIBRAW_OUT_OF_ORDER_CALL
;
903 if(!libraw_internal_data
.output_data
.histogram
)
905 libraw_internal_data
.output_data
.histogram
=
906 (int (*)[LIBRAW_HISTOGRAM_SIZE
]) malloc(sizeof(*libraw_internal_data
.output_data
.histogram
)*4);
907 merror(libraw_internal_data
.output_data
.histogram
,"LibRaw::dcraw_make_mem_image()");
910 unsigned ds
= S
.height
* S
.width
* (O
.output_bps
/8) * P1
.colors
;
911 libraw_processed_image_t
*ret
= (libraw_processed_image_t
*)::malloc(sizeof(libraw_processed_image_t
)+ds
);
914 if(errcode
) *errcode
= ENOMEM
;
917 bzero(ret
,sizeof(libraw_processed_image_t
));
920 int s_iheight
= S
.iheight
;
921 int s_iwidth
= S
.iwidth
;
922 int s_width
= S
.width
;
923 int s_hwight
= S
.height
;
925 S
.iheight
= S
.height
;
929 if (S
.flip
& 4) SWAP(S
.height
,S
.width
);
932 ret
->type
= LIBRAW_IMAGE_BITMAP
;
933 ret
->height
= S
.height
;
934 ret
->width
= S
.width
;
935 ret
->colors
= P1
.colors
;
936 ret
->bits
= O
.output_bps
;
937 ret
->gamma_corrected
= (O
.output_bps
== 8)?1:O
.gamma_16bit
;
941 // Cut'n'paste from write_tiff_ppm, should be generalized later
942 uchar
*bufp
= ret
->data
;
944 ushort
*ppm2
,lut16
[0x10000];
945 int c
, row
, col
, soff
, rstep
, cstep
;
948 if (ret
->bits
== 8 || ret
->gamma_corrected
) gamma_lut (lut16
);
949 soff
= flip_index (0, 0);
950 cstep
= flip_index (0, 1) - soff
;
951 rstep
= flip_index (1, 0) - flip_index (0, S
.width
);
954 for (row
=0; row
< ret
->height
; row
++, soff
+= rstep
)
956 ppm2
= (ushort
*) (ppm
= bufp
);
957 for (col
=0; col
< ret
->width
; col
++, soff
+= cstep
)
959 FORCC ppm
[col
*ret
->colors
+c
] = lut16
[imgdata
.image
[soff
][c
]]/256;
960 else if(ret
->gamma_corrected
)
961 FORCC ppm2
[col
*ret
->colors
+c
] = lut16
[imgdata
.image
[soff
][c
]];
963 FORCC ppm2
[col
*ret
->colors
+c
] = imgdata
.image
[soff
][c
];
964 bufp
+=ret
->colors
*(ret
->bits
/8)*ret
->width
;
966 if(errcode
) *errcode
= 0;
968 S
.iheight
= s_iheight
;
982 int LibRaw::dcraw_ppm_tiff_writer(const char *filename
)
984 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW
);
987 return LIBRAW_OUT_OF_ORDER_CALL
;
991 FILE *f
= fopen(filename
,"wb");
997 if(!libraw_internal_data
.output_data
.histogram
)
999 libraw_internal_data
.output_data
.histogram
=
1000 (int (*)[LIBRAW_HISTOGRAM_SIZE
]) malloc(sizeof(*libraw_internal_data
.output_data
.histogram
)*4);
1001 merror(libraw_internal_data
.output_data
.histogram
,"LibRaw::dcraw_ppm_tiff_writer()");
1004 SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP
);
1008 catch ( LibRaw_exceptions err
) {
1010 EXCEPTION_HANDLER(err
);
1014 void LibRaw::kodak_thumb_loader()
1016 // some kodak cameras
1017 ushort s_height
= S
.height
, s_width
= S
.width
,s_iwidth
= S
.iwidth
,s_iheight
=S
.iheight
;
1018 int s_colors
= P1
.colors
;
1019 unsigned s_filters
= P1
.filters
;
1020 ushort (*s_image
)[4] = imgdata
.image
;
1023 S
.height
= T
.theight
;
1027 if (thumb_load_raw
== &CLASS kodak_ycbcr_load_raw
)
1029 S
.height
+= S
.height
& 1;
1030 S
.width
+= S
.width
& 1;
1033 imgdata
.image
= (ushort (*)[4]) calloc (S
.iheight
*S
.iwidth
, sizeof (*imgdata
.image
));
1034 merror (imgdata
.image
, "LibRaw::kodak_thumb_loader()");
1036 ID
.input
->seek(ID
.toffset
, SEEK_SET
);
1037 // read kodak thumbnail into T.image[]
1038 (this->*thumb_load_raw
)();
1040 // copy-n-paste from image pipe
1041 #define MIN(a,b) ((a) < (b) ? (a) : (b))
1042 #define MAX(a,b) ((a) > (b) ? (a) : (b))
1043 #define LIM(x,min,max) MAX(min,MIN(x,max))
1044 #define CLIP(x) LIM(x,0,65535)
1045 #define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
1047 // from scale_colors
1052 for (dmax
=DBL_MAX
, c
=0; c
< 3; c
++)
1053 if (dmax
> C
.pre_mul
[c
])
1054 dmax
= C
.pre_mul
[c
];
1056 for( c
=0; c
< 3; c
++)
1057 scale_mul
[c
] = (C
.pre_mul
[c
] / dmax
) * 65535.0 / C
.maximum
;
1058 scale_mul
[3] = scale_mul
[1];
1060 size_t size
= S
.height
* S
.width
;
1061 for (int i
=0; i
< size
*4 ; i
++)
1063 val
= imgdata
.image
[0][i
];
1065 val
*= scale_mul
[i
& 3];
1066 imgdata
.image
[0][i
] = CLIP(val
);
1070 // from convert_to_rgb
1074 int (*t_hist
)[LIBRAW_HISTOGRAM_SIZE
] = (int (*)[LIBRAW_HISTOGRAM_SIZE
]) calloc(sizeof(*t_hist
),4);
1075 merror (t_hist
, "LibRaw::kodak_thumb_loader()");
1080 {2.81761312, -1.98369181, 0.166078627, 0},
1081 {-0.111855984, 1.73688626, -0.625030339, 0},
1082 {-0.0379119813, -0.891268849, 1.92918086, 0}
1085 for (img
=imgdata
.image
[0], row
=0; row
< S
.height
; row
++)
1086 for (col
=0; col
< S
.width
; col
++, img
+=4)
1088 out
[0] = out
[1] = out
[2] = 0;
1089 for(int c
=0;c
<3;c
++)
1091 out
[0] += out_cam
[0][c
] * img
[c
];
1092 out
[1] += out_cam
[1][c
] * img
[c
];
1093 out
[2] += out_cam
[2][c
] * img
[c
];
1095 for(int c
=0; c
<3; c
++)
1096 img
[c
] = CLIP((int) out
[c
]);
1097 for(int c
=0; c
<P1
.colors
;c
++)
1098 t_hist
[c
][img
[c
] >> 3]++;
1103 int (*save_hist
)[LIBRAW_HISTOGRAM_SIZE
] = libraw_internal_data
.output_data
.histogram
;
1104 libraw_internal_data
.output_data
.histogram
= t_hist
;
1106 ushort
*lut16
= (ushort
*)calloc(0x10000,sizeof(ushort
));
1107 merror(lut16
,"LibRaw::kodak_thumb_loader()");
1110 libraw_internal_data
.output_data
.histogram
= save_hist
;
1114 // from write_ppm_tiff - copy pixels into bitmap
1116 S
.iheight
= S
.height
;
1118 if (S
.flip
& 4) SWAP(S
.height
,S
.width
);
1120 if(T
.thumb
) free(T
.thumb
);
1121 T
.thumb
= (char*) calloc (S
.width
* S
.height
, P1
.colors
);
1122 merror (T
.thumb
, "LibRaw::kodak_thumb_loader()");
1123 T
.tlength
= S
.width
* S
.height
* P1
.colors
;
1125 // from write_tiff_ppm
1127 int soff
= flip_index (0, 0);
1128 int cstep
= flip_index (0, 1) - soff
;
1129 int rstep
= flip_index (1, 0) - flip_index (0, S
.width
);
1131 for (int row
=0; row
< S
.height
; row
++, soff
+= rstep
)
1133 char *ppm
= T
.thumb
+ row
*S
.width
*P1
.colors
;
1134 for (int col
=0; col
< S
.width
; col
++, soff
+= cstep
)
1135 for(int c
= 0; c
< P1
.colors
; c
++)
1136 ppm
[col
*P1
.colors
+c
] = lut16
[imgdata
.image
[soff
][c
]]/256;
1140 // restore variables
1141 free(imgdata
.image
);
1142 imgdata
.image
= s_image
;
1147 S
.iwidth
= s_iwidth
;
1148 S
.iheight
= s_iheight
;
1150 T
.theight
= S
.height
;
1151 S
.height
= s_height
;
1153 T
.tcolors
= P1
.colors
;
1154 P1
.colors
= s_colors
;
1156 P1
.filters
= s_filters
;
1165 void LibRaw::foveon_thumb_loader (void)
1167 unsigned bwide
, row
, col
, bitbuf
=0, bit
=1, c
, i
;
1168 struct decode
*dindex
;
1171 if(T
.thumb
) free(T
.thumb
);
1177 if (bwide
< T
.twidth
*3) return;
1178 T
.thumb
= (char*)malloc(3*T
.twidth
* T
.theight
);
1179 merror (T
.thumb
, "foveon_thumb()");
1180 char *buf
= (char*)malloc(bwide
);
1181 merror (buf
, "foveon_thumb()");
1182 for (row
=0; row
< T
.theight
; row
++)
1184 ID
.input
->read(buf
, 1, bwide
);
1185 memmove(T
.thumb
+(row
*T
.twidth
*3),buf
,T
.twidth
*3);
1188 T
.tlength
= 3*T
.twidth
* T
.theight
;
1189 T
.tformat
= LIBRAW_THUMBNAIL_BITMAP
;
1194 foveon_decoder (256, 0);
1195 T
.thumb
= (char*)malloc(3*T
.twidth
* T
.theight
);
1196 char *bufp
= T
.thumb
;
1197 merror (T
.thumb
, "foveon_thumb()");
1198 for (row
=0; row
< T
.theight
; row
++)
1200 memset (pred
, 0, sizeof pred
);
1202 for (bit
=col
=0; col
< T
.twidth
; col
++)
1205 for (dindex
=first_decode
; dindex
->branch
[0]; )
1207 if ((bit
= (bit
-1) & 31) == 31)
1208 for (i
=0; i
< 4; i
++)
1209 bitbuf
= (bitbuf
<< 8) + ID
.input
->get_char();
1210 dindex
= dindex
->branch
[bitbuf
>> bit
& 1];
1212 pred
[c
] += dindex
->leaf
;
1216 T
.tformat
= LIBRAW_THUMBNAIL_BITMAP
;
1217 T
.tlength
= 3*T
.twidth
* T
.theight
;
1223 // Äîñòà åò thumbnail èç ôà éëà , ñòà âèò thumb_format â ñîîòâåòñòâèè ñ ôîðìà òîì
1224 int LibRaw::unpack_thumb(void)
1226 CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY
);
1227 CHECK_ORDER_BIT(LIBRAW_PROGRESS_THUMB_LOAD
);
1232 return LIBRAW_NO_THUMBNAIL
;
1234 else if (thumb_load_raw
)
1236 kodak_thumb_loader();
1237 T
.tformat
= LIBRAW_THUMBNAIL_BITMAP
;
1238 SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD
);
1243 ID
.input
->seek(ID
.toffset
, SEEK_SET
);
1244 if ( write_thumb
== &LibRaw::jpeg_thumb
)
1246 if(T
.thumb
) free(T
.thumb
);
1247 T
.thumb
= (char *) malloc (T
.tlength
);
1248 merror (T
.thumb
, "jpeg_thumb()");
1249 ID
.input
->read (T
.thumb
, 1, T
.tlength
);
1251 T
.tformat
= LIBRAW_THUMBNAIL_JPEG
;
1252 SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD
);
1255 else if (write_thumb
== &LibRaw::ppm_thumb
)
1257 T
.tlength
= T
.twidth
* T
.theight
*3;
1258 if(T
.thumb
) free(T
.thumb
);
1260 T
.thumb
= (char *) malloc (T
.tlength
);
1261 merror (T
.thumb
, "ppm_thumb()");
1263 ID
.input
->read(T
.thumb
, 1, T
.tlength
);
1265 T
.tformat
= LIBRAW_THUMBNAIL_BITMAP
;
1266 SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD
);
1270 else if (write_thumb
== &LibRaw::foveon_thumb
)
1272 foveon_thumb_loader();
1273 // may return with error, so format is set in
1274 // foveon thumb loader itself
1275 SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD
);
1278 // else if -- all other write_thumb cases!
1281 return LIBRAW_UNSUPPORTED_THUMBNAIL
;
1285 return LIBRAW_UNSUPPORTED_THUMBNAIL
;
1287 catch ( LibRaw_exceptions err
) {
1288 EXCEPTION_HANDLER(err
);
1293 int LibRaw::dcraw_thumb_writer(const char *fname
)
1295 // CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD);
1300 FILE *tfp
= fopen(fname
,"wb");
1308 return LIBRAW_OUT_OF_ORDER_CALL
;
1314 case LIBRAW_THUMBNAIL_JPEG
:
1315 jpeg_thumb_writer (tfp
,T
.thumb
,T
.tlength
);
1317 case LIBRAW_THUMBNAIL_BITMAP
:
1318 fprintf (tfp
, "P6\n%d %d\n255\n", T
.twidth
, T
.theight
);
1319 fwrite (T
.thumb
, 1, T
.tlength
, tfp
);
1323 return LIBRAW_UNSUPPORTED_THUMBNAIL
;
1328 catch ( LibRaw_exceptions err
) {
1330 EXCEPTION_HANDLER(err
);
1334 int LibRaw::adjust_sizes_info_only(void)
1336 CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY
);
1337 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_FUJI_ROTATE
);
1338 if (O
.use_fuji_rotate
)
1342 // restore saved values
1345 S
.height
= IO
.fheight
;
1346 S
.width
= IO
.fwidth
;
1347 S
.iheight
= (S
.height
+ IO
.shrink
) >> IO
.shrink
;
1348 S
.iwidth
= (S
.width
+ IO
.shrink
) >> IO
.shrink
;
1349 S
.raw_height
-= 2*S
.top_margin
;
1350 IO
.fheight
= IO
.fwidth
= 0; // prevent repeated calls
1353 IO
.fuji_width
= (IO
.fuji_width
- 1 + IO
.shrink
) >> IO
.shrink
;
1354 S
.iwidth
= (ushort
)(IO
.fuji_width
/ sqrt(0.5));
1355 S
.iheight
= (ushort
)( (S
.iheight
- IO
.fuji_width
) / sqrt(0.5));
1359 if (S
.pixel_aspect
< 1) S
.iheight
= (ushort
)( S
.iheight
/ S
.pixel_aspect
+ 0.5);
1360 if (S
.pixel_aspect
> 1) S
.iwidth
= (ushort
) (S
.iwidth
* S
.pixel_aspect
+ 0.5);
1363 SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE
);
1366 unsigned short t
= S
.iheight
;
1369 SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP
);
1374 int LibRaw::rotate_fuji_raw(void)
1376 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW
);
1377 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
1380 if(!IO
.fwidth
) return LIBRAW_SUCCESS
;
1382 ushort (*newimage
)[4];
1383 ushort fiwidth
,fiheight
;
1385 fiheight
= (IO
.fheight
+ IO
.shrink
) >> IO
.shrink
;
1386 fiwidth
= (IO
.fwidth
+ IO
.shrink
) >> IO
.shrink
;
1388 newimage
= (ushort (*)[4]) calloc (fiheight
*fiwidth
, sizeof (*newimage
));
1389 merror(newimage
,"rotate_fuji_raw()");
1390 for(row
=0;row
<S
.height
;row
++)
1392 for(col
=0;col
<S
.width
;col
++)
1395 if (libraw_internal_data
.unpacker_data
.fuji_layout
) {
1396 r
= IO
.fuji_width
- 1 - col
+ (row
>> 1);
1397 c
= col
+ ((row
+1) >> 1);
1399 r
= IO
.fuji_width
- 1 + row
- (col
>> 1);
1400 c
= row
+ ((col
+1) >> 1);
1402 newimage
[((r
) >> IO
.shrink
)*fiwidth
+ ((c
) >> IO
.shrink
)][FC(r
,c
)] =
1403 imgdata
.image
[((row
) >> IO
.shrink
)*S
.iwidth
+ ((col
) >> IO
.shrink
)][FC(r
,c
)];
1406 // restore fuji sizes!
1407 S
.height
= IO
.fheight
;
1408 S
.width
= IO
.fwidth
;
1409 S
.iheight
= (S
.height
+ IO
.shrink
) >> IO
.shrink
;
1410 S
.iwidth
= (S
.width
+ IO
.shrink
) >> IO
.shrink
;
1411 S
.raw_height
-= 2*S
.top_margin
;
1412 IO
.fheight
= IO
.fwidth
= 0; // prevent repeated calls
1414 free(imgdata
.image
);
1415 imgdata
.image
= newimage
;
1416 return LIBRAW_SUCCESS
;
1421 int LibRaw::dcraw_process(void)
1426 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW
);
1427 CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
1435 if(!own_filtering_supported() && (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
))
1436 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC_BIT
; // turn on black and zeroes filtering
1439 O
.four_color_rgb
= 1;
1441 if (!(O
.filtering_mode
& LIBRAW_FILTERING_NOZEROES
) && IO
.zero_is_bad
)
1444 SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES
);
1448 bad_pixels(O
.bad_pixels
);
1449 SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS
);
1453 subtract (O
.dark_frame
);
1454 SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME
);
1457 quality
= 2 + !IO
.fuji_width
;
1459 if(O
.filtering_mode
& LIBRAW_FILTERING_NOBLACKS
)
1462 if (O
.user_qual
>= 0) quality
= O
.user_qual
;
1463 if (O
.user_black
>= 0) C
.black
= O
.user_black
;
1464 if (O
.user_sat
> 0) C
.maximum
= O
.user_sat
;
1466 if (P1
.is_foveon
&& !O
.document_mode
)
1468 foveon_interpolate();
1469 SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE
);
1472 if (!P1
.is_foveon
&& O
.document_mode
< 2)
1475 SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS
);
1479 SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE
);
1481 if (P1
.filters
&& !O
.document_mode
)
1485 else if (quality
== 1 || P1
.colors
> 3)
1487 else if (quality
== 2)
1491 SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE
);
1495 for (P1
.colors
=3, i
=0; i
< S
.height
* S
.width
; i
++)
1496 imgdata
.image
[i
][1] = (imgdata
.image
[i
][1] + imgdata
.image
[i
][3]) >> 1;
1497 SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN
);
1505 SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER
);
1508 if (O
.highlight
== 2)
1511 SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS
);
1514 if (O
.highlight
> 2)
1516 recover_highlights();
1517 SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS
);
1520 if (O
.use_fuji_rotate
)
1523 SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE
);
1526 if(!libraw_internal_data
.output_data
.histogram
)
1528 libraw_internal_data
.output_data
.histogram
= (int (*)[LIBRAW_HISTOGRAM_SIZE
]) malloc(sizeof(*libraw_internal_data
.output_data
.histogram
)*4);
1529 merror(libraw_internal_data
.output_data
.histogram
,"LibRaw::dcraw_process()");
1532 if(O
.camera_profile
)
1534 apply_profile(O
.camera_profile
,O
.output_profile
);
1535 SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE
);
1540 SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB
);
1542 if (O
.use_fuji_rotate
)
1545 SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH
);
1547 if (O
.filtering_mode
& LIBRAW_FILTERING_AUTOMATIC_BIT
)
1548 O
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC
; // restore automated mode
1551 catch ( LibRaw_exceptions err
) {
1552 EXCEPTION_HANDLER(err
);
1556 // Supported cameras:
1557 static const char *static_camera_list
[] =
1559 "Adobe Digital Negative (DNG)",
1560 "Apple QuickTake 100",
1561 "Apple QuickTake 150",
1562 "Apple QuickTake 200",
1568 "Canon PowerShot 600",
1569 "Canon PowerShot A5",
1570 "Canon PowerShot A5 Zoom",
1571 "Canon PowerShot A50",
1572 "Canon PowerShot A460 (CHDK hack)",
1573 "Canon PowerShot A530 (CHDK hack)",
1574 "Canon PowerShot A610 (CHDK hack)",
1575 "Canon PowerShot A620 (CHDK hack)",
1576 "Canon PowerShot A630 (CHDK hack)",
1577 "Canon PowerShot A640 (CHDK hack)",
1578 "Canon PowerShot A650 (CHDK hack)",
1579 "Canon PowerShot A710 IS (CHDK hack)",
1580 "Canon PowerShot A720 IS (CHDK hack)",
1581 "Canon PowerShot Pro70",
1582 "Canon PowerShot Pro90 IS",
1583 "Canon PowerShot G1",
1584 "Canon PowerShot G2",
1585 "Canon PowerShot G3",
1586 "Canon PowerShot G5",
1587 "Canon PowerShot G6",
1588 "Canon PowerShot G7 (CHDK hack)",
1589 "Canon PowerShot G9",
1590 "Canon PowerShot G10",
1591 "Canon PowerShot S2 IS (CHDK hack)",
1592 "Canon PowerShot S3 IS (CHDK hack)",
1593 "Canon PowerShot S5 IS (CHDK hack)",
1594 "Canon PowerShot SD300 (CHDK hack)",
1595 "Canon PowerShot S30",
1596 "Canon PowerShot S40",
1597 "Canon PowerShot S45",
1598 "Canon PowerShot S50",
1599 "Canon PowerShot S60",
1600 "Canon PowerShot S70",
1601 "Canon PowerShot Pro1",
1605 "Canon EOS 5D Mark II",
1611 "Canon EOS 300D / Digital Rebel / Kiss Digital",
1612 "Canon EOS 350D / Digital Rebel XT / Kiss Digital N",
1613 "Canon EOS 400D / Digital Rebel XTi / Kiss Digital X",
1614 "Canon EOS 450D / Digital Rebel XSi / Kiss Digital X2",
1615 "Canon EOS 1000D / Digital Rebel XS / Kiss Digital F",
1619 "Canon EOS-1D Mark II",
1620 "Canon EOS-1D Mark III",
1621 "Canon EOS-1D Mark II N",
1622 "Canon EOS-1Ds Mark II",
1623 "Canon EOS-1Ds Mark III",
1636 "Casio Exlim Pro 505",
1637 "Casio Exlim Pro 600",
1638 "Casio Exlim Pro 700",
1640 "Creative PC-CAM 600",
1643 "Fuji FinePix E550",
1644 "Fuji FinePix E900",
1645 "Fuji FinePix F700",
1646 "Fuji FinePix F710",
1647 "Fuji FinePix F800",
1648 "Fuji FinePix F810",
1649 "Fuji FinePix S2Pro",
1650 "Fuji FinePix S3Pro",
1651 "Fuji FinePix S5Pro",
1652 "Fuji FinePix S20Pro",
1653 "Fuji FinePix S100FS",
1654 "Fuji FinePix S5000",
1655 "Fuji FinePix S5100/S5500",
1656 "Fuji FinePix S5200/S5600",
1657 "Fuji FinePix S6000fd",
1658 "Fuji FinePix S7000",
1659 "Fuji FinePix S9000/S9500",
1660 "Fuji FinePix S9100/S9600",
1665 "Imacon Ixpress 16-megapixel",
1666 "Imacon Ixpress 22-megapixel",
1667 "Imacon Ixpress 39-megapixel",
1669 "Kodak DC20 (see Oliver Hartman's page)",
1670 "Kodak DC25 (see Jun-ichiro Itoh's page)",
1673 "Kodak DC120 (also try kdc2tiff)",
1696 "Kodak DCS Pro 14n",
1697 "Kodak DCS Pro 14nx",
1698 "Kodak DCS Pro SLR/c",
1699 "Kodak DCS Pro SLR/n",
1729 "Logitech Fotoman Pixtura",
1735 "Minolta DiMAGE 7i",
1736 "Minolta DiMAGE 7Hi",
1737 "Minolta DiMAGE A1",
1738 "Minolta DiMAGE A2",
1739 "Minolta DiMAGE A200",
1740 "Minolta DiMAGE G400",
1741 "Minolta DiMAGE G500",
1742 "Minolta DiMAGE G530",
1743 "Minolta DiMAGE G600",
1744 "Minolta DiMAGE Z2",
1745 "Minolta Alpha/Dynax/Maxxum 5D",
1746 "Minolta Alpha/Dynax/Maxxum 7D",
1768 "Nikon E700 (\"DIAG RAW\" hack)",
1769 "Nikon E800 (\"DIAG RAW\" hack)",
1770 "Nikon E880 (\"DIAG RAW\" hack)",
1771 "Nikon E900 (\"DIAG RAW\" hack)",
1772 "Nikon E950 (\"DIAG RAW\" hack)",
1773 "Nikon E990 (\"DIAG RAW\" hack)",
1774 "Nikon E995 (\"DIAG RAW\" hack)",
1775 "Nikon E2100 (\"DIAG RAW\" hack)",
1776 "Nikon E2500 (\"DIAG RAW\" hack)",
1777 "Nikon E3200 (\"DIAG RAW\" hack)",
1778 "Nikon E3700 (\"DIAG RAW\" hack)",
1779 "Nikon E4300 (\"DIAG RAW\" hack)",
1780 "Nikon E4500 (\"DIAG RAW\" hack)",
1787 "Nikon Coolpix P6000",
1788 "Nikon Coolpix S6 (\"DIAG RAW\" hack)",
1794 "Olympus C70Z,C7000Z",
1818 "Panasonic DMC-FZ8",
1819 "Panasonic DMC-FZ18",
1820 "Panasonic DMC-FZ28",
1821 "Panasonic DMC-FZ30",
1822 "Panasonic DMC-FZ50",
1823 "Panasonic DMC-FX150",
1826 "Panasonic DMC-L10",
1827 "Panasonic DMC-LC1",
1828 "Panasonic DMC-LX1",
1829 "Panasonic DMC-LX2",
1830 "Panasonic DMC-LX3",
1839 "Pentax K100D Super",
1844 "Pentax Optio 33WR",
1845 "Pentax Optio 750Z",
1846 "Phase One LightPhase",
1860 "Samsung S85 (hacked)",
1861 "Sarnoff 4096x5440",
1869 "SMaL Ultra-Pocket 3",
1870 "SMaL Ultra-Pocket 4",
1871 "SMaL Ultra-Pocket 5",
1886 const char** LibRaw::cameraList() { return static_camera_list
;}
1887 int LibRaw::cameraCount() { return (sizeof(static_camera_list
)/sizeof(static_camera_list
[0]))-1; }
1890 const char * LibRaw::strprogress(enum LibRaw_progress p
)
1894 case LIBRAW_PROGRESS_START
:
1896 case LIBRAW_PROGRESS_OPEN
:
1897 return "Opening file";
1898 case LIBRAW_PROGRESS_IDENTIFY
:
1899 return "Reading metadata";
1900 case LIBRAW_PROGRESS_SIZE_ADJUST
:
1901 return "Adjusting size";
1902 case LIBRAW_PROGRESS_LOAD_RAW
:
1903 return "Reading RAW data";
1904 case LIBRAW_PROGRESS_REMOVE_ZEROES
:
1905 return "Clearing zero values";
1906 case LIBRAW_PROGRESS_BAD_PIXELS
:
1907 return "Removing dead pixels";
1908 case LIBRAW_PROGRESS_DARK_FRAME
:
1909 return "Subtracting dark frame data";
1910 case LIBRAW_PROGRESS_FOVEON_INTERPOLATE
:
1911 return "Interpolating Foveon sensor data";
1912 case LIBRAW_PROGRESS_SCALE_COLORS
:
1913 return "Scaling colors";
1914 case LIBRAW_PROGRESS_PRE_INTERPOLATE
:
1915 return "Pre-interpolating";
1916 case LIBRAW_PROGRESS_INTERPOLATE
:
1917 return "Interpolating";
1918 case LIBRAW_PROGRESS_MIX_GREEN
:
1919 return "Mixing green channels";
1920 case LIBRAW_PROGRESS_MEDIAN_FILTER
:
1921 return "Median filter";
1922 case LIBRAW_PROGRESS_HIGHLIGHTS
:
1923 return "Highlight recovery";
1924 case LIBRAW_PROGRESS_FUJI_ROTATE
:
1925 return "Rotating Fuji diagonal data";
1926 case LIBRAW_PROGRESS_FLIP
:
1927 return "Flipping image";
1928 case LIBRAW_PROGRESS_APPLY_PROFILE
:
1929 return "ICC conversion";
1930 case LIBRAW_PROGRESS_CONVERT_RGB
:
1931 return "Converting to RGB";
1932 case LIBRAW_PROGRESS_STRETCH
:
1933 return "Stretching image";
1934 case LIBRAW_PROGRESS_THUMB_LOAD
:
1935 return "Loading thumbnail";
1937 return "Some strange things";