File indexing completed on 2025-01-05 03:56:52
0001 /* -*- C++ -*- 0002 * Copyright 2019-2021 LibRaw LLC (info@libraw.org) 0003 * 0004 LibRaw is free software; you can redistribute it and/or modify 0005 it under the terms of the one of two licenses as you choose: 0006 0007 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 0008 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 0009 0010 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 0011 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). 0012 0013 */ 0014 0015 #include "../../internal/libraw_cxx_defs.h" 0016 0017 inline unsigned int __DNG_HalfToFloat(ushort halfValue) 0018 { 0019 int sign = (halfValue >> 15) & 0x00000001; 0020 int exponent = (halfValue >> 10) & 0x0000001f; 0021 int mantissa = halfValue & 0x000003ff; 0022 if (exponent == 0) 0023 { 0024 if (mantissa == 0) 0025 { 0026 return (unsigned int)(sign << 31); 0027 } 0028 else 0029 { 0030 while (!(mantissa & 0x00000400)) 0031 { 0032 mantissa <<= 1; 0033 exponent -= 1; 0034 } 0035 exponent += 1; 0036 mantissa &= ~0x00000400; 0037 } 0038 } 0039 else if (exponent == 31) 0040 { 0041 if (mantissa == 0) 0042 { 0043 return (unsigned int)((sign << 31) | ((0x1eL + 127 - 15) << 23) | 0044 (0x3ffL << 13)); 0045 } 0046 else 0047 { 0048 return 0; 0049 } 0050 } 0051 exponent += (127 - 15); 0052 mantissa <<= 13; 0053 return (unsigned int)((sign << 31) | (exponent << 23) | mantissa); 0054 } 0055 0056 inline unsigned int __DNG_FP24ToFloat(const unsigned char *input) 0057 { 0058 int sign = (input[0] >> 7) & 0x01; 0059 int exponent = (input[0]) & 0x7F; 0060 int mantissa = (((int)input[1]) << 8) | input[2]; 0061 if (exponent == 0) 0062 { 0063 if (mantissa == 0) 0064 { 0065 return (unsigned int)(sign << 31); 0066 } 0067 else 0068 { 0069 while (!(mantissa & 0x00010000)) 0070 { 0071 mantissa <<= 1; 0072 exponent -= 1; 0073 } 0074 exponent += 1; 0075 mantissa &= ~0x00010000; 0076 } 0077 } 0078 else if (exponent == 127) 0079 { 0080 if (mantissa == 0) 0081 { 0082 return (unsigned int)((sign << 31) | ((0x7eL + 128 - 64) << 23) | 0083 (0xffffL << 7)); 0084 } 0085 else 0086 { 0087 // Nan -- Just set to zero. 0088 return 0; 0089 } 0090 } 0091 exponent += (128 - 64); 0092 mantissa <<= 7; 0093 return (uint32_t)((sign << 31) | (exponent << 23) | mantissa); 0094 } 0095 0096 inline void DecodeDeltaBytes(unsigned char *bytePtr, int cols, int channels) 0097 { 0098 if (channels == 1) 0099 { 0100 unsigned char b0 = bytePtr[0]; 0101 bytePtr += 1; 0102 for (int col = 1; col < cols; ++col) 0103 { 0104 b0 += bytePtr[0]; 0105 bytePtr[0] = b0; 0106 bytePtr += 1; 0107 } 0108 } 0109 else if (channels == 3) 0110 { 0111 unsigned char b0 = bytePtr[0]; 0112 unsigned char b1 = bytePtr[1]; 0113 unsigned char b2 = bytePtr[2]; 0114 bytePtr += 3; 0115 for (int col = 1; col < cols; ++col) 0116 { 0117 b0 += bytePtr[0]; 0118 b1 += bytePtr[1]; 0119 b2 += bytePtr[2]; 0120 bytePtr[0] = b0; 0121 bytePtr[1] = b1; 0122 bytePtr[2] = b2; 0123 bytePtr += 3; 0124 } 0125 } 0126 else if (channels == 4) 0127 { 0128 unsigned char b0 = bytePtr[0]; 0129 unsigned char b1 = bytePtr[1]; 0130 unsigned char b2 = bytePtr[2]; 0131 unsigned char b3 = bytePtr[3]; 0132 bytePtr += 4; 0133 for (int col = 1; col < cols; ++col) 0134 { 0135 b0 += bytePtr[0]; 0136 b1 += bytePtr[1]; 0137 b2 += bytePtr[2]; 0138 b3 += bytePtr[3]; 0139 bytePtr[0] = b0; 0140 bytePtr[1] = b1; 0141 bytePtr[2] = b2; 0142 bytePtr[3] = b3; 0143 bytePtr += 4; 0144 } 0145 } 0146 else 0147 { 0148 for (int col = 1; col < cols; ++col) 0149 { 0150 for (int chan = 0; chan < channels; ++chan) 0151 { 0152 bytePtr[chan + channels] += bytePtr[chan]; 0153 } 0154 bytePtr += channels; 0155 } 0156 } 0157 } 0158 0159 #ifdef USE_ZLIB 0160 static void DecodeFPDelta(unsigned char *input, unsigned char *output, int cols, 0161 int channels, int bytesPerSample) 0162 { 0163 DecodeDeltaBytes(input, cols * bytesPerSample, channels); 0164 int32_t rowIncrement = cols * channels; 0165 0166 if (bytesPerSample == 2) 0167 { 0168 0169 #if LibRawBigEndian 0170 const unsigned char *input0 = input; 0171 const unsigned char *input1 = input + rowIncrement; 0172 #else 0173 const unsigned char *input1 = input; 0174 const unsigned char *input0 = input + rowIncrement; 0175 #endif 0176 for (int col = 0; col < rowIncrement; ++col) 0177 { 0178 output[0] = input0[col]; 0179 output[1] = input1[col]; 0180 output += 2; 0181 } 0182 } 0183 else if (bytesPerSample == 3) 0184 { 0185 const unsigned char *input0 = input; 0186 const unsigned char *input1 = input + rowIncrement; 0187 const unsigned char *input2 = input + rowIncrement * 2; 0188 for (int col = 0; col < rowIncrement; ++col) 0189 { 0190 output[0] = input0[col]; 0191 output[1] = input1[col]; 0192 output[2] = input2[col]; 0193 output += 3; 0194 } 0195 } 0196 else 0197 { 0198 #if LibRawBigEndian 0199 const unsigned char *input0 = input; 0200 const unsigned char *input1 = input + rowIncrement; 0201 const unsigned char *input2 = input + rowIncrement * 2; 0202 const unsigned char *input3 = input + rowIncrement * 3; 0203 #else 0204 const unsigned char *input3 = input; 0205 const unsigned char *input2 = input + rowIncrement; 0206 const unsigned char *input1 = input + rowIncrement * 2; 0207 const unsigned char *input0 = input + rowIncrement * 3; 0208 #endif 0209 for (int col = 0; col < rowIncrement; ++col) 0210 { 0211 output[0] = input0[col]; 0212 output[1] = input1[col]; 0213 output[2] = input2[col]; 0214 output[3] = input3[col]; 0215 output += 4; 0216 } 0217 } 0218 } 0219 #endif 0220 0221 static float expandFloats(unsigned char *dst, int tileWidth, int bytesps) 0222 { 0223 float max = 0.f; 0224 if (bytesps == 2) 0225 { 0226 uint16_t *dst16 = (ushort *)dst; 0227 uint32_t *dst32 = (unsigned int *)dst; 0228 float *f32 = (float *)dst; 0229 for (int index = tileWidth - 1; index >= 0; --index) 0230 { 0231 dst32[index] = __DNG_HalfToFloat(dst16[index]); 0232 max = MAX(max, f32[index]); 0233 } 0234 } 0235 else if (bytesps == 3) 0236 { 0237 uint8_t *dst8 = ((unsigned char *)dst) + (tileWidth - 1) * 3; 0238 uint32_t *dst32 = (unsigned int *)dst; 0239 float *f32 = (float *)dst; 0240 for (int index = tileWidth - 1; index >= 0; --index, dst8 -= 3) 0241 { 0242 dst32[index] = __DNG_FP24ToFloat(dst8); 0243 max = MAX(max, f32[index]); 0244 } 0245 } 0246 else if (bytesps == 4) 0247 { 0248 float *f32 = (float *)dst; 0249 for (int index = 0; index < tileWidth; index++) 0250 max = MAX(max, f32[index]); 0251 } 0252 return max; 0253 } 0254 0255 struct tile_stripe_data_t 0256 { 0257 bool tiled, striped; 0258 int tileCnt; 0259 unsigned tileWidth, tileHeight, tilesH, tilesV; 0260 size_t maxBytesInTile; 0261 std::vector<size_t> tOffsets, tBytes; 0262 tile_stripe_data_t() : tiled(false), striped(false),tileCnt(0), 0263 tileWidth(0),tileHeight(0),tilesH(0),tilesV(0), 0264 maxBytesInTile(0){} 0265 void init(tiff_ifd_t *ifd, const libraw_image_sizes_t&, const unpacker_data_t&, 0266 short _order, 0267 LibRaw_abstract_datastream *stream); 0268 }; 0269 0270 static unsigned static_get4(LibRaw_abstract_datastream *stream, short _order) 0271 { 0272 uchar str[4] = { 0xff, 0xff, 0xff, 0xff }; 0273 stream->read(str, 1, 4); 0274 return libraw_sget4_static(_order, str); 0275 } 0276 0277 0278 void tile_stripe_data_t::init(tiff_ifd_t *ifd, const libraw_image_sizes_t& sizes, 0279 const unpacker_data_t& unpacker_data, short _order, LibRaw_abstract_datastream *stream) 0280 { 0281 tiled = (unpacker_data.tile_width <= sizes.raw_width) && (unpacker_data.tile_length <= sizes.raw_height); 0282 striped = (ifd->rows_per_strip > 0 && ifd->rows_per_strip < sizes.raw_height) && ifd->strip_byte_counts_count > 0; 0283 0284 tileWidth = tiled ? unpacker_data.tile_width : sizes.raw_width; 0285 tileHeight = tiled ? unpacker_data.tile_length :(striped ? ifd->rows_per_strip : sizes.raw_height); 0286 tilesH = tiled ? (sizes.raw_width + tileWidth - 1) / tileWidth : 1; 0287 tilesV = tiled ? (sizes.raw_height + tileHeight - 1) / tileHeight : 0288 (striped ? ((sizes.raw_height + ifd->rows_per_strip - 1) / ifd->rows_per_strip) : 1); 0289 tileCnt = tilesH * tilesV; 0290 0291 if (tileCnt < 1 || tileCnt > 1000000) 0292 throw LIBRAW_EXCEPTION_DECODE_RAW; 0293 0294 tOffsets = std::vector<size_t>(tileCnt); 0295 tBytes = std::vector <size_t>(tileCnt); 0296 0297 if (tiled) 0298 for (int t = 0; t < tileCnt; ++t) 0299 tOffsets[t] = static_get4(stream, _order); 0300 else if (striped) 0301 for (int t = 0; t < tileCnt && t < ifd->strip_offsets_count; ++t) 0302 tOffsets[t] = ifd->strip_offsets[t]; 0303 else 0304 tOffsets[0] = ifd->offset; 0305 0306 maxBytesInTile = 0; 0307 0308 if (tileCnt == 1 || (!tiled && !striped)) 0309 tBytes[0] = maxBytesInTile = ifd->bytes; 0310 else if (tiled) 0311 { 0312 // ifd->bytes points to tile size table if more than 1 tile exists 0313 stream->seek(ifd->bytes, SEEK_SET); 0314 for (int t = 0; t < tileCnt; ++t) 0315 { 0316 tBytes[t] = static_get4(stream, _order); ; 0317 maxBytesInTile = MAX(maxBytesInTile, tBytes[t]); 0318 } 0319 } 0320 else if (striped) 0321 for (int t = 0; t < tileCnt && t < ifd->strip_byte_counts_count; ++t) 0322 { 0323 tBytes[t] = ifd->strip_byte_counts[t]; 0324 maxBytesInTile = MAX(maxBytesInTile, tBytes[t]); 0325 } 0326 } 0327 0328 #ifdef USE_ZLIB 0329 void LibRaw::deflate_dng_load_raw() 0330 { 0331 int iifd = find_ifd_by_offset(libraw_internal_data.unpacker_data.data_offset); 0332 if(iifd < 0 || iifd > (int)libraw_internal_data.identify_data.tiff_nifds) 0333 throw LIBRAW_EXCEPTION_DECODE_RAW; 0334 struct tiff_ifd_t *ifd = &tiff_ifd[iifd]; 0335 0336 float *float_raw_image = 0; 0337 float max = 0.f; 0338 0339 if (ifd->samples != 1 && ifd->samples != 3 && ifd->samples != 4) 0340 throw LIBRAW_EXCEPTION_DECODE_RAW; 0341 0342 if (libraw_internal_data.unpacker_data.tiff_samples != (unsigned)ifd->samples) 0343 throw LIBRAW_EXCEPTION_DECODE_RAW; // Wrong IFD 0344 0345 if (imgdata.idata.filters && ifd->samples > 1) 0346 throw LIBRAW_EXCEPTION_DECODE_RAW; 0347 0348 tile_stripe_data_t tiles; 0349 tiles.init(ifd, imgdata.sizes, libraw_internal_data.unpacker_data, libraw_internal_data.unpacker_data.order, 0350 libraw_internal_data.internal_data.input); 0351 0352 if (ifd->sample_format == 3) 0353 float_raw_image = (float *)calloc(tiles.tileCnt * tiles.tileWidth * tiles.tileHeight *ifd->samples, sizeof(float)); 0354 else 0355 throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float deflated supported 0356 0357 int xFactor; 0358 switch (ifd->predictor) 0359 { 0360 case 3: 0361 default: 0362 xFactor = 1; 0363 break; 0364 case 34894: 0365 xFactor = 2; 0366 break; 0367 case 34895: 0368 xFactor = 4; 0369 break; 0370 } 0371 0372 unsigned tilePixels = tiles.tileWidth * tiles.tileHeight; 0373 unsigned pixelSize = sizeof(float) * ifd->samples; 0374 unsigned tileBytes = tilePixels * pixelSize; 0375 unsigned tileRowBytes = tiles.tileWidth * pixelSize; 0376 0377 if(INT64(tiles.maxBytesInTile) > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024) ) 0378 throw LIBRAW_EXCEPTION_TOOBIG; 0379 0380 std::vector<uchar> cBuffer(tiles.maxBytesInTile); 0381 std::vector<uchar> uBuffer(tileBytes + tileRowBytes); // extra row for decoding 0382 0383 for (size_t y = 0, t = 0; y < imgdata.sizes.raw_height; y += tiles.tileHeight) 0384 { 0385 for (size_t x = 0; x < imgdata.sizes.raw_width; x += tiles.tileWidth, ++t) 0386 { 0387 libraw_internal_data.internal_data.input->seek(tiles.tOffsets[t], SEEK_SET); 0388 libraw_internal_data.internal_data.input->read(cBuffer.data(), 1, tiles.tBytes[t]); 0389 unsigned long dstLen = tileBytes; 0390 int err = 0391 uncompress(uBuffer.data() + tileRowBytes, &dstLen, cBuffer.data(), (unsigned long)tiles.tBytes[t]); 0392 if (err != Z_OK) 0393 { 0394 throw LIBRAW_EXCEPTION_DECODE_RAW; 0395 return; 0396 } 0397 else 0398 { 0399 int bytesps = ifd->bps >> 3; 0400 size_t rowsInTile = y + tiles.tileHeight > imgdata.sizes.raw_height ? imgdata.sizes.raw_height - y : tiles.tileHeight; 0401 size_t colsInTile = x + tiles.tileWidth > imgdata.sizes.raw_width ? imgdata.sizes.raw_width - x : tiles.tileWidth; 0402 0403 for (size_t row = 0; row < rowsInTile; ++row) // do not process full tile if not needed 0404 { 0405 unsigned char *dst = uBuffer.data() + row * tiles.tileWidth * bytesps * ifd->samples; 0406 unsigned char *src = dst + tileRowBytes; 0407 DecodeFPDelta(src, dst, tiles.tileWidth / xFactor, ifd->samples * xFactor, bytesps); 0408 float lmax = expandFloats(dst, tiles.tileWidth * ifd->samples, bytesps); 0409 max = MAX(max, lmax); 0410 unsigned char *dst2 = (unsigned char *)&float_raw_image 0411 [((y + row) * imgdata.sizes.raw_width + x) * ifd->samples]; 0412 memmove(dst2, dst, colsInTile * ifd->samples * sizeof(float)); 0413 } 0414 } 0415 } 0416 } 0417 0418 imgdata.color.fmaximum = max; 0419 0420 // Set fields according to data format 0421 0422 imgdata.rawdata.raw_alloc = float_raw_image; 0423 if (ifd->samples == 1) 0424 { 0425 imgdata.rawdata.float_image = float_raw_image; 0426 imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = 0427 imgdata.sizes.raw_width * 4; 0428 } 0429 else if (ifd->samples == 3) 0430 { 0431 imgdata.rawdata.float3_image = (float(*)[3])float_raw_image; 0432 imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = 0433 imgdata.sizes.raw_width * 12; 0434 } 0435 else if (ifd->samples == 4) 0436 { 0437 imgdata.rawdata.float4_image = (float(*)[4])float_raw_image; 0438 imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = 0439 imgdata.sizes.raw_width * 16; 0440 } 0441 0442 if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT) 0443 convertFloatToInt(); // with default settings 0444 } 0445 #else 0446 void LibRaw::deflate_dng_load_raw() { throw LIBRAW_EXCEPTION_DECODE_RAW; } 0447 #endif 0448 0449 int LibRaw::is_floating_point() 0450 { 0451 struct tiff_ifd_t *ifd = &tiff_ifd[0]; 0452 while (ifd < &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds] && 0453 ifd->offset != libraw_internal_data.unpacker_data.data_offset) 0454 ++ifd; 0455 if (ifd == &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds]) 0456 return 0; 0457 0458 return ifd->sample_format == 3; 0459 } 0460 0461 int LibRaw::have_fpdata() 0462 { 0463 return imgdata.rawdata.float_image || imgdata.rawdata.float3_image || 0464 imgdata.rawdata.float4_image; 0465 } 0466 0467 void LibRaw::convertFloatToInt(float dmin /* =4096.f */, 0468 float dmax /* =32767.f */, 0469 float dtarget /*= 16383.f */) 0470 { 0471 int samples = 0; 0472 float *data = 0; 0473 void *orawalloc = imgdata.rawdata.raw_alloc; 0474 if (imgdata.rawdata.float_image) 0475 { 0476 samples = 1; 0477 data = imgdata.rawdata.float_image; 0478 } 0479 else if (imgdata.rawdata.float3_image) 0480 { 0481 samples = 3; 0482 data = (float *)imgdata.rawdata.float3_image; 0483 } 0484 else if (imgdata.rawdata.float4_image) 0485 { 0486 samples = 4; 0487 data = (float *)imgdata.rawdata.float4_image; 0488 } 0489 else 0490 return; 0491 0492 ushort *raw_alloc = (ushort *)malloc( 0493 imgdata.sizes.raw_height * imgdata.sizes.raw_width * 0494 libraw_internal_data.unpacker_data.tiff_samples * sizeof(ushort)); 0495 float tmax = MAX(imgdata.color.maximum, 1); 0496 float datamax = imgdata.color.fmaximum; 0497 0498 tmax = MAX(tmax, datamax); 0499 tmax = MAX(tmax, 1.f); 0500 0501 float multip = 1.f; 0502 if (tmax < dmin || tmax > dmax) 0503 { 0504 imgdata.rawdata.color.fnorm = imgdata.color.fnorm = multip = dtarget / tmax; 0505 imgdata.rawdata.color.maximum = imgdata.color.maximum = dtarget; 0506 imgdata.rawdata.color.black = imgdata.color.black = 0507 (float)imgdata.color.black * multip; 0508 for (int i = 0; 0509 i < int(sizeof(imgdata.color.cblack)/sizeof(imgdata.color.cblack[0])); 0510 i++) 0511 if (i != 4 && i != 5) 0512 imgdata.rawdata.color.cblack[i] = imgdata.color.cblack[i] = 0513 (float)imgdata.color.cblack[i] * multip; 0514 } 0515 else 0516 imgdata.rawdata.color.fnorm = imgdata.color.fnorm = 0.f; 0517 0518 for (size_t i = 0; i < imgdata.sizes.raw_height * imgdata.sizes.raw_width * 0519 libraw_internal_data.unpacker_data.tiff_samples; 0520 ++i) 0521 { 0522 float val = MAX(data[i], 0.f); 0523 raw_alloc[i] = (ushort)(val * multip); 0524 } 0525 0526 if (samples == 1) 0527 { 0528 imgdata.rawdata.raw_alloc = imgdata.rawdata.raw_image = raw_alloc; 0529 imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = 0530 imgdata.sizes.raw_width * 2; 0531 } 0532 else if (samples == 3) 0533 { 0534 imgdata.rawdata.raw_alloc = imgdata.rawdata.color3_image = 0535 (ushort(*)[3])raw_alloc; 0536 imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = 0537 imgdata.sizes.raw_width * 6; 0538 } 0539 else if (samples == 4) 0540 { 0541 imgdata.rawdata.raw_alloc = imgdata.rawdata.color4_image = 0542 (ushort(*)[4])raw_alloc; 0543 imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = 0544 imgdata.sizes.raw_width * 8; 0545 } 0546 if(orawalloc) 0547 free(orawalloc); // remove old allocation 0548 imgdata.rawdata.float_image = 0; 0549 imgdata.rawdata.float3_image = 0; 0550 imgdata.rawdata.float4_image = 0; 0551 } 0552 0553 static 0554 #if (defined(_MSC_VER) && !defined(__clang__)) 0555 _forceinline 0556 #else 0557 inline 0558 #endif 0559 void libraw_swap24(uchar *data, int len) 0560 { 0561 for (int i = 0; i < len - 2; i += 3) 0562 { 0563 uchar t = data[i]; 0564 data[i] = data[i + 2]; 0565 data[i + 2] = t; 0566 } 0567 } 0568 0569 static 0570 #if (defined(_MSC_VER) && !defined(__clang__)) 0571 _forceinline 0572 #else 0573 inline 0574 #endif 0575 void libraw_swap32(uchar *data, int len) 0576 { 0577 unsigned *d = (unsigned*)data; 0578 for (int i = 0; i < len / 4; i++) 0579 { 0580 unsigned x = d[i]; 0581 d[i] = (x << 24) + ((x << 8) & 0x00FF0000) + 0582 ((x >> 8) & 0x0000FF00) + (x >> 24); 0583 } 0584 } 0585 0586 0587 void LibRaw::uncompressed_fp_dng_load_raw() 0588 { 0589 int iifd = find_ifd_by_offset(libraw_internal_data.unpacker_data.data_offset); 0590 if (iifd < 0 || iifd > (int)libraw_internal_data.identify_data.tiff_nifds) 0591 throw LIBRAW_EXCEPTION_DECODE_RAW; 0592 struct tiff_ifd_t *ifd = &tiff_ifd[iifd]; 0593 0594 float *float_raw_image = 0; 0595 0596 if (ifd->samples != 1 && ifd->samples != 3 && ifd->samples != 4) 0597 throw LIBRAW_EXCEPTION_DECODE_RAW; 0598 0599 if(imgdata.idata.filters && ifd->samples > 1) 0600 throw LIBRAW_EXCEPTION_DECODE_RAW; 0601 0602 if ((int)libraw_internal_data.unpacker_data.tiff_samples != ifd->samples) 0603 throw LIBRAW_EXCEPTION_DECODE_RAW; // Wrong IFD 0604 0605 int bytesps = (ifd->bps + 7) >> 3; // round to upper value 0606 0607 if(bytesps < 1 || bytesps > 4) 0608 throw LIBRAW_EXCEPTION_DECODE_RAW; 0609 0610 tile_stripe_data_t tiles; 0611 tiles.init(ifd, imgdata.sizes, libraw_internal_data.unpacker_data, libraw_internal_data.unpacker_data.order, 0612 libraw_internal_data.internal_data.input); 0613 0614 INT64 allocsz = INT64(tiles.tileCnt) * INT64(tiles.tileWidth) * INT64(tiles.tileHeight) * INT64(ifd->samples) * INT64(sizeof(float)); 0615 if (allocsz > INT64(imgdata.rawparams.max_raw_memory_mb) * INT64(1024 * 1024)) 0616 throw LIBRAW_EXCEPTION_TOOBIG; 0617 0618 if (ifd->sample_format == 3) 0619 float_raw_image = (float *)calloc(tiles.tileCnt * tiles.tileWidth * tiles.tileHeight *ifd->samples, sizeof(float)); 0620 else 0621 throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float supported 0622 0623 bool difford = (libraw_internal_data.unpacker_data.order == 0x4949) == (ntohs(0x1234) == 0x1234); 0624 float max = 0.f; 0625 0626 std::vector<uchar> rowbuf(tiles.tileWidth *sizeof(float) * ifd->samples); // line buffer for last tile in tile row 0627 0628 for (size_t y = 0, t = 0; y < imgdata.sizes.raw_height; y += tiles.tileHeight) 0629 { 0630 for (unsigned x = 0; x < imgdata.sizes.raw_width && t < (unsigned)tiles.tileCnt; x += tiles.tileWidth, ++t) 0631 { 0632 libraw_internal_data.internal_data.input->seek(tiles.tOffsets[t], SEEK_SET); 0633 size_t rowsInTile = y + tiles.tileHeight > imgdata.sizes.raw_height ? imgdata.sizes.raw_height - y : tiles.tileHeight; 0634 size_t colsInTile = x + tiles.tileWidth > imgdata.sizes.raw_width ? imgdata.sizes.raw_width - x : tiles.tileWidth; 0635 0636 size_t inrowbytes = colsInTile * bytesps * ifd->samples; 0637 int fullrowbytes = tiles.tileWidth *bytesps * ifd->samples; 0638 size_t outrowbytes = colsInTile * sizeof(float) * ifd->samples; 0639 0640 for (size_t row = 0; row < rowsInTile; ++row) // do not process full tile if not needed 0641 { 0642 unsigned char *dst = fullrowbytes > inrowbytes ? rowbuf.data(): // last tile in row, use buffer 0643 (unsigned char *)&float_raw_image 0644 [((y + row) * imgdata.sizes.raw_width + x) * ifd->samples]; 0645 libraw_internal_data.internal_data.input->read(dst, 1, fullrowbytes); 0646 if (bytesps == 2 && difford) 0647 libraw_swab(dst, fullrowbytes); 0648 else if (bytesps == 3 && (libraw_internal_data.unpacker_data.order == 0x4949)) // II-16bit 0649 libraw_swap24(dst, fullrowbytes); 0650 if (bytesps == 4 && difford) 0651 libraw_swap32(dst, fullrowbytes); 0652 0653 float lmax = expandFloats( 0654 dst, 0655 tiles.tileWidth * ifd->samples, 0656 bytesps); 0657 if (fullrowbytes > inrowbytes) // last tile in row: copy buffer to destination 0658 memmove(&float_raw_image[((y + row) * imgdata.sizes.raw_width + x) * ifd->samples], dst, outrowbytes); 0659 max = MAX(max, lmax); 0660 } 0661 } 0662 } 0663 0664 imgdata.color.fmaximum = max; 0665 0666 // setup outpuf fields 0667 imgdata.rawdata.raw_alloc = float_raw_image; 0668 if (ifd->samples == 1) 0669 { 0670 imgdata.rawdata.float_image = float_raw_image; 0671 imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = 0672 imgdata.sizes.raw_width * 4; 0673 } 0674 else if (ifd->samples == 3) 0675 { 0676 imgdata.rawdata.float3_image = (float(*)[3])float_raw_image; 0677 imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = 0678 imgdata.sizes.raw_width * 12; 0679 } 0680 else if (ifd->samples == 4) 0681 { 0682 imgdata.rawdata.float4_image = (float(*)[4])float_raw_image; 0683 imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = 0684 imgdata.sizes.raw_width * 16; 0685 } 0686 0687 if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT) 0688 convertFloatToInt(); 0689 }