File indexing completed on 2025-01-05 03:57:06
0001 /* -*- C++ -*- 0002 * Copyright 2019-2021 LibRaw LLC (info@libraw.org) 0003 * 0004 0005 LibRaw is free software; you can redistribute it and/or modify 0006 it under the terms of the one of two licenses as you choose: 0007 0008 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 0009 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 0010 0011 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 0012 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). 0013 0014 */ 0015 0016 #include "../../internal/libraw_cxx_defs.h" 0017 0018 void LibRaw::raw2image_start() 0019 { 0020 // restore color,sizes and internal data into raw_image fields 0021 memmove(&imgdata.color, &imgdata.rawdata.color, sizeof(imgdata.color)); 0022 memmove(&imgdata.sizes, &imgdata.rawdata.sizes, sizeof(imgdata.sizes)); 0023 memmove(&imgdata.idata, &imgdata.rawdata.iparams, sizeof(imgdata.idata)); 0024 memmove(&libraw_internal_data.internal_output_params, 0025 &imgdata.rawdata.ioparams, 0026 sizeof(libraw_internal_data.internal_output_params)); 0027 0028 if (O.user_flip >= 0) 0029 S.flip = O.user_flip; 0030 0031 switch ((S.flip + 3600) % 360) 0032 { 0033 case 270: 0034 S.flip = 5; 0035 break; 0036 case 180: 0037 S.flip = 3; 0038 break; 0039 case 90: 0040 S.flip = 6; 0041 break; 0042 } 0043 0044 // adjust for half mode! 0045 IO.shrink = 0046 !imgdata.rawdata.color4_image && !imgdata.rawdata.color3_image && 0047 !imgdata.rawdata.float4_image && !imgdata.rawdata.float3_image && 0048 P1.filters && 0049 (O.half_size || ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1))); 0050 0051 S.iheight = (S.height + IO.shrink) >> IO.shrink; 0052 S.iwidth = (S.width + IO.shrink) >> IO.shrink; 0053 } 0054 0055 int LibRaw::raw2image(void) 0056 { 0057 0058 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW); 0059 0060 try 0061 { 0062 raw2image_start(); 0063 0064 if (is_phaseone_compressed() && imgdata.rawdata.raw_alloc) 0065 { 0066 phase_one_allocate_tempbuffer(); 0067 int rc = phase_one_subtract_black((ushort *)imgdata.rawdata.raw_alloc, 0068 imgdata.rawdata.raw_image); 0069 if (rc == 0) 0070 rc = phase_one_correct(); 0071 if (rc != 0) 0072 { 0073 phase_one_free_tempbuffer(); 0074 return rc; 0075 } 0076 } 0077 0078 // free and re-allocate image bitmap 0079 if (imgdata.image) 0080 { 0081 imgdata.image = (ushort(*)[4])realloc( 0082 imgdata.image, S.iheight * S.iwidth * sizeof(*imgdata.image)); 0083 memset(imgdata.image, 0, S.iheight * S.iwidth * sizeof(*imgdata.image)); 0084 } 0085 else 0086 imgdata.image = 0087 (ushort(*)[4])calloc(S.iheight * S.iwidth, sizeof(*imgdata.image)); 0088 0089 0090 libraw_decoder_info_t decoder_info; 0091 get_decoder_info(&decoder_info); 0092 0093 // Copy area size 0094 int copyheight = MAX(0, MIN(int(S.height), int(S.raw_height) - int(S.top_margin))); 0095 int copywidth = MAX(0, MIN(int(S.width), int(S.raw_width) - int(S.left_margin))); 0096 0097 // Move saved bitmap to imgdata.image 0098 if ((imgdata.idata.filters || P1.colors == 1) && imgdata.rawdata.raw_image) 0099 { 0100 if (IO.fuji_width) 0101 { 0102 unsigned r, c; 0103 int row, col; 0104 for (row = 0; row < S.raw_height - S.top_margin * 2; row++) 0105 { 0106 for (col = 0; 0107 col < IO.fuji_width 0108 << int(!libraw_internal_data.unpacker_data.fuji_layout); 0109 col++) 0110 { 0111 if (libraw_internal_data.unpacker_data.fuji_layout) 0112 { 0113 r = IO.fuji_width - 1 - col + (row >> 1); 0114 c = col + ((row + 1) >> 1); 0115 } 0116 else 0117 { 0118 r = IO.fuji_width - 1 + row - (col >> 1); 0119 c = row + ((col + 1) >> 1); 0120 } 0121 if (r < S.height && c < S.width && col + int(S.left_margin) < int(S.raw_width)) 0122 imgdata.image[((r) >> IO.shrink) * S.iwidth + ((c) >> IO.shrink)] 0123 [FC(r, c)] = 0124 imgdata.rawdata 0125 .raw_image[(row + S.top_margin) * S.raw_pitch / 2 + 0126 (col + S.left_margin)]; 0127 } 0128 } 0129 } 0130 else 0131 { 0132 int row, col; 0133 for (row = 0; row < copyheight; row++) 0134 for (col = 0; col < copywidth; col++) 0135 imgdata.image[((row) >> IO.shrink) * S.iwidth + 0136 ((col) >> IO.shrink)][fcol(row, col)] = 0137 imgdata.rawdata 0138 .raw_image[(row + S.top_margin) * S.raw_pitch / 2 + 0139 (col + S.left_margin)]; 0140 } 0141 } 0142 else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY) 0143 { 0144 if (imgdata.rawdata.color4_image) 0145 { 0146 if (S.width * 8u == S.raw_pitch && S.height == S.raw_height) 0147 memmove(imgdata.image, imgdata.rawdata.color4_image, 0148 S.width * S.height * sizeof(*imgdata.image)); 0149 else 0150 { 0151 for (int row = 0; row < copyheight; row++) 0152 memmove(&imgdata.image[row * S.width], 0153 &imgdata.rawdata 0154 .color4_image[(row + S.top_margin) * S.raw_pitch / 8 + 0155 S.left_margin], 0156 copywidth * sizeof(*imgdata.image)); 0157 } 0158 } 0159 else if (imgdata.rawdata.color3_image) 0160 { 0161 unsigned char *c3image = (unsigned char *)imgdata.rawdata.color3_image; 0162 for (int row = 0; row < copyheight; row++) 0163 { 0164 ushort(*srcrow)[3] = 0165 (ushort(*)[3]) & c3image[(row + S.top_margin) * S.raw_pitch]; 0166 ushort(*dstrow)[4] = (ushort(*)[4]) & imgdata.image[row * S.width]; 0167 for (int col = 0; col < copywidth; col++) 0168 { 0169 for (int c = 0; c < 3; c++) 0170 dstrow[col][c] = srcrow[S.left_margin + col][c]; 0171 dstrow[col][3] = 0; 0172 } 0173 } 0174 } 0175 else 0176 { 0177 // legacy decoder, but no data? 0178 throw LIBRAW_EXCEPTION_DECODE_RAW; 0179 } 0180 } 0181 0182 // Free PhaseOne separate copy allocated at function start 0183 if (is_phaseone_compressed()) 0184 { 0185 phase_one_free_tempbuffer(); 0186 } 0187 // hack - clear later flags! 0188 0189 if (load_raw == &LibRaw::canon_600_load_raw && S.width < S.raw_width) 0190 { 0191 canon_600_correct(); 0192 } 0193 0194 imgdata.progress_flags = 0195 LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN | 0196 LIBRAW_PROGRESS_RAW2_IMAGE | LIBRAW_PROGRESS_IDENTIFY | 0197 LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW; 0198 return 0; 0199 } 0200 catch (const std::bad_alloc&) 0201 { 0202 EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC); 0203 } 0204 catch (const LibRaw_exceptions& err) 0205 { 0206 EXCEPTION_HANDLER(err); 0207 } 0208 } 0209 0210 void LibRaw::copy_fuji_uncropped(unsigned short cblack[4], 0211 unsigned short *dmaxp) 0212 { 0213 #if defined(LIBRAW_USE_OPENMP) 0214 #pragma omp parallel for schedule(dynamic) default(none) firstprivate(cblack) shared(dmaxp) 0215 #endif 0216 for (int row = 0; row < int(S.raw_height) - int(S.top_margin) * 2; row++) 0217 { 0218 int col; 0219 unsigned short ldmax = 0; 0220 for (col = 0; 0221 col < IO.fuji_width << int(!libraw_internal_data.unpacker_data.fuji_layout) 0222 && col + int(S.left_margin) < int(S.raw_width); 0223 col++) 0224 { 0225 unsigned r, c; 0226 if (libraw_internal_data.unpacker_data.fuji_layout) 0227 { 0228 r = IO.fuji_width - 1 - col + (row >> 1); 0229 c = col + ((row + 1) >> 1); 0230 } 0231 else 0232 { 0233 r = IO.fuji_width - 1 + row - (col >> 1); 0234 c = row + ((col + 1) >> 1); 0235 } 0236 if (r < S.height && c < S.width) 0237 { 0238 unsigned short val = 0239 imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 + 0240 (col + S.left_margin)]; 0241 int cc = FC(r, c); 0242 if (val > cblack[cc]) 0243 { 0244 val -= cblack[cc]; 0245 if (val > ldmax) 0246 ldmax = val; 0247 } 0248 else 0249 val = 0; 0250 imgdata.image[((r) >> IO.shrink) * S.iwidth + ((c) >> IO.shrink)][cc] = 0251 val; 0252 } 0253 } 0254 #if defined(LIBRAW_USE_OPENMP) 0255 #pragma omp critical(dataupdate) 0256 #endif 0257 { 0258 if (*dmaxp < ldmax) 0259 *dmaxp = ldmax; 0260 } 0261 } 0262 } 0263 0264 void LibRaw::copy_bayer(unsigned short cblack[4], unsigned short *dmaxp) 0265 { 0266 // Both cropped and uncropped 0267 int maxHeight = MIN(int(S.height),int(S.raw_height)-int(S.top_margin)); 0268 #if defined(LIBRAW_USE_OPENMP) 0269 #pragma omp parallel for schedule(dynamic) default(none) shared(dmaxp) firstprivate(cblack, maxHeight) 0270 #endif 0271 for (int row = 0; row < maxHeight ; row++) 0272 { 0273 int col; 0274 unsigned short ldmax = 0; 0275 for (col = 0; col < S.width && col + S.left_margin < S.raw_width; col++) 0276 { 0277 unsigned short val = 0278 imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 + 0279 (col + S.left_margin)]; 0280 int cc = fcol(row, col); 0281 if (val > cblack[cc]) 0282 { 0283 val -= cblack[cc]; 0284 if (val > ldmax) 0285 ldmax = val; 0286 } 0287 else 0288 val = 0; 0289 imgdata.image[((row) >> IO.shrink) * S.iwidth + ((col) >> IO.shrink)][cc] = val; 0290 } 0291 #if defined(LIBRAW_USE_OPENMP) 0292 #pragma omp critical(dataupdate) 0293 #endif 0294 { 0295 if (*dmaxp < ldmax) 0296 *dmaxp = ldmax; 0297 } 0298 } 0299 } 0300 0301 int LibRaw::raw2image_ex(int do_subtract_black) 0302 { 0303 0304 CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW); 0305 0306 try 0307 { 0308 raw2image_start(); 0309 0310 // Compressed P1 files with bl data! 0311 if (is_phaseone_compressed() && imgdata.rawdata.raw_alloc) 0312 { 0313 phase_one_allocate_tempbuffer(); 0314 int rc = phase_one_subtract_black((ushort *)imgdata.rawdata.raw_alloc, 0315 imgdata.rawdata.raw_image); 0316 if (rc == 0) 0317 rc = phase_one_correct(); 0318 if (rc != 0) 0319 { 0320 phase_one_free_tempbuffer(); 0321 return rc; 0322 } 0323 } 0324 0325 // process cropping 0326 int do_crop = 0; 0327 if (~O.cropbox[2] && ~O.cropbox[3]) 0328 { 0329 int crop[4], c, filt; 0330 for (int q = 0; q < 4; q++) 0331 { 0332 crop[q] = O.cropbox[q]; 0333 if (crop[q] < 0) 0334 crop[q] = 0; 0335 } 0336 0337 if (IO.fuji_width && imgdata.idata.filters >= 1000) 0338 { 0339 crop[0] = (crop[0] / 4) * 4; 0340 crop[1] = (crop[1] / 4) * 4; 0341 if (!libraw_internal_data.unpacker_data.fuji_layout) 0342 { 0343 crop[2] *= sqrt(2.0); 0344 crop[3] /= sqrt(2.0); 0345 } 0346 crop[2] = (crop[2] / 4 + 1) * 4; 0347 crop[3] = (crop[3] / 4 + 1) * 4; 0348 } 0349 else if (imgdata.idata.filters == 1) 0350 { 0351 crop[0] = (crop[0] / 16) * 16; 0352 crop[1] = (crop[1] / 16) * 16; 0353 } 0354 else if (imgdata.idata.filters == LIBRAW_XTRANS) 0355 { 0356 crop[0] = (crop[0] / 6) * 6; 0357 crop[1] = (crop[1] / 6) * 6; 0358 } 0359 do_crop = 1; 0360 0361 crop[2] = MIN(crop[2], (signed)S.width - crop[0]); 0362 crop[3] = MIN(crop[3], (signed)S.height - crop[1]); 0363 if (crop[2] <= 0 || crop[3] <= 0) 0364 throw LIBRAW_EXCEPTION_BAD_CROP; 0365 0366 // adjust sizes! 0367 S.left_margin += crop[0]; 0368 S.top_margin += crop[1]; 0369 S.width = crop[2]; 0370 S.height = crop[3]; 0371 0372 S.iheight = (S.height + IO.shrink) >> IO.shrink; 0373 S.iwidth = (S.width + IO.shrink) >> IO.shrink; 0374 if (!IO.fuji_width && imgdata.idata.filters && 0375 imgdata.idata.filters >= 1000) 0376 { 0377 for (filt = c = 0; c < 16; c++) 0378 filt |= FC((c >> 1) + (crop[1]), (c & 1) + (crop[0])) << c * 2; 0379 imgdata.idata.filters = filt; 0380 } 0381 } 0382 0383 int alloc_width = S.iwidth; 0384 int alloc_height = S.iheight; 0385 0386 if (IO.fuji_width && do_crop) 0387 { 0388 int IO_fw = S.width >> int(!libraw_internal_data.unpacker_data.fuji_layout); 0389 int t_alloc_width = 0390 (S.height >> libraw_internal_data.unpacker_data.fuji_layout) + IO_fw; 0391 int t_alloc_height = t_alloc_width - 1; 0392 alloc_height = (t_alloc_height + IO.shrink) >> IO.shrink; 0393 alloc_width = (t_alloc_width + IO.shrink) >> IO.shrink; 0394 } 0395 int alloc_sz = alloc_width * alloc_height; 0396 0397 if (imgdata.image) 0398 { 0399 imgdata.image = (ushort(*)[4])realloc(imgdata.image, 0400 alloc_sz * sizeof(*imgdata.image)); 0401 memset(imgdata.image, 0, alloc_sz * sizeof(*imgdata.image)); 0402 } 0403 else 0404 imgdata.image = (ushort(*)[4])calloc(alloc_sz, sizeof(*imgdata.image)); 0405 0406 libraw_decoder_info_t decoder_info; 0407 get_decoder_info(&decoder_info); 0408 0409 // Adjust black levels 0410 unsigned short cblack[4] = {0, 0, 0, 0}; 0411 unsigned short dmax = 0; 0412 if (do_subtract_black) 0413 { 0414 adjust_bl(); 0415 for (int i = 0; i < 4; i++) 0416 cblack[i] = (unsigned short)C.cblack[i]; 0417 } 0418 0419 // Max area size to definitely not overrun in/out buffers 0420 int copyheight = MAX(0, MIN(int(S.height), int(S.raw_height) - int(S.top_margin))); 0421 int copywidth = MAX(0, MIN(int(S.width), int(S.raw_width) - int(S.left_margin))); 0422 0423 // Move saved bitmap to imgdata.image 0424 if ((imgdata.idata.filters || P1.colors == 1) && imgdata.rawdata.raw_image) 0425 { 0426 if (IO.fuji_width) 0427 { 0428 if (do_crop) 0429 { 0430 IO.fuji_width = 0431 S.width >> int(!libraw_internal_data.unpacker_data.fuji_layout); 0432 int IO_fwidth = 0433 (S.height >> int(libraw_internal_data.unpacker_data.fuji_layout)) + 0434 IO.fuji_width; 0435 int IO_fheight = IO_fwidth - 1; 0436 0437 int row, col; 0438 for (row = 0; row < S.height; row++) 0439 { 0440 for (col = 0; col < S.width; col++) 0441 { 0442 int r, c; 0443 if (libraw_internal_data.unpacker_data.fuji_layout) 0444 { 0445 r = IO.fuji_width - 1 - col + (row >> 1); 0446 c = col + ((row + 1) >> 1); 0447 } 0448 else 0449 { 0450 r = IO.fuji_width - 1 + row - (col >> 1); 0451 c = row + ((col + 1) >> 1); 0452 } 0453 0454 unsigned short val = 0455 imgdata.rawdata 0456 .raw_image[(row + S.top_margin) * S.raw_pitch / 2 + 0457 (col + S.left_margin)]; 0458 int cc = FCF(row, col); 0459 if (val > cblack[cc]) 0460 { 0461 val -= cblack[cc]; 0462 if (dmax < val) 0463 dmax = val; 0464 } 0465 else 0466 val = 0; 0467 imgdata.image[((r) >> IO.shrink) * alloc_width + 0468 ((c) >> IO.shrink)][cc] = val; 0469 } 0470 } 0471 S.height = IO_fheight; 0472 S.width = IO_fwidth; 0473 S.iheight = (S.height + IO.shrink) >> IO.shrink; 0474 S.iwidth = (S.width + IO.shrink) >> IO.shrink; 0475 S.raw_height -= 2 * S.top_margin; 0476 } 0477 else 0478 { 0479 copy_fuji_uncropped(cblack, &dmax); 0480 } 0481 } // end Fuji 0482 else 0483 { 0484 copy_bayer(cblack, &dmax); 0485 } 0486 } 0487 else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY) 0488 { 0489 if (imgdata.rawdata.color4_image) 0490 { 0491 if (S.raw_pitch != S.width * 8u || S.height != S.raw_height) 0492 { 0493 for (int row = 0; row < copyheight; row++) 0494 memmove(&imgdata.image[row * S.width], 0495 &imgdata.rawdata 0496 .color4_image[(row + S.top_margin) * S.raw_pitch / 8 + 0497 S.left_margin], 0498 copywidth * sizeof(*imgdata.image)); 0499 } 0500 else 0501 { 0502 // legacy is always 4channel and not shrinked! 0503 memmove(imgdata.image, imgdata.rawdata.color4_image, 0504 S.width*copyheight * sizeof(*imgdata.image)); 0505 } 0506 } 0507 else if (imgdata.rawdata.color3_image) 0508 { 0509 unsigned char *c3image = (unsigned char *)imgdata.rawdata.color3_image; 0510 for (int row = 0; row < copyheight; row++) 0511 { 0512 ushort(*srcrow)[3] = 0513 (ushort(*)[3]) & c3image[(row + S.top_margin) * S.raw_pitch]; 0514 ushort(*dstrow)[4] = (ushort(*)[4]) & imgdata.image[row * S.width]; 0515 for (int col = 0; col < copywidth; col++) 0516 { 0517 for (int c = 0; c < 3; c++) 0518 dstrow[col][c] = srcrow[S.left_margin + col][c]; 0519 dstrow[col][3] = 0; 0520 } 0521 } 0522 } 0523 else 0524 { 0525 // legacy decoder, but no data? 0526 throw LIBRAW_EXCEPTION_DECODE_RAW; 0527 } 0528 } 0529 0530 // Free PhaseOne separate copy allocated at function start 0531 if (is_phaseone_compressed()) 0532 { 0533 phase_one_free_tempbuffer(); 0534 } 0535 if (load_raw == &LibRaw::canon_600_load_raw && S.width < S.raw_width) 0536 { 0537 canon_600_correct(); 0538 } 0539 0540 if (do_subtract_black) 0541 { 0542 C.data_maximum = (int)dmax; 0543 C.maximum -= C.black; 0544 // ZERO(C.cblack); 0545 C.cblack[0] = C.cblack[1] = C.cblack[2] = C.cblack[3] = 0; 0546 C.black = 0; 0547 } 0548 0549 // hack - clear later flags! 0550 imgdata.progress_flags = 0551 LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN | 0552 LIBRAW_PROGRESS_RAW2_IMAGE | LIBRAW_PROGRESS_IDENTIFY | 0553 LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW; 0554 return 0; 0555 } 0556 catch (const LibRaw_exceptions& err) 0557 { 0558 EXCEPTION_HANDLER(err); 0559 } 0560 }