Mercurial > octave-libtiff
comparison libinterp/corefcn/__tiff__.cc @ 31168:27ed758c1688
Tiff setTag: fixed bug for rational tags and special-case tags.
author | magedrifaat <magedrifaat@gmail.com> |
---|---|
date | Fri, 12 Aug 2022 21:50:43 +0200 |
parents | f91cd5ceaae6 |
children | 72a159bc5a4c |
comparison
equal
deleted
inserted
replaced
31167:f91cd5ceaae6 | 31168:27ed758c1688 |
---|---|
737 retval = static_cast<double> (*(reinterpret_cast<uint64_t *> (data))); | 737 retval = static_cast<double> (*(reinterpret_cast<uint64_t *> (data))); |
738 break; | 738 break; |
739 } | 739 } |
740 case TIFF_RATIONAL: | 740 case TIFF_RATIONAL: |
741 { | 741 { |
742 error ("TIFF_RATIONAL should have at least 2 elements but got only 1"); | 742 retval = *(reinterpret_cast<float *> (data)); |
743 break; | 743 break; |
744 } | 744 } |
745 case TIFF_SBYTE: | 745 case TIFF_SBYTE: |
746 { | 746 { |
747 retval = static_cast<double> (*(reinterpret_cast<int8_t *> (data))); | 747 retval = static_cast<double> (*(reinterpret_cast<int8_t *> (data))); |
772 retval = *(reinterpret_cast<double *> (data)); | 772 retval = *(reinterpret_cast<double *> (data)); |
773 break; | 773 break; |
774 } | 774 } |
775 case TIFF_SRATIONAL: | 775 case TIFF_SRATIONAL: |
776 { | 776 { |
777 error ("TIFF_SRATIONAL should have at least 2 elements but got only 1"); | 777 retval = *(reinterpret_cast<float *> (data)); |
778 break; | 778 break; |
779 } | 779 } |
780 case TIFF_IFD: | 780 case TIFF_IFD: |
781 case TIFF_IFD8: | 781 case TIFF_IFD8: |
782 error ("Unimplemented IFFD data type"); | 782 error ("Unimplemented IFFD data type"); |
852 retval = octave_value (arr); | 852 retval = octave_value (arr); |
853 break; | 853 break; |
854 } | 854 } |
855 case TIFF_RATIONAL: | 855 case TIFF_RATIONAL: |
856 { | 856 { |
857 // TODO(maged): This is incorrect, LibTIFF already handles | |
858 // rationals and converts them to floats | |
859 NDArray arr (arr_dims); | 857 NDArray arr (arr_dims); |
860 for (uint32_t i = 0; i < count; i+=2) | 858 for (uint32_t i = 0; i < count; i++) |
861 { | 859 { |
862 arr(i / 2) = static_cast<float> ((reinterpret_cast<uint32_t *> (data))[i]) | 860 arr(i) = (reinterpret_cast<float *> (data))[i]; |
863 / static_cast<float> ((reinterpret_cast<uint32_t *> (data))[i+1]); | |
864 } | 861 } |
865 retval = octave_value (arr); | 862 retval = octave_value (arr); |
866 break; | 863 break; |
867 } | 864 } |
868 case TIFF_SBYTE: | 865 case TIFF_SBYTE: |
926 break; | 923 break; |
927 } | 924 } |
928 case TIFF_SRATIONAL: | 925 case TIFF_SRATIONAL: |
929 { | 926 { |
930 NDArray arr (arr_dims); | 927 NDArray arr (arr_dims); |
931 for (uint32_t i = 0; i < count; i+=2) | 928 for (uint32_t i = 0; i < count; i++) |
932 { | 929 { |
933 arr(i / 2) = static_cast<float> ((reinterpret_cast<int32_t *> (data))[i]) | 930 arr(i) = (reinterpret_cast<float *> (data))[i]; |
934 / static_cast<float> ((reinterpret_cast<int32_t *> (data))[i+1]); | |
935 } | 931 } |
936 retval = octave_value (arr); | 932 retval = octave_value (arr); |
937 break; | 933 break; |
938 } | 934 } |
939 case TIFF_IFD: | 935 case TIFF_IFD: |
1080 &bits_per_sample)) | 1076 &bits_per_sample)) |
1081 error ("Failed to obtain the bit depth"); | 1077 error ("Failed to obtain the bit depth"); |
1082 | 1078 |
1083 uint32_t count = 1 << bits_per_sample; | 1079 uint32_t count = 1 << bits_per_sample; |
1084 uint16_t *ch1, *ch2, *ch3; | 1080 uint16_t *ch1, *ch2, *ch3; |
1085 if (samples_per_pixel == 1) | 1081 validate_tiff_get_field (TIFFGetField (tif, tag_id, |
1086 { | 1082 &ch1, &ch2, &ch3)); |
1087 validate_tiff_get_field (TIFFGetField (tif, TIFFTAG_COLORMAP, &ch1)); | 1083 if (ch2 == NULL) |
1088 tag_data_ov = interpret_tag_data (ch1, count, | 1084 tag_data_ov = interpret_tag_data (ch1, count, |
1089 TIFFFieldDataType (fip)); | 1085 TIFFFieldDataType (fip)); |
1090 } | |
1091 else | 1086 else |
1092 { | 1087 { |
1093 validate_tiff_get_field (TIFFGetField (tif, TIFFTAG_COLORMAP, | |
1094 &ch1, &ch2, &ch3)); | |
1095 | |
1096 OCTAVE_LOCAL_BUFFER (uint16NDArray, array_list, 3); | 1088 OCTAVE_LOCAL_BUFFER (uint16NDArray, array_list, 3); |
1097 dim_vector col_dims(count, 1); | 1089 dim_vector col_dims(count, 1); |
1098 array_list[0] = interpret_tag_data (ch1, | 1090 array_list[0] = interpret_tag_data (ch1, |
1099 count, | 1091 count, |
1100 TIFFFieldDataType (fip)) | 1092 TIFFFieldDataType (fip)) |
1187 // Since scalar tags are the last to be handled, any tag that | 1179 // Since scalar tags are the last to be handled, any tag that |
1188 // require a count to be passed is an unsupported tag. | 1180 // require a count to be passed is an unsupported tag. |
1189 if (TIFFFieldPassCount (fip)) | 1181 if (TIFFFieldPassCount (fip)) |
1190 error ("Unsupported tag"); | 1182 error ("Unsupported tag"); |
1191 | 1183 |
1184 // According to matlab, the value must be a scalar double | |
1185 if (! tag_ov.is_scalar_type () || ! tag_ov.is_double_type ()) | |
1186 error ("Tag value must be a scalar double"); | |
1187 | |
1192 TIFFDataType tag_datatype = TIFFFieldDataType (fip); | 1188 TIFFDataType tag_datatype = TIFFFieldDataType (fip); |
1193 switch (tag_datatype) | 1189 switch (tag_datatype) |
1194 { | 1190 { |
1195 case TIFF_BYTE: | 1191 case TIFF_BYTE: |
1196 case TIFF_UNDEFINED: | 1192 case TIFF_UNDEFINED: |
1197 // TODO(maged): check if matlab errors for long data type/range | |
1198 TIFFSetField (tif, tag_id, tag_ov.uint8_scalar_value ()); | 1193 TIFFSetField (tif, tag_id, tag_ov.uint8_scalar_value ()); |
1199 break; | 1194 break; |
1200 case TIFF_ASCII: | 1195 case TIFF_ASCII: |
1201 TIFFSetField (tif, tag_id, tag_ov.string_value ().c_str ()); | 1196 TIFFSetField (tif, tag_id, tag_ov.string_value ().c_str ()); |
1202 break; | 1197 break; |
1240 default: | 1235 default: |
1241 error ("Unsupported tag data type"); | 1236 error ("Unsupported tag data type"); |
1242 } | 1237 } |
1243 } | 1238 } |
1244 | 1239 |
1240 template <typename T> | |
1241 void | |
1242 set_array_field_helper (TIFF *tif, uint32_t tag_id, T data_arr) | |
1243 { | |
1244 const void *data_ptr = data_arr.data (); | |
1245 | |
1246 if (! TIFFSetField (tif, tag_id, data_ptr)) | |
1247 error ("Failed to set tag"); | |
1248 } | |
1249 | |
1245 void | 1250 void |
1246 set_array_field_data (TIFF *tif, const TIFFField *fip, | 1251 set_array_field_data (TIFF *tif, const TIFFField *fip, |
1247 octave_value tag_ov, uint32_t count) | 1252 octave_value tag_ov, uint32_t count) |
1248 { | 1253 { |
1249 uint32_t tag_id = TIFFFieldTag (fip); | 1254 uint32_t tag_id = TIFFFieldTag (fip); |
1250 TIFFDataType tag_datatype = TIFFFieldDataType (fip); | 1255 TIFFDataType tag_datatype = TIFFFieldDataType (fip); |
1251 | 1256 |
1252 // TODO(maged): validate count? | 1257 // Array type must be double in matlab |
1253 octave_unused_parameter (count); | 1258 if (! tag_ov.is_double_type ()) |
1254 | 1259 error ("Tag data must be double"); |
1255 void *data_ptr; | 1260 |
1261 // Matlab checks number of elements not dimensions | |
1262 if (tag_ov.array_value ().numel () != count) | |
1263 error ("Expected an array with %u elements", count); | |
1256 | 1264 |
1257 switch (tag_datatype) | 1265 switch (tag_datatype) |
1258 { | 1266 { |
1259 case TIFF_BYTE: | 1267 case TIFF_BYTE: |
1260 case TIFF_UNDEFINED: | 1268 case TIFF_UNDEFINED: |
1261 // TODO(maged): check if matlab errors for long data type/dimensions | 1269 set_array_field_helper<uint8NDArray> (tif, tag_id, |
1262 // TODO(maged): should we resize/reshape? | 1270 tag_ov.uint8_array_value ()); |
1263 data_ptr = tag_ov.uint8_array_value ().fortran_vec (); | |
1264 break; | 1271 break; |
1265 case TIFF_SHORT: | 1272 case TIFF_SHORT: |
1266 data_ptr = tag_ov.uint16_array_value ().fortran_vec (); | 1273 set_array_field_helper<uint16NDArray> (tif, tag_id, |
1274 tag_ov.uint16_array_value ()); | |
1267 break; | 1275 break; |
1268 case TIFF_LONG: | 1276 case TIFF_LONG: |
1269 data_ptr = tag_ov.uint32_array_value ().fortran_vec (); | 1277 set_array_field_helper<uint32NDArray> (tif, tag_id, |
1278 tag_ov.uint32_array_value ()); | |
1270 break; | 1279 break; |
1271 case TIFF_LONG8: | 1280 case TIFF_LONG8: |
1272 data_ptr = tag_ov.uint64_array_value ().fortran_vec (); | 1281 set_array_field_helper<uint64NDArray> (tif, tag_id, |
1282 tag_ov.uint64_array_value ()); | |
1273 break; | 1283 break; |
1274 case TIFF_RATIONAL: | 1284 case TIFF_RATIONAL: |
1275 data_ptr = tag_ov.float_array_value ().fortran_vec (); | 1285 set_array_field_helper<FloatNDArray> (tif, tag_id, |
1286 tag_ov.float_array_value ()); | |
1276 break; | 1287 break; |
1277 case TIFF_SBYTE: | 1288 case TIFF_SBYTE: |
1278 data_ptr = tag_ov.int8_array_value ().fortran_vec (); | 1289 set_array_field_helper<int8NDArray> (tif, tag_id, |
1290 tag_ov.int8_array_value ()); | |
1279 break; | 1291 break; |
1280 case TIFF_SSHORT: | 1292 case TIFF_SSHORT: |
1281 data_ptr = tag_ov.int16_array_value ().fortran_vec (); | 1293 set_array_field_helper<int16NDArray> (tif, tag_id, |
1294 tag_ov.int16_array_value ()); | |
1282 break; | 1295 break; |
1283 case TIFF_SLONG: | 1296 case TIFF_SLONG: |
1284 data_ptr = tag_ov.int32_array_value ().fortran_vec (); | 1297 set_array_field_helper<int32NDArray> (tif, tag_id, |
1298 tag_ov.int32_array_value ()); | |
1285 break; | 1299 break; |
1286 case TIFF_SLONG8: | 1300 case TIFF_SLONG8: |
1287 data_ptr = tag_ov.int64_array_value ().fortran_vec (); | 1301 set_array_field_helper<int64NDArray> (tif, tag_id, |
1302 tag_ov.int64_array_value ()); | |
1288 break; | 1303 break; |
1289 case TIFF_FLOAT: | 1304 case TIFF_FLOAT: |
1290 data_ptr = tag_ov.float_array_value ().fortran_vec (); | 1305 set_array_field_helper<FloatNDArray> (tif, tag_id, |
1306 tag_ov.float_array_value ()); | |
1291 break; | 1307 break; |
1292 case TIFF_DOUBLE: | 1308 case TIFF_DOUBLE: |
1293 data_ptr = tag_ov.array_value ().fortran_vec (); | 1309 set_array_field_helper<NDArray> (tif, tag_id, |
1310 tag_ov.array_value ()); | |
1294 break; | 1311 break; |
1295 case TIFF_SRATIONAL: | 1312 case TIFF_SRATIONAL: |
1296 data_ptr = tag_ov.float_array_value ().fortran_vec (); | 1313 set_array_field_helper<FloatNDArray> (tif, tag_id, |
1314 tag_ov.float_array_value ()); | |
1297 break; | 1315 break; |
1298 case TIFF_IFD: | 1316 case TIFF_IFD: |
1299 case TIFF_IFD8: | 1317 case TIFF_IFD8: |
1300 error ("Unimplemented IFFD data type"); | 1318 error ("Unimplemented IFFD data type"); |
1301 break; | 1319 break; |
1302 default: | 1320 default: |
1303 error ("Unsupported tag data type"); | 1321 error ("Unsupported tag data type"); |
1304 } | 1322 } |
1305 | |
1306 if (! TIFFSetField (tif, tag_id, data_ptr)) | |
1307 error ("Failed to set tag"); | |
1308 } | 1323 } |
1309 | 1324 |
1310 void | 1325 void |
1311 set_field_data (TIFF *tif, const TIFFField *fip, octave_value tag_ov) | 1326 set_field_data (TIFF *tif, const TIFFField *fip, octave_value tag_ov) |
1312 { | 1327 { |
1313 uint32_t tag_id = TIFFFieldTag (fip); | 1328 uint32_t tag_id = TIFFFieldTag (fip); |
1314 | 1329 |
1315 // TODO(maged): find/create images to test the special tags | 1330 // TODO(maged): find/create images to test the special tags |
1316 switch (tag_id) | 1331 switch (tag_id) |
1317 { | 1332 { |
1318 case TIFFTAG_YCBCRCOEFFICIENTS: | 1333 case TIFFTAG_YCBCRCOEFFICIENTS: |
1319 set_array_field_data (tif, fip, tag_ov, 3); | 1334 set_array_field_data (tif, fip, tag_ov, 3); |
1336 uint16_t bits_per_sample; | 1351 uint16_t bits_per_sample; |
1337 if (! TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE, | 1352 if (! TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE, |
1338 &bits_per_sample)) | 1353 &bits_per_sample)) |
1339 error ("Failed to obtain the bit depth"); | 1354 error ("Failed to obtain the bit depth"); |
1340 | 1355 |
1356 if (! tag_ov.is_double_type ()) | |
1357 error ("Tag data must be double"); | |
1358 | |
1341 // According to the format specification, this field should | 1359 // According to the format specification, this field should |
1342 // be 8 or 16 only. | 1360 // be 8 or 16 only. |
1343 if (bits_per_sample > 16) | 1361 if (bits_per_sample > 16) |
1344 error ("Too high bit depth for a palette image"); | 1362 error ("Too high bit depth for a palette image"); |
1345 | 1363 |
1346 // TODO(maged): what is matlab behavior for wrong input dimensions | |
1347 uint32_t count = 1 << bits_per_sample; | 1364 uint32_t count = 1 << bits_per_sample; |
1365 | |
1366 if (tag_ov.is_scalar_type () | |
1367 || tag_ov.array_value ().dim1 () != count | |
1368 || tag_ov.array_value ().dim2 () != 3) | |
1369 error ("Expected matrix with %u rows and 3 columns", count); | |
1370 | |
1348 NDArray array_data = tag_ov.array_value (); | 1371 NDArray array_data = tag_ov.array_value (); |
1349 array_data *= UINT16_MAX; | 1372 array_data *= UINT16_MAX; |
1350 uint16NDArray u16_array = uint16NDArray (array_data); | 1373 uint16NDArray u16_array = uint16NDArray (array_data); |
1351 uint16_t *data_ptr | 1374 const uint16_t *data_ptr |
1352 = reinterpret_cast<uint16_t *> (u16_array.fortran_vec ()); | 1375 = reinterpret_cast<const uint16_t *> (u16_array.data ()); |
1353 uint16_t *red = data_ptr; | 1376 if (! TIFFSetField (tif, tag_id, data_ptr, data_ptr + count, |
1354 uint16_t *green = red + count; | 1377 data_ptr + 2 * count)) |
1355 uint16_t *blue = green + count; | |
1356 if (! TIFFSetField (tif, tag_id, red, green, blue)) | |
1357 error ("Failed to set tag"); | 1378 error ("Failed to set tag"); |
1358 break; | 1379 break; |
1359 } | 1380 } |
1360 case TIFFTAG_TRANSFERFUNCTION: | 1381 case TIFFTAG_TRANSFERFUNCTION: |
1361 { | 1382 { |
1369 &bits_per_sample)) | 1390 &bits_per_sample)) |
1370 error ("Failed to obtain the bit depth"); | 1391 error ("Failed to obtain the bit depth"); |
1371 | 1392 |
1372 uint32_t count = 1 << bits_per_sample; | 1393 uint32_t count = 1 << bits_per_sample; |
1373 | 1394 |
1374 uint16_t *data_ptr | 1395 // An intermediate variable is required for storing the return of |
1375 = reinterpret_cast<uint16_t *> (tag_ov.uint16_array_value () | 1396 // uint16_array_value so that the object remains in scope and the |
1376 .fortran_vec ()); | 1397 // pointer returned from data () is not a dangling pointer |
1398 uint16NDArray data_arr = tag_ov.uint16_array_value (); | |
1399 | |
1400 if (data_arr.numel () != count) | |
1401 error ("Tag data should be and array of %u elements", count); | |
1402 | |
1403 const uint16_t *data_ptr | |
1404 = reinterpret_cast<const uint16_t *> (data_arr.data ()); | |
1377 if (samples_per_pixel == 1) | 1405 if (samples_per_pixel == 1) |
1378 { | 1406 { |
1379 if (! TIFFSetField (tif, tag_id, data_ptr)) | 1407 if (! TIFFSetField (tif, tag_id, data_ptr)) |
1380 error ("Failed to set field"); | 1408 error ("Failed to set field"); |
1381 } | 1409 } |
1390 case TIFFTAG_PAGENUMBER: | 1418 case TIFFTAG_PAGENUMBER: |
1391 case TIFFTAG_HALFTONEHINTS: | 1419 case TIFFTAG_HALFTONEHINTS: |
1392 case TIFFTAG_DOTRANGE: | 1420 case TIFFTAG_DOTRANGE: |
1393 case TIFFTAG_YCBCRSUBSAMPLING: | 1421 case TIFFTAG_YCBCRSUBSAMPLING: |
1394 { | 1422 { |
1395 // TODO(maged): what is matlab behavior for wrong dimensions | |
1396 uint16NDArray array_data = tag_ov.uint16_array_value (); | 1423 uint16NDArray array_data = tag_ov.uint16_array_value (); |
1424 if (array_data.numel () != 2) | |
1425 error ("Tag data should be an array with 2 elements"); | |
1426 | |
1397 if (! TIFFSetField (tif, tag_id, array_data (0), array_data (1))) | 1427 if (! TIFFSetField (tif, tag_id, array_data (0), array_data (1))) |
1398 error ("Failed to set field"); | 1428 error ("Failed to set field"); |
1399 break; | 1429 break; |
1400 } | 1430 } |
1401 case TIFFTAG_SUBIFD: | 1431 case TIFFTAG_SUBIFD: |
1402 { | 1432 { |
1403 // TODO(maged): check if matlab supports setting this tag | 1433 // TODO(maged): Matlab doesnt error on setting this tag |
1434 // but returns 0 for getTag | |
1404 error ("Unsupported tag"); | 1435 error ("Unsupported tag"); |
1405 break; | 1436 break; |
1406 } | 1437 } |
1407 case TIFFTAG_EXTRASAMPLES: | 1438 case TIFFTAG_EXTRASAMPLES: |
1408 { | 1439 { |
1409 // TODO(maged): check if matlab validates dimensions/values of this tag | 1440 uint16_t samples_per_pixel; |
1441 if (! TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLESPERPIXEL, | |
1442 &samples_per_pixel)) | |
1443 error ("Failed to obtain the number of samples per pixel"); | |
1444 | |
1410 uint16NDArray data_array = tag_ov.uint16_array_value (); | 1445 uint16NDArray data_array = tag_ov.uint16_array_value (); |
1446 if (data_array.numel () > samples_per_pixel - 3) | |
1447 error ("Failed to set field, too many values"); | |
1448 | |
1411 if (! TIFFSetField (tif, tag_id, | 1449 if (! TIFFSetField (tif, tag_id, |
1412 static_cast<uint16_t> (data_array.dim1 ()), | 1450 static_cast<uint16_t> (data_array.numel ()), |
1413 data_array.fortran_vec ())) | 1451 data_array.data ())) |
1414 error ("Failed to set field"); | 1452 error ("Failed to set field"); |
1415 break; | 1453 break; |
1416 } | 1454 } |
1417 // TODO(maged): These tags are more complex to implement | 1455 // TODO(maged): These tags are more complex to implement |
1418 // will be implemented and tested later. | 1456 // will be implemented and tested later. |
1500 perm(0) = 2; | 1538 perm(0) = 2; |
1501 perm(1) = 1; | 1539 perm(1) = 1; |
1502 perm(2) = 0; | 1540 perm(2) = 0; |
1503 strip_data = strip_data.permute (perm); | 1541 strip_data = strip_data.permute (perm); |
1504 | 1542 |
1505 void *data_vec = strip_data.fortran_vec (); | 1543 uint8_t *data_u8 |
1544 = reinterpret_cast<uint8_t *> (strip_data.fortran_vec ()); | |
1506 if (image_data->bits_per_sample == 8 | 1545 if (image_data->bits_per_sample == 8 |
1507 || image_data->bits_per_sample == 16 | 1546 || image_data->bits_per_sample == 16 |
1508 || image_data->bits_per_sample == 32 | 1547 || image_data->bits_per_sample == 32 |
1509 || image_data->bits_per_sample == 64) | 1548 || image_data->bits_per_sample == 64) |
1510 { | 1549 { |
1511 // Can't rely on LibTIFF's TIFFStripSize because boundary strips | 1550 // Can't rely on LibTIFF's TIFFStripSize because boundary strips |
1512 // can be smaller in size | 1551 // can be smaller in size |
1513 tsize_t strip_size = strip_data.numel () | 1552 tsize_t strip_size = strip_data.numel () |
1514 * image_data->bits_per_sample / 8; | 1553 * image_data->bits_per_sample / 8; |
1515 if (TIFFWriteEncodedStrip (tif, strip_no, data_vec, strip_size) == -1) | 1554 if (TIFFWriteEncodedStrip (tif, strip_no, data_u8, strip_size) == -1) |
1516 error ("Failed to write strip data to image"); | 1555 error ("Failed to write strip data to image"); |
1517 | 1556 |
1518 } | 1557 } |
1519 else if (image_data->bits_per_sample == 1) | 1558 else if (image_data->bits_per_sample == 1) |
1520 { | 1559 { |
1524 // Create a buffer to hold the packed strip data | 1563 // Create a buffer to hold the packed strip data |
1525 // Unique pointers are faster than vectors for constant size buffers | 1564 // Unique pointers are faster than vectors for constant size buffers |
1526 std::unique_ptr<uint8_t []> strip_ptr | 1565 std::unique_ptr<uint8_t []> strip_ptr |
1527 = std::make_unique<uint8_t []> (TIFFStripSize (tif)); | 1566 = std::make_unique<uint8_t []> (TIFFStripSize (tif)); |
1528 uint8_t *strip_buf = strip_ptr.get (); | 1567 uint8_t *strip_buf = strip_ptr.get (); |
1529 uint8_t *data_u8 = reinterpret_cast<uint8_t *> (data_vec); | |
1530 // According to the format specification, the row should be byte | 1568 // According to the format specification, the row should be byte |
1531 // aligned so the number of bytes is rounded up to the nearest byte | 1569 // aligned so the number of bytes is rounded up to the nearest byte |
1532 uint32_t padded_width = (image_data->width + 7) / 8; | 1570 uint32_t padded_width = (image_data->width + 7) / 8; |
1533 // Packing the pixel data into bits | 1571 // Packing the pixel data into bits |
1534 for (uint32_t row = 0; row < rows_in_strip; row++) | 1572 for (uint32_t row = 0; row < rows_in_strip; row++) |
1602 perm(2) = 0; | 1640 perm(2) = 0; |
1603 tile_data = tile_data.permute (perm); | 1641 tile_data = tile_data.permute (perm); |
1604 | 1642 |
1605 // Octave indexing is 1-based while LibTIFF is zero-based | 1643 // Octave indexing is 1-based while LibTIFF is zero-based |
1606 tile_no--; | 1644 tile_no--; |
1607 void *data_vec = tile_data.fortran_vec (); | 1645 uint8_t *data_u8 = reinterpret_cast<uint8_t *> (tile_data.fortran_vec ()); |
1608 if (image_data->bits_per_sample == 8 | 1646 if (image_data->bits_per_sample == 8 |
1609 || image_data->bits_per_sample == 16 | 1647 || image_data->bits_per_sample == 16 |
1610 || image_data->bits_per_sample == 32 | 1648 || image_data->bits_per_sample == 32 |
1611 || image_data->bits_per_sample == 64) | 1649 || image_data->bits_per_sample == 64) |
1612 { | 1650 { |
1613 if (TIFFWriteEncodedTile (tif, tile_no, data_vec, | 1651 if (TIFFWriteEncodedTile (tif, tile_no, data_u8, |
1614 TIFFTileSize (tif)) == -1) | 1652 TIFFTileSize (tif)) == -1) |
1615 error ("Failed to write tile data to image"); | 1653 error ("Failed to write tile data to image"); |
1616 | 1654 |
1617 } | 1655 } |
1618 else if (image_data->bits_per_sample == 1) | 1656 else if (image_data->bits_per_sample == 1) |
1623 // Create a buffer to hold the packed tile data | 1661 // Create a buffer to hold the packed tile data |
1624 // Unique pointers are faster than vectors for constant size buffers | 1662 // Unique pointers are faster than vectors for constant size buffers |
1625 std::unique_ptr<uint8_t []> tile_ptr | 1663 std::unique_ptr<uint8_t []> tile_ptr |
1626 = std::make_unique<uint8_t []> (TIFFTileSize (tif)); | 1664 = std::make_unique<uint8_t []> (TIFFTileSize (tif)); |
1627 uint8_t *tile_buf = tile_ptr.get (); | 1665 uint8_t *tile_buf = tile_ptr.get (); |
1628 uint8_t *data_u8 = reinterpret_cast<uint8_t *> (data_vec); | |
1629 // Packing the pixel data into bits | 1666 // Packing the pixel data into bits |
1630 for (uint32_t row = 0; row < tile_height; row++) | 1667 for (uint32_t row = 0; row < tile_height; row++) |
1631 { | 1668 { |
1632 for (uint32_t col = 0; col < tile_width; col++) | 1669 for (uint32_t col = 0; col < tile_width; col++) |
1633 { | 1670 { |
1780 | 1817 |
1781 // The default value is INT_MAX so we need to cap it to the image height | 1818 // The default value is INT_MAX so we need to cap it to the image height |
1782 if (row_per_strip > image_data->height) | 1819 if (row_per_strip > image_data->height) |
1783 row_per_strip = image_data->height; | 1820 row_per_strip = image_data->height; |
1784 | 1821 |
1785 uint8_t *pixel_fvec = reinterpret_cast<uint8_t *> (pixel_data.fortran_vec ()); | 1822 uint8_t *pixel_fvec |
1823 = reinterpret_cast<uint8_t *> (pixel_data.fortran_vec ()); | |
1786 uint32_t strip_count = TIFFNumberOfStrips (tif); | 1824 uint32_t strip_count = TIFFNumberOfStrips (tif); |
1787 tsize_t strip_size; | 1825 tsize_t strip_size; |
1788 uint32_t rows_in_strip; | 1826 uint32_t rows_in_strip; |
1789 for (uint32_t strip = 0; strip < strip_count; strip++) | 1827 for (uint32_t strip = 0; strip < strip_count; strip++) |
1790 { | 1828 { |
1955 | 1993 |
1956 template <typename T> | 1994 template <typename T> |
1957 void | 1995 void |
1958 write_image (TIFF *tif, T pixel_data, tiff_image_data *image_data) | 1996 write_image (TIFF *tif, T pixel_data, tiff_image_data *image_data) |
1959 { | 1997 { |
1960 // TODO(maged): matlab sets the remaining to zero for less width and height | 1998 // This dimensions checking is intentially done in this non-homogeneous |
1961 // and issues a warning for larger widths but not for larger height? (we should error) | 1999 // way for matlab compatibility. |
1962 // and doesnt issue a warning for larger width for tiled images and produces zeros | 2000 // In Matlab R2022a, If the width or height of the input matrix is less |
1963 // and errors for less or more number of channels | 2001 // than needed, the data is silently padded with zeroes to fit. |
2002 // If the width is larger than needed, a warning is issued and the excess | |
2003 // data is truncated. If the height is larger than needed, no warning is | |
2004 // issued and the image data is wrong. If the number of channels is less | |
2005 // or more than needed an error is produced. | |
2006 // We chose to deviate from matlab in the larger height case to avoid | |
2007 // errors resulting from silently corrupting image data, a warning is | |
2008 // produced instead. | |
1964 if ((image_data->samples_per_pixel > 1 && pixel_data.ndims () < 3) | 2009 if ((image_data->samples_per_pixel > 1 && pixel_data.ndims () < 3) |
1965 || (pixel_data.ndims () > 2 | 2010 || (pixel_data.ndims () > 2 |
1966 && image_data->samples_per_pixel != pixel_data.dim3 ())) | 2011 && image_data->samples_per_pixel != pixel_data.dim3 ())) |
1967 error ("Incorrect number of channels, expected %u", | 2012 error ("Incorrect number of channels, expected %u", |
1968 image_data->samples_per_pixel); | 2013 image_data->samples_per_pixel); |