@@ -586,71 +586,6 @@ EditISIS3MetadataForBandChange(const char *pszJSON, int nSrcBandCount,
586
586
return oRoot.Format (CPLJSONObject::PrettyFormat::Pretty);
587
587
}
588
588
589
- /* ***********************************************************************/
590
- /* AdjustNoDataValue() */
591
- /* ***********************************************************************/
592
-
593
- static double AdjustNoDataValue (double dfInputNoDataValue,
594
- GDALRasterBand *poBand,
595
- const GDALTranslateOptions *psOptions)
596
- {
597
- bool bSignedByte = false ;
598
- const char *pszPixelType =
599
- psOptions->aosCreateOptions .FetchNameValue (" PIXELTYPE" );
600
- if (pszPixelType == nullptr && poBand->GetRasterDataType () == GDT_Byte)
601
- {
602
- poBand->EnablePixelTypeSignedByteWarning (false );
603
- pszPixelType = poBand->GetMetadataItem (" PIXELTYPE" , " IMAGE_STRUCTURE" );
604
- poBand->EnablePixelTypeSignedByteWarning (true );
605
- }
606
- if (pszPixelType != nullptr && EQUAL (pszPixelType, " SIGNEDBYTE" ))
607
- bSignedByte = true ;
608
- int bClamped = FALSE ;
609
- int bRounded = FALSE ;
610
- double dfVal = 0.0 ;
611
- const GDALDataType eBandType = poBand->GetRasterDataType ();
612
- if (bSignedByte)
613
- {
614
- if (dfInputNoDataValue < -128.0 )
615
- {
616
- dfVal = -128.0 ;
617
- bClamped = TRUE ;
618
- }
619
- else if (dfInputNoDataValue > 127.0 )
620
- {
621
- dfVal = 127.0 ;
622
- bClamped = TRUE ;
623
- }
624
- else
625
- {
626
- dfVal = static_cast <int >(floor (dfInputNoDataValue + 0.5 ));
627
- if (dfVal != dfInputNoDataValue)
628
- bRounded = TRUE ;
629
- }
630
- }
631
- else
632
- {
633
- dfVal = GDALAdjustValueToDataType (eBandType, dfInputNoDataValue,
634
- &bClamped, &bRounded);
635
- }
636
-
637
- if (bClamped)
638
- {
639
- CPLError (CE_Warning, CPLE_AppDefined,
640
- " for band %d, nodata value has been clamped "
641
- " to %.0f, the original value being out of range." ,
642
- poBand->GetBand (), dfVal);
643
- }
644
- else if (bRounded)
645
- {
646
- CPLError (CE_Warning, CPLE_AppDefined,
647
- " for band %d, nodata value has been rounded "
648
- " to %.0f, %s being an integer datatype." ,
649
- poBand->GetBand (), dfVal, GDALGetDataTypeName (eBandType));
650
- }
651
- return dfVal;
652
- }
653
-
654
589
/* ***********************************************************************/
655
590
/* GDALTranslate() */
656
591
/* ***********************************************************************/
@@ -1128,7 +1063,19 @@ GDALDatasetH GDALTranslate(const char *pszDest, GDALDatasetH hSrcDataset,
1128
1063
/* This is needed for */
1129
1064
/* gdal_translate foo.tif foo.tif.ovr -outsize 50% 50% */
1130
1065
/* -------------------------------------------------------------------- */
1131
- if (!psOptions->aosCreateOptions .FetchBool (" APPEND_SUBDATASET" , false ))
1066
+ if (psOptions->aosCreateOptions .FetchBool (" APPEND_SUBDATASET" , false ))
1067
+ {
1068
+ if (GDALGetMetadataItem (hDriver, GDAL_DCAP_CREATE_SUBDATASETS,
1069
+ nullptr ) == nullptr )
1070
+ {
1071
+ CPLError (CE_Failure, CPLE_NotSupported,
1072
+ " Subdataset creation not supported for driver %s" ,
1073
+ GDALGetDescription (hDriver));
1074
+ GDALTranslateOptionsFree (psOptions);
1075
+ return nullptr ;
1076
+ }
1077
+ }
1078
+ else
1132
1079
{
1133
1080
if (!EQUAL (psOptions->osFormat .c_str (), " VRT" ))
1134
1081
{
@@ -2496,87 +2443,46 @@ GDALDatasetH GDALTranslate(const char *pszDest, GDALDatasetH hSrcDataset,
2496
2443
*/
2497
2444
if (psOptions->bSetNoData )
2498
2445
{
2499
- if (poVRTBand->GetRasterDataType () == GDT_Int64)
2500
- {
2501
- if (psOptions->osNoData .find (' .' ) != std::string::npos ||
2502
- CPLGetValueType (psOptions->osNoData .c_str ()) ==
2503
- CPL_VALUE_STRING)
2504
- {
2505
- const double dfNoData =
2506
- CPLAtof (psOptions->osNoData .c_str ());
2507
- if (GDALIsValueExactAs<int64_t >(dfNoData))
2508
- {
2509
- poVRTBand->SetNoDataValueAsInt64 (
2510
- static_cast <int64_t >(dfNoData));
2511
- }
2512
- else
2513
- {
2514
- CPLError (CE_Warning, CPLE_AppDefined,
2515
- " Cannot set nodata value %s on a Int64 band" ,
2516
- psOptions->osNoData .c_str ());
2517
- }
2518
- }
2519
- else
2520
- {
2521
- errno = 0 ;
2522
- const auto val =
2523
- std::strtoll (psOptions->osNoData .c_str (), nullptr , 10 );
2524
- if (errno == 0 )
2525
- {
2526
- poVRTBand->SetNoDataValueAsInt64 (
2527
- static_cast <int64_t >(val));
2528
- }
2529
- else
2530
- {
2531
- CPLError (CE_Warning, CPLE_AppDefined,
2532
- " Cannot set nodata value %s on a Int64 band" ,
2533
- psOptions->osNoData .c_str ());
2534
- }
2535
- }
2446
+ const char *pszPixelType =
2447
+ psOptions->aosCreateOptions .FetchNameValue (" PIXELTYPE" );
2448
+ if (pszPixelType == nullptr &&
2449
+ poVRTBand->GetRasterDataType () == GDT_Byte)
2450
+ {
2451
+ poVRTBand->EnablePixelTypeSignedByteWarning (false );
2452
+ pszPixelType =
2453
+ poVRTBand->GetMetadataItem (" PIXELTYPE" , " IMAGE_STRUCTURE" );
2454
+ poVRTBand->EnablePixelTypeSignedByteWarning (true );
2536
2455
}
2537
- else if (poVRTBand->GetRasterDataType () == GDT_UInt64)
2456
+
2457
+ bool bCannotBeExactlyRepresented = false ;
2458
+
2459
+ if (pszPixelType != nullptr && EQUAL (pszPixelType, " SIGNEDBYTE" ))
2538
2460
{
2539
- if (psOptions->osNoData .find (' .' ) != std::string::npos ||
2540
- CPLGetValueType (psOptions->osNoData .c_str ()) ==
2541
- CPL_VALUE_STRING)
2461
+ char *endptr = nullptr ;
2462
+ const double dfVal =
2463
+ CPLStrtod (psOptions->osNoData .c_str (), &endptr);
2464
+ if (endptr == psOptions->osNoData .c_str () +
2465
+ psOptions->osNoData .size () &&
2466
+ dfVal >= -128.0 && dfVal <= 127.0 &&
2467
+ static_cast <int8_t >(dfVal) == dfVal)
2542
2468
{
2543
- const double dfNoData =
2544
- CPLAtof (psOptions->osNoData .c_str ());
2545
- if (GDALIsValueExactAs<uint64_t >(dfNoData))
2546
- {
2547
- poVRTBand->SetNoDataValueAsUInt64 (
2548
- static_cast <uint64_t >(dfNoData));
2549
- }
2550
- else
2551
- {
2552
- CPLError (CE_Warning, CPLE_AppDefined,
2553
- " Cannot set nodata value %s on a UInt64 band" ,
2554
- psOptions->osNoData .c_str ());
2555
- }
2469
+ poVRTBand->SetNoDataValue (dfVal);
2556
2470
}
2557
2471
else
2558
2472
{
2559
- errno = 0 ;
2560
- const auto val =
2561
- std::strtoull (psOptions->osNoData .c_str (), nullptr , 10 );
2562
- if (errno == 0 )
2563
- {
2564
- poVRTBand->SetNoDataValueAsUInt64 (
2565
- static_cast <uint64_t >(val));
2566
- }
2567
- else
2568
- {
2569
- CPLError (CE_Warning, CPLE_AppDefined,
2570
- " Cannot set nodata value %s on a UInt64 band" ,
2571
- psOptions->osNoData .c_str ());
2572
- }
2473
+ bCannotBeExactlyRepresented = true ;
2573
2474
}
2574
2475
}
2575
2476
else
2576
2477
{
2577
- const double dfVal = AdjustNoDataValue (
2578
- CPLAtof (psOptions->osNoData .c_str ()), poVRTBand, psOptions);
2579
- poVRTBand->SetNoDataValue (dfVal);
2478
+ poVRTBand->SetNoDataValueAsString (psOptions->osNoData .c_str (),
2479
+ &bCannotBeExactlyRepresented);
2480
+ }
2481
+ if (bCannotBeExactlyRepresented)
2482
+ {
2483
+ CPLError (CE_Warning, CPLE_AppDefined,
2484
+ " Nodata value was not set to output band, "
2485
+ " as it cannot be represented on its data type." );
2580
2486
}
2581
2487
}
2582
2488
@@ -2758,7 +2664,7 @@ static void AttachDomainMetadata(GDALDatasetH hDS,
2758
2664
static void CopyBandInfo (GDALRasterBand *poSrcBand, GDALRasterBand *poDstBand,
2759
2665
int bCanCopyStatsMetadata, int bCopyScale,
2760
2666
int bCopyNoData, bool bCopyRAT,
2761
- const GDALTranslateOptions *psOptions)
2667
+ const GDALTranslateOptions * /* psOptions*/ )
2762
2668
2763
2669
{
2764
2670
@@ -2809,24 +2715,20 @@ static void CopyBandInfo(GDALRasterBand *poSrcBand, GDALRasterBand *poDstBand,
2809
2715
2810
2716
if (bCopyNoData)
2811
2717
{
2812
- if (poSrcBand->GetRasterDataType () != GDT_Int64 &&
2813
- poSrcBand->GetRasterDataType () != GDT_UInt64 &&
2814
- poDstBand->GetRasterDataType () != GDT_Int64 &&
2815
- poDstBand->GetRasterDataType () != GDT_UInt64)
2718
+ int bSuccess = FALSE ;
2719
+ CPL_IGNORE_RET_VAL (poSrcBand->GetNoDataValue (&bSuccess));
2720
+ if (bSuccess)
2816
2721
{
2817
- int bSuccess = FALSE ;
2818
- double dfNoData = poSrcBand->GetNoDataValue (&bSuccess);
2819
- if (bSuccess)
2722
+ bool bCannotBeExactlyRepresented = false ;
2723
+ if (!GDALCopyNoDataValue (poDstBand, poSrcBand,
2724
+ &bCannotBeExactlyRepresented) &&
2725
+ bCannotBeExactlyRepresented)
2820
2726
{
2821
- const double dfVal =
2822
- AdjustNoDataValue (dfNoData, poDstBand, psOptions);
2823
- poDstBand-> SetNoDataValue (dfVal );
2727
+ CPLError (CE_Warning, CPLE_AppDefined,
2728
+ " Source nodata value was not copied to output band, "
2729
+ " as it cannot be represented on its data type. " );
2824
2730
}
2825
2731
}
2826
- else
2827
- {
2828
- GDALCopyNoDataValue (poDstBand, poSrcBand);
2829
- }
2830
2732
}
2831
2733
2832
2734
if (bCopyScale)
@@ -3516,7 +3418,7 @@ GDALTranslateOptionsNew(char **papszArgv,
3516
3418
{
3517
3419
++i;
3518
3420
const std::string s = papszArgv[i];
3519
- if (EQUAL (s.c_str (), " none" ))
3421
+ if (EQUAL (s.c_str (), " none" ) || EQUAL (s. c_str (), " null " ) )
3520
3422
{
3521
3423
psOptions->bUnsetNoData = true ;
3522
3424
}
0 commit comments