3 * Purpose: Platform Independent RAW Image Class Loader
\r
4 * 16/Dec/2007 Davide Pizzolato - www.xdp.it
\r
5 * CxImage version 6.0.0 02/Feb/2008
\r
7 * CxImageRAW (c) May/2006 pdw63
\r
9 * based on dcraw.c -- Dave Coffin's raw photo decoder
\r
10 * Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net
\r
13 #include "ximaraw.h"
\r
15 #if CXIMAGE_SUPPORT_RAW
\r
17 ////////////////////////////////////////////////////////////////////////////////
\r
18 #if CXIMAGE_SUPPORT_DECODE
\r
19 ////////////////////////////////////////////////////////////////////////////////
\r
20 bool CxImageRAW::Decode(CxFile *hFile)
\r
30 dcr_init_dcraw(&dcr);
\r
32 dcr.opt.user_qual = GetCodecOption(CXIMAGE_FORMAT_RAW) & 0x03;
\r
34 // setup variables for debugging
\r
35 char szClass[] = "CxImageRAW";
\r
36 dcr.ifname = szClass;
\r
37 dcr.sz_error = info.szLastError;
\r
39 // setup library options, see dcr_print_manual for the available switches
\r
40 // call dcr_parse_command_line_options(&dcr,0,0,0) to set default options
\r
41 // if (dcr_parse_command_line_options(&dcr,argc,argv,&arg))
\r
42 if (dcr_parse_command_line_options(&dcr,0,0,0)){
\r
43 cx_throw("CxImageRAW: unknown option");
\r
46 // set return point for error handling
\r
47 if (setjmp (dcr.failure)) {
\r
51 // install file manager
\r
52 CxFileRaw src(hFile,&dcr);
\r
54 // check file header
\r
58 cx_throw("CxImageRAW: not a raw image");
\r
61 if (dcr.load_raw == NULL) {
\r
62 cx_throw("CxImageRAW: missing raw decoder");
\r
65 // verify special case
\r
66 if (dcr.load_raw == dcr_kodak_ycbcr_load_raw) {
\r
67 dcr.height += dcr.height & 1;
\r
68 dcr.width += dcr.width & 1;
\r
71 if (info.nEscape == -1){
\r
72 head.biWidth = dcr.width;
\r
73 head.biHeight= dcr.height;
\r
74 info.dwType = CXIMAGE_FORMAT_RAW;
\r
75 cx_throw("output dimensions returned");
\r
78 // shrinked decoding available and requested?
\r
79 dcr.shrink = dcr.filters && (dcr.opt.half_size || dcr.opt.threshold || dcr.opt.aber[0] != 1 || dcr.opt.aber[2] != 1);
\r
80 dcr.iheight = (dcr.height + dcr.shrink) >> dcr.shrink;
\r
81 dcr.iwidth = (dcr.width + dcr.shrink) >> dcr.shrink;
\r
83 // install custom camera matrix
\r
84 if (dcr.opt.use_camera_matrix && dcr.cmatrix[0][0] > 0.25) {
\r
85 memcpy (dcr.rgb_cam, dcr.cmatrix, sizeof dcr.cmatrix);
\r
89 // allocate memory for the image
\r
90 dcr.image = (ushort (*)[4]) calloc (dcr.iheight*dcr.iwidth, sizeof *dcr.image);
\r
91 dcr_merror (&dcr, dcr.image, szClass);
\r
93 if (dcr.meta_length) {
\r
94 dcr.meta_data = (char *) malloc (dcr.meta_length);
\r
95 dcr_merror (&dcr, dcr.meta_data, szClass);
\r
98 // start image decoder
\r
99 hFile->Seek(dcr.data_offset, SEEK_SET);
\r
100 (*dcr.load_raw)(&dcr);
\r
103 if (dcr.zero_is_bad) dcr_remove_zeroes(&dcr);
\r
105 dcr_bad_pixels(&dcr);
\r
107 if (dcr.opt.dark_frame) dcr_subtract (&dcr,dcr.opt.dark_frame);
\r
109 dcr.quality = 2 + !dcr.fuji_width;
\r
111 if (dcr.opt.user_qual >= 0) dcr.quality = dcr.opt.user_qual;
\r
113 if (dcr.opt.user_black >= 0) dcr.black = dcr.opt.user_black;
\r
116 dcr_colorcheck(&dcr);
\r
120 if (dcr.is_foveon && !dcr.opt.document_mode) dcr_foveon_interpolate(&dcr);
\r
123 if (!dcr.is_foveon && dcr.opt.document_mode < 2) dcr_scale_colors(&dcr);
\r
125 // pixel interpolation and filters
\r
126 dcr_pre_interpolate(&dcr);
\r
128 if (dcr.filters && !dcr.opt.document_mode) {
\r
129 if (dcr.quality == 0)
\r
130 dcr_lin_interpolate(&dcr);
\r
131 else if (dcr.quality == 1 || dcr.colors > 3)
\r
132 dcr_vng_interpolate(&dcr);
\r
133 else if (dcr.quality == 2)
\r
134 dcr_ppg_interpolate(&dcr);
\r
136 dcr_ahd_interpolate(&dcr);
\r
139 if (dcr.mix_green) {
\r
141 for (dcr.colors=3, i=0; i < dcr.height*dcr.width; i++) {
\r
142 dcr.image[i][1] = (dcr.image[i][1] + dcr.image[i][3]) >> 1;
\r
146 if (!dcr.is_foveon && dcr.colors == 3) dcr_median_filter(&dcr);
\r
148 if (!dcr.is_foveon && dcr.opt.highlight == 2) dcr_blend_highlights(&dcr);
\r
150 if (!dcr.is_foveon && dcr.opt.highlight > 2) dcr_recover_highlights(&dcr);
\r
152 if (dcr.opt.use_fuji_rotate) dcr_fuji_rotate(&dcr);
\r
155 if (dcr.opt.cam_profile) dcr_apply_profile (dcr.opt.cam_profile, dcr.opt.out_profile);
\r
158 // final conversion
\r
159 dcr_convert_to_rgb(&dcr);
\r
161 if (dcr.opt.use_fuji_rotate) dcr_stretch(&dcr);
\r
163 dcr.iheight = dcr.height;
\r
164 dcr.iwidth = dcr.width;
\r
165 if (dcr.flip & 4) SWAP(dcr.height,dcr.width);
\r
167 // ready to transfer data from dcr.image
\r
168 if (!Create(dcr.width,dcr.height,24,CXIMAGE_FORMAT_RAW)){
\r
172 uchar *ppm = (uchar *) calloc (dcr.width, dcr.colors*dcr.opt.output_bps/8);
\r
173 ushort *ppm2 = (ushort *) ppm;
\r
174 dcr_merror (&dcr, ppm, szClass);
\r
176 uchar lut[0x10000];
\r
177 if (dcr.opt.output_bps == 8) dcr_gamma_lut (&dcr, lut);
\r
179 long c, row, col, soff, rstep, cstep;
\r
180 soff = dcr_flip_index (&dcr, 0, 0);
\r
181 cstep = dcr_flip_index (&dcr, 0, 1) - soff;
\r
182 rstep = dcr_flip_index (&dcr, 1, 0) - dcr_flip_index (&dcr, 0, dcr.width);
\r
183 for (row=0; row < dcr.height; row++, soff += rstep) {
\r
184 for (col=0; col < dcr.width; col++, soff += cstep) {
\r
185 if (dcr.opt.output_bps == 8)
\r
186 for (c=0; c < dcr.colors; c++) ppm [col*dcr.colors+c] = lut[dcr.image[soff][c]];
\r
188 for (c=0; c < dcr.colors; c++) ppm2[col*dcr.colors+c] = dcr.image[soff][c];
\r
190 if (dcr.opt.output_bps == 16 && !dcr.opt.output_tiff && htons(0x55aa) != 0x55aa)
\r
191 _swab ((char*)ppm2, (char*)ppm2, dcr.width*dcr.colors*2);
\r
193 DWORD size = dcr.width * (dcr.colors*dcr.opt.output_bps/8);
\r
194 RGBtoBGR(ppm,size);
\r
195 memcpy(GetBits(dcr.height - 1 - row), ppm, min(size,GetEffWidth()));
\r
200 dcr_cleanup_dcraw(&dcr);
\r
204 dcr_cleanup_dcraw(&dcr);
\r
206 if (strcmp(message,"")) strncpy(info.szLastError,message,255);
\r
207 if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_RAW) return true;
\r
213 ////////////////////////////////////////////////////////////////////////////////
\r
214 #endif //CXIMAGE_SUPPORT_DECODE
\r
215 ////////////////////////////////////////////////////////////////////////////////
\r
216 #if CXIMAGE_SUPPORT_ENCODE
\r
217 ////////////////////////////////////////////////////////////////////////////////
\r
218 bool CxImageRAW::Encode(CxFile * hFile)
\r
220 if (hFile == NULL) return false;
\r
221 strcpy(info.szLastError, "Save RAW not supported");
\r
224 ////////////////////////////////////////////////////////////////////////////////
\r
225 #endif // CXIMAGE_SUPPORT_ENCODE
\r
226 ////////////////////////////////////////////////////////////////////////////////
\r
227 #endif // CXIMAGE_SUPPORT_RAW
\r