[93] | 1 | /*
|
---|
| 2 | * File: ximaraw.cpp
|
---|
| 3 | * Purpose: Platform Independent RAW Image Class Loader
|
---|
| 4 | * 16/Dec/2007 Davide Pizzolato - www.xdp.it
|
---|
| 5 | * CxImage version 6.0.0 02/Feb/2008
|
---|
| 6 | *
|
---|
| 7 | * CxImageRAW (c) May/2006 pdw63
|
---|
| 8 | *
|
---|
| 9 | * based on dcraw.c -- Dave Coffin's raw photo decoder
|
---|
| 10 | * Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net
|
---|
| 11 | */
|
---|
| 12 |
|
---|
| 13 | #include "ximaraw.h"
|
---|
| 14 |
|
---|
| 15 | #if CXIMAGE_SUPPORT_RAW
|
---|
| 16 |
|
---|
| 17 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 18 | #if CXIMAGE_SUPPORT_DECODE
|
---|
| 19 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 20 | bool CxImageRAW::Decode(CxFile *hFile)
|
---|
| 21 | {
|
---|
| 22 | if (hFile==NULL)
|
---|
| 23 | return false;
|
---|
| 24 |
|
---|
| 25 | DCRAW dcr;
|
---|
| 26 |
|
---|
| 27 | cx_try
|
---|
| 28 | {
|
---|
| 29 | // initialization
|
---|
| 30 | dcr_init_dcraw(&dcr);
|
---|
| 31 |
|
---|
| 32 | dcr.opt.user_qual = GetCodecOption(CXIMAGE_FORMAT_RAW) & 0x03;
|
---|
| 33 |
|
---|
| 34 | // setup variables for debugging
|
---|
| 35 | char szClass[] = "CxImageRAW";
|
---|
| 36 | dcr.ifname = szClass;
|
---|
| 37 | dcr.sz_error = info.szLastError;
|
---|
| 38 |
|
---|
| 39 | // setup library options, see dcr_print_manual for the available switches
|
---|
| 40 | // call dcr_parse_command_line_options(&dcr,0,0,0) to set default options
|
---|
| 41 | // if (dcr_parse_command_line_options(&dcr,argc,argv,&arg))
|
---|
| 42 | if (dcr_parse_command_line_options(&dcr,0,0,0)){
|
---|
| 43 | cx_throw("CxImageRAW: unknown option");
|
---|
| 44 | }
|
---|
| 45 |
|
---|
| 46 | // set return point for error handling
|
---|
| 47 | if (setjmp (dcr.failure)) {
|
---|
| 48 | cx_throw("");
|
---|
| 49 | }
|
---|
| 50 |
|
---|
| 51 | // install file manager
|
---|
| 52 | CxFileRaw src(hFile,&dcr);
|
---|
| 53 |
|
---|
| 54 | // check file header
|
---|
| 55 | dcr_identify(&dcr);
|
---|
| 56 |
|
---|
| 57 | if(!dcr.is_raw){
|
---|
| 58 | cx_throw("CxImageRAW: not a raw image");
|
---|
| 59 | }
|
---|
| 60 |
|
---|
| 61 | if (dcr.load_raw == NULL) {
|
---|
| 62 | cx_throw("CxImageRAW: missing raw decoder");
|
---|
| 63 | }
|
---|
| 64 |
|
---|
| 65 | // verify special case
|
---|
| 66 | if (dcr.load_raw == dcr_kodak_ycbcr_load_raw) {
|
---|
| 67 | dcr.height += dcr.height & 1;
|
---|
| 68 | dcr.width += dcr.width & 1;
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 | if (info.nEscape == -1){
|
---|
| 72 | head.biWidth = dcr.width;
|
---|
| 73 | head.biHeight= dcr.height;
|
---|
| 74 | info.dwType = CXIMAGE_FORMAT_RAW;
|
---|
| 75 | cx_throw("output dimensions returned");
|
---|
| 76 | }
|
---|
| 77 |
|
---|
| 78 | // shrinked decoding available and requested?
|
---|
| 79 | dcr.shrink = dcr.filters && (dcr.opt.half_size || dcr.opt.threshold || dcr.opt.aber[0] != 1 || dcr.opt.aber[2] != 1);
|
---|
| 80 | dcr.iheight = (dcr.height + dcr.shrink) >> dcr.shrink;
|
---|
| 81 | dcr.iwidth = (dcr.width + dcr.shrink) >> dcr.shrink;
|
---|
| 82 |
|
---|
| 83 | // install custom camera matrix
|
---|
| 84 | if (dcr.opt.use_camera_matrix && dcr.cmatrix[0][0] > 0.25) {
|
---|
| 85 | memcpy (dcr.rgb_cam, dcr.cmatrix, sizeof dcr.cmatrix);
|
---|
| 86 | dcr.raw_color = 0;
|
---|
| 87 | }
|
---|
| 88 |
|
---|
| 89 | // allocate memory for the image
|
---|
| 90 | dcr.image = (ushort (*)[4]) calloc (dcr.iheight*dcr.iwidth, sizeof *dcr.image);
|
---|
| 91 | dcr_merror (&dcr, dcr.image, szClass);
|
---|
| 92 |
|
---|
| 93 | if (dcr.meta_length) {
|
---|
| 94 | dcr.meta_data = (char *) malloc (dcr.meta_length);
|
---|
| 95 | dcr_merror (&dcr, dcr.meta_data, szClass);
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | // start image decoder
|
---|
| 99 | hFile->Seek(dcr.data_offset, SEEK_SET);
|
---|
| 100 | (*dcr.load_raw)(&dcr);
|
---|
| 101 |
|
---|
| 102 | // post processing
|
---|
| 103 | if (dcr.zero_is_bad) dcr_remove_zeroes(&dcr);
|
---|
| 104 |
|
---|
| 105 | dcr_bad_pixels(&dcr);
|
---|
| 106 |
|
---|
| 107 | if (dcr.opt.dark_frame) dcr_subtract (&dcr,dcr.opt.dark_frame);
|
---|
| 108 |
|
---|
| 109 | dcr.quality = 2 + !dcr.fuji_width;
|
---|
| 110 |
|
---|
| 111 | if (dcr.opt.user_qual >= 0) dcr.quality = dcr.opt.user_qual;
|
---|
| 112 |
|
---|
| 113 | if (dcr.opt.user_black >= 0) dcr.black = dcr.opt.user_black;
|
---|
| 114 |
|
---|
| 115 | #ifdef COLORCHECK
|
---|
| 116 | dcr_colorcheck(&dcr);
|
---|
| 117 | #endif
|
---|
| 118 |
|
---|
| 119 | #if RESTRICTED
|
---|
| 120 | if (dcr.is_foveon && !dcr.opt.document_mode) dcr_foveon_interpolate(&dcr);
|
---|
| 121 | #endif
|
---|
| 122 |
|
---|
| 123 | if (!dcr.is_foveon && dcr.opt.document_mode < 2) dcr_scale_colors(&dcr);
|
---|
| 124 |
|
---|
| 125 | // pixel interpolation and filters
|
---|
| 126 | dcr_pre_interpolate(&dcr);
|
---|
| 127 |
|
---|
| 128 | if (dcr.filters && !dcr.opt.document_mode) {
|
---|
| 129 | if (dcr.quality == 0)
|
---|
| 130 | dcr_lin_interpolate(&dcr);
|
---|
| 131 | else if (dcr.quality == 1 || dcr.colors > 3)
|
---|
| 132 | dcr_vng_interpolate(&dcr);
|
---|
| 133 | else if (dcr.quality == 2)
|
---|
| 134 | dcr_ppg_interpolate(&dcr);
|
---|
| 135 | else
|
---|
| 136 | dcr_ahd_interpolate(&dcr);
|
---|
| 137 | }
|
---|
| 138 |
|
---|
| 139 | if (dcr.mix_green) {
|
---|
| 140 | long i;
|
---|
| 141 | for (dcr.colors=3, i=0; i < dcr.height*dcr.width; i++) {
|
---|
| 142 | dcr.image[i][1] = (dcr.image[i][1] + dcr.image[i][3]) >> 1;
|
---|
| 143 | }
|
---|
| 144 | }
|
---|
| 145 |
|
---|
| 146 | if (!dcr.is_foveon && dcr.colors == 3) dcr_median_filter(&dcr);
|
---|
| 147 |
|
---|
| 148 | if (!dcr.is_foveon && dcr.opt.highlight == 2) dcr_blend_highlights(&dcr);
|
---|
| 149 |
|
---|
| 150 | if (!dcr.is_foveon && dcr.opt.highlight > 2) dcr_recover_highlights(&dcr);
|
---|
| 151 |
|
---|
| 152 | if (dcr.opt.use_fuji_rotate) dcr_fuji_rotate(&dcr);
|
---|
| 153 |
|
---|
| 154 | #ifndef NO_LCMS
|
---|
| 155 | if (dcr.opt.cam_profile) dcr_apply_profile (dcr.opt.cam_profile, dcr.opt.out_profile);
|
---|
| 156 | #endif
|
---|
| 157 |
|
---|
| 158 | // final conversion
|
---|
| 159 | dcr_convert_to_rgb(&dcr);
|
---|
| 160 |
|
---|
| 161 | if (dcr.opt.use_fuji_rotate) dcr_stretch(&dcr);
|
---|
| 162 |
|
---|
| 163 | dcr.iheight = dcr.height;
|
---|
| 164 | dcr.iwidth = dcr.width;
|
---|
| 165 | if (dcr.flip & 4) SWAP(dcr.height,dcr.width);
|
---|
| 166 |
|
---|
| 167 | // ready to transfer data from dcr.image
|
---|
| 168 | if (!Create(dcr.width,dcr.height,24,CXIMAGE_FORMAT_RAW)){
|
---|
| 169 | cx_throw("");
|
---|
| 170 | }
|
---|
| 171 |
|
---|
| 172 | uchar *ppm = (uchar *) calloc (dcr.width, dcr.colors*dcr.opt.output_bps/8);
|
---|
| 173 | ushort *ppm2 = (ushort *) ppm;
|
---|
| 174 | dcr_merror (&dcr, ppm, szClass);
|
---|
| 175 |
|
---|
| 176 | uchar lut[0x10000];
|
---|
| 177 | if (dcr.opt.output_bps == 8) dcr_gamma_lut (&dcr, lut);
|
---|
| 178 |
|
---|
| 179 | long c, row, col, soff, rstep, cstep;
|
---|
| 180 | soff = dcr_flip_index (&dcr, 0, 0);
|
---|
| 181 | cstep = dcr_flip_index (&dcr, 0, 1) - soff;
|
---|
| 182 | rstep = dcr_flip_index (&dcr, 1, 0) - dcr_flip_index (&dcr, 0, dcr.width);
|
---|
| 183 | for (row=0; row < dcr.height; row++, soff += rstep) {
|
---|
| 184 | for (col=0; col < dcr.width; col++, soff += cstep) {
|
---|
| 185 | if (dcr.opt.output_bps == 8)
|
---|
| 186 | for (c=0; c < dcr.colors; c++) ppm [col*dcr.colors+c] = lut[dcr.image[soff][c]];
|
---|
| 187 | else
|
---|
| 188 | for (c=0; c < dcr.colors; c++) ppm2[col*dcr.colors+c] = dcr.image[soff][c];
|
---|
| 189 | }
|
---|
| 190 | if (dcr.opt.output_bps == 16 && !dcr.opt.output_tiff && htons(0x55aa) != 0x55aa)
|
---|
| 191 | _swab ((char*)ppm2, (char*)ppm2, dcr.width*dcr.colors*2);
|
---|
| 192 |
|
---|
| 193 | DWORD size = dcr.width * (dcr.colors*dcr.opt.output_bps/8);
|
---|
| 194 | RGBtoBGR(ppm,size);
|
---|
| 195 | memcpy(GetBits(dcr.height - 1 - row), ppm, min(size,GetEffWidth()));
|
---|
| 196 | }
|
---|
| 197 | free (ppm);
|
---|
| 198 |
|
---|
| 199 |
|
---|
| 200 | dcr_cleanup_dcraw(&dcr);
|
---|
| 201 |
|
---|
| 202 | } cx_catch {
|
---|
| 203 |
|
---|
| 204 | dcr_cleanup_dcraw(&dcr);
|
---|
| 205 |
|
---|
| 206 | if (strcmp(message,"")) strncpy(info.szLastError,message,255);
|
---|
| 207 | if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_RAW) return true;
|
---|
| 208 | return false;
|
---|
| 209 | }
|
---|
| 210 | /* that's it */
|
---|
| 211 | return true;
|
---|
| 212 | }
|
---|
| 213 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 214 | #endif //CXIMAGE_SUPPORT_DECODE
|
---|
| 215 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 216 | #if CXIMAGE_SUPPORT_ENCODE
|
---|
| 217 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 218 | bool CxImageRAW::Encode(CxFile * hFile)
|
---|
| 219 | {
|
---|
| 220 | if (hFile == NULL) return false;
|
---|
| 221 | strcpy(info.szLastError, "Save RAW not supported");
|
---|
| 222 | return false;
|
---|
| 223 | }
|
---|
| 224 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 225 | #endif // CXIMAGE_SUPPORT_ENCODE
|
---|
| 226 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 227 | #endif // CXIMAGE_SUPPORT_RAW
|
---|
| 228 |
|
---|