comparison libinterp/corefcn/__tiff__.cc @ 31173:0abc9779f751

Tiff: modified readRGBAImage to use the orientation tag correctly * __tiff__.cc (F__tiff_read_rgba_image__): modified the way the image is read to use the orientation tag in the correct way.
author magedrifaat <magedrifaat@gmail.com>
date Tue, 16 Aug 2022 16:10:10 +0200
parents 3f5f1404af8a
children 1f19e9a06f2d
comparison
equal deleted inserted replaced
31172:3f5f1404af8a 31173:0abc9779f751
794 interpret_tag_data (void *data, uint32_t count, TIFFDataType tag_datatype) 794 interpret_tag_data (void *data, uint32_t count, TIFFDataType tag_datatype)
795 { 795 {
796 octave_value retval; 796 octave_value retval;
797 // Apparently matlab converts scalar numerical values into double 797 // Apparently matlab converts scalar numerical values into double
798 // but doesn't do the same for arrays 798 // but doesn't do the same for arrays
799 // TODO(maged): matlab returns double for array tags as well, except
800 // for a selected set of tags (e.g. StripByteCounts)
799 if (count == 1 && tag_datatype != TIFF_ASCII) 801 if (count == 1 && tag_datatype != TIFF_ASCII)
800 { 802 {
801 retval = interpret_scalar_tag_data (data, tag_datatype); 803 retval = interpret_scalar_tag_data (data, tag_datatype);
802 } 804 }
803 else 805 else
2358 2360
2359 TIFF *tif = (TIFF *)(args(0).uint64_value ()); 2361 TIFF *tif = (TIFF *)(args(0).uint64_value ());
2360 2362
2361 tiff_image_data image_data (tif); 2363 tiff_image_data image_data (tif);
2362 2364
2365 uint16_t orientation;
2366 if (! TIFFGetFieldDefaulted (tif, TIFFTAG_ORIENTATION, &orientation))
2367 orientation = ORIENTATION_LEFTTOP;
2368
2363 // Start with reversed dimensions to be aligned with LibTIFF and 2369 // Start with reversed dimensions to be aligned with LibTIFF and
2364 // permute to the correct order later 2370 // permute to the correct order later
2365 dim_vector img_dims (4, image_data.width, image_data.height); 2371 dim_vector img_dims (4, image_data.width, image_data.height);
2366 uint8NDArray img (img_dims); 2372 uint8NDArray img (img_dims);
2367 uint32_t *img_ptr = reinterpret_cast <uint32_t *> (img.fortran_vec ()); 2373 uint32_t *img_ptr = reinterpret_cast <uint32_t *> (img.fortran_vec ());
2368 // Matlab (R2022a) uses a top-left orientation ignoring the tag if present 2374
2369 if (! TIFFReadRGBAImageOriented (tif, image_data.width, image_data.height, 2375 TIFFRGBAImage img_config;
2370 img_ptr, 1)) 2376 char emsg[1024];
2377 if (! TIFFRGBAImageOK (tif, emsg)
2378 || ! TIFFRGBAImageBegin (&img_config, tif, 0, emsg))
2379 error ("Failed to read image");
2380
2381 img_config.orientation = ORIENTATION_TOPLEFT;
2382 img_config.req_orientation = orientation;
2383
2384 bool success = TIFFRGBAImageGet (&img_config, img_ptr, img_config.width,
2385 img_config.height);
2386
2387 TIFFRGBAImageEnd (&img_config);
2388 if (!success)
2371 error ("Failed to read image"); 2389 error ("Failed to read image");
2372 2390
2373 // Permute to the correct Octave dimension order 2391 // Permute to the correct Octave dimension order
2374 Array<octave_idx_type> perm (dim_vector (3, 1)); 2392 Array<octave_idx_type> perm (dim_vector (3, 1));
2375 perm(0) = 2; 2393 perm(0) = 2;
2404 if (nargin != 2) 2422 if (nargin != 2)
2405 error ("Wrong number of arguments"); 2423 error ("Wrong number of arguments");
2406 2424
2407 TIFF *tif = (TIFF *)(args(0).uint64_value ()); 2425 TIFF *tif = (TIFF *)(args(0).uint64_value ());
2408 2426
2409 // TODO(maged): check matlab behavior for missing/ wrong/ out of bounds row 2427 // Matlab (R2022a) requires row to be double
2410 // matlab row must be double (scalar or array), and checks bounds 2428 if (! args(1).is_double_type ())
2429 error ("row must be double");
2430
2411 uint32_t row = args (1).uint32_scalar_value (); 2431 uint32_t row = args (1).uint32_scalar_value ();
2412 2432
2413 tiff_image_data image_data (tif); 2433 tiff_image_data image_data (tif);
2414 if (image_data.is_tiled) 2434 if (image_data.is_tiled)
2415 error ("The image is tiled not stripped"); 2435 error ("The image is tiled not stripped");
2484 error ("Wrong number of arguments"); 2504 error ("Wrong number of arguments");
2485 2505
2486 TIFF *tif = (TIFF *)(args(0).uint64_value ()); 2506 TIFF *tif = (TIFF *)(args(0).uint64_value ());
2487 2507
2488 // TODO(maged): check matlab behavior for missing/ wrong/ out of bounds vals 2508 // TODO(maged): check matlab behavior for missing/ wrong/ out of bounds vals
2509 // matlab checks bounds and requires double vals (scalar or array)
2489 uint32_t row = args (1).uint32_scalar_value (); 2510 uint32_t row = args (1).uint32_scalar_value ();
2490 uint32_t col = args (2).uint32_scalar_value (); 2511 uint32_t col = args (2).uint32_scalar_value ();
2491 2512
2492 tiff_image_data image_data (tif); 2513 tiff_image_data image_data (tif);
2493 if (! image_data.is_tiled) 2514 if (! image_data.is_tiled)
2496 if (row < 1 || row > image_data.height) 2517 if (row < 1 || row > image_data.height)
2497 error ("Row out of bounds of the image"); 2518 error ("Row out of bounds of the image");
2498 if (col < 1 || col > image_data.width) 2519 if (col < 1 || col > image_data.width)
2499 error ("Column out of bounds of the image"); 2520 error ("Column out of bounds of the image");
2500 2521
2501 // TODO(maged): check if matlab require the first row,col in tile as well
2502 // Convert from 1-based indexing to zero-based 2522 // Convert from 1-based indexing to zero-based
2503 row--; 2523 row--;
2504 col--; 2524 col--;
2505 2525
2506 uint32_t tile_width, tile_height; 2526 uint32_t tile_width, tile_height;
2521 uint8NDArray tile_data (tile_dims); 2541 uint8NDArray tile_data (tile_dims);
2522 uint32_t *tile_ptr 2542 uint32_t *tile_ptr
2523 = reinterpret_cast <uint32_t *> (tile_data.fortran_vec ()); 2543 = reinterpret_cast <uint32_t *> (tile_data.fortran_vec ());
2524 2544
2525 // TODO(maged): check if matlab does anything with orientation tag 2545 // TODO(maged): check if matlab does anything with orientation tag
2546 // matlab uses orientation tag to correct the data
2526 if (! TIFFReadRGBATile (tif, col, row, tile_ptr)) 2547 if (! TIFFReadRGBATile (tif, col, row, tile_ptr))
2527 error ("Failed to read tile"); 2548 error ("Failed to read tile");
2528 2549
2529 // Permute to the correct order of dimensions for Octave 2550 // Permute to the correct order of dimensions for Octave
2530 Array<octave_idx_type> perm (dim_vector (3, 1)); 2551 Array<octave_idx_type> perm (dim_vector (3, 1));
2900 error ("Wrong number of arguments\n"); 2921 error ("Wrong number of arguments\n");
2901 2922
2902 TIFF *tif = (TIFF *)(args(0).uint64_value ()); 2923 TIFF *tif = (TIFF *)(args(0).uint64_value ());
2903 2924
2904 // TODO(maged): check matlab behavior 2925 // TODO(maged): check matlab behavior
2926 // matlab returns double and handles the special case as 0!
2905 uint16_t dir = TIFFCurrentDirectory (tif); 2927 uint16_t dir = TIFFCurrentDirectory (tif);
2906 if (dir == (uint16_t)-1) 2928 if (dir == (uint16_t)-1)
2907 dir = 0; 2929 dir = 0;
2908 2930
2909 return octave_value_list (octave_value (dir + 1)); 2931 return octave_value_list (octave_value (dir + 1));
2940 if (nargin != 1) 2962 if (nargin != 1)
2941 error ("Wrong number of arguments\n"); 2963 error ("Wrong number of arguments\n");
2942 2964
2943 TIFF *tif = (TIFF *)(args(0).uint64_value ()); 2965 TIFF *tif = (TIFF *)(args(0).uint64_value ());
2944 2966
2945 // TODO(maged): check if matlab handles this case different from
2946 // an erronous next IFD
2947 bool is_last = TIFFLastDirectory (tif); 2967 bool is_last = TIFFLastDirectory (tif);
2948 if (is_last) 2968 if (is_last)
2949 error ("Current directory is the last directory"); 2969 error ("Current directory is the last directory");
2950 2970
2951 if (! TIFFReadDirectory (tif)) 2971 if (! TIFFReadDirectory (tif))
2966 if (nargin != 2) 2986 if (nargin != 2)
2967 error ("Wrong number of arguments\n"); 2987 error ("Wrong number of arguments\n");
2968 2988
2969 TIFF *tif = (TIFF *)(args(0).uint64_value ()); 2989 TIFF *tif = (TIFF *)(args(0).uint64_value ());
2970 2990
2971 // TODO(maged): check matlab behavior for wrong argument type
2972 // and out of bounds index
2973 uint16_t dir = args(1).uint16_scalar_value (); 2991 uint16_t dir = args(1).uint16_scalar_value ();
2974 if (dir < 1 || dir > TIFFNumberOfDirectories (tif)) 2992 if (dir < 1 || dir > TIFFNumberOfDirectories (tif))
2975 error ("Directory index out of bounds"); 2993 error ("Directory index out of bounds");
2976 2994
2977 dir--; 2995 dir--;
2993 3011
2994 if (nargin != 1) 3012 if (nargin != 1)
2995 error ("Wrong number of arguments\n"); 3013 error ("Wrong number of arguments\n");
2996 3014
2997 TIFF *tif = (TIFF *)(args(0).uint64_value ()); 3015 TIFF *tif = (TIFF *)(args(0).uint64_value ());
2998 // TODO(maged): check if matlab errors for leaving a corrupt directory 3016 // TODO(maged): Check if mtalab always writes directories at the end for both w and a (And r+)
2999 // Check if mtalab always writes directories at the end for both w and a (And r+) 3017 // it does
3000 if (! TIFFWriteDirectory(tif)) 3018 if (! TIFFWriteDirectory(tif))
3001 error ("Failed to write directory"); 3019 error ("Failed to write directory");
3002 3020
3003 return octave_value_list (); 3021 return octave_value_list ();
3004 #else 3022 #else
3014 3032
3015 if (nargin != 1) 3033 if (nargin != 1)
3016 error ("Wrong number of arguments\n"); 3034 error ("Wrong number of arguments\n");
3017 3035
3018 TIFF *tif = (TIFF *)(args(0).uint64_value ()); 3036 TIFF *tif = (TIFF *)(args(0).uint64_value ());
3019 // TODO(maged): check if matlab errors for leaving a corrupt directory 3037
3020 // check if matlab changes directory after the call or switches back
3021 if (! TIFFRewriteDirectory(tif)) 3038 if (! TIFFRewriteDirectory(tif))
3022 error ("Failed to rewrite directory"); 3039 error ("Failed to rewrite directory");
3023 3040
3024 return octave_value_list (); 3041 return octave_value_list ();
3025 #else 3042 #else
3037 error ("Wrong number of arguments\n"); 3054 error ("Wrong number of arguments\n");
3038 3055
3039 TIFF *tif = (TIFF *)(args(0).uint64_value ()); 3056 TIFF *tif = (TIFF *)(args(0).uint64_value ());
3040 3057
3041 // TODO(maged): check if matlab requires scalar double 3058 // TODO(maged): check if matlab requires scalar double
3059 // matlab expects double, uint32, or uint64
3060 // and checks the subIFD tag first
3042 uint64_t offset = args(1).uint64_scalar_value (); 3061 uint64_t offset = args(1).uint64_scalar_value ();
3043 if (! TIFFSetSubDirectory (tif, offset)) 3062 if (! TIFFSetSubDirectory (tif, offset))
3044 error ("Failed to switch to the sub directory"); 3063 error ("Failed to switch to the sub directory");
3045 3064
3046 return octave_value_list (); 3065 return octave_value_list ();