3
0

TIFFLoader.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/Debug/Trace.h>
  9. #include <AzCore/Math/MathUtils.h>
  10. #include <ImageLoader/ImageLoaders.h>
  11. #include <Atom/ImageProcessing/ImageObject.h>
  12. #include <Processing/PixelFormatInfo.h>
  13. #include <QString>
  14. #include <tiffio.h> // TIFF library
  15. namespace ImageProcessingAtom
  16. {
  17. namespace TIFFLoader
  18. {
  19. #ifdef AZ_ENABLE_TRACING
  20. static constexpr int TiffMaxMessageSize = 1024;
  21. // Note: the fatal errors are processed in LoadImageFromTIFF function.
  22. // We only report the errors as warning here.
  23. static void ImageProcessingTiffErrorHandler(const char* module, const char* format, va_list argList)
  24. {
  25. char buffer[TiffMaxMessageSize];
  26. azvsnprintf(buffer, TiffMaxMessageSize, format, argList);
  27. AZ_Warning(module, false, buffer);
  28. }
  29. #endif
  30. class TiffFileRead
  31. {
  32. public:
  33. TiffFileRead(const AZStd::string& filename)
  34. : m_tif(nullptr)
  35. {
  36. m_tif = TIFFOpen(filename.c_str(), "r");
  37. }
  38. ~TiffFileRead()
  39. {
  40. if (m_tif != nullptr)
  41. {
  42. TIFFClose(m_tif);
  43. }
  44. }
  45. TIFF* GetTiff()
  46. {
  47. return m_tif;
  48. }
  49. private:
  50. TIFF* m_tif;
  51. };
  52. bool IsExtensionSupported(const char* extension)
  53. {
  54. QString ext = QString(extension).toLower();
  55. // This is the list of file extensions supported by this loader
  56. return ext == "tif" || ext == "tiff";
  57. }
  58. // loads image from a TIFF structure and converts to an Atom image.
  59. static IImageObject* LoadImageFromTIFFInternal(TIFF* tif);
  60. // Based on the input TIFF format, choose an appropriate output pixel format.
  61. static EPixelFormat GetOutputPixelFormat(uint32_t dwChannels, uint32_t dwBitsPerChannel, uint32_t dwFormat);
  62. IImageObject* LoadImageFromTIFF(const AZStd::string& filename)
  63. {
  64. #ifdef AZ_ENABLE_TRACING
  65. // Reroute the TIFF loader Error Handler so that any load errors are recorded.
  66. // There is also a warning handler that can get rerouted via TIFFSetWarningHandler, but the warnings include noisy notices
  67. // like 'tiff tag X unsupported', so it isn't currently hooked up here.
  68. TIFFSetErrorHandler(ImageProcessingTiffErrorHandler);
  69. #endif
  70. TiffFileRead tiffRead(filename);
  71. TIFF* tif = tiffRead.GetTiff();
  72. IImageObject* pRet = nullptr;
  73. if (!tif)
  74. {
  75. AZ_Warning("Image Processing", false, "%s: Open tiff failed (%s)", __FUNCTION__, filename.c_str());
  76. return pRet;
  77. }
  78. uint32_t dwBitsPerChannel = 0;
  79. uint32_t dwChannels = 0;
  80. uint32_t dwFormat = 0;
  81. TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &dwChannels);
  82. TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &dwBitsPerChannel);
  83. TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLEFORMAT, &dwFormat);
  84. if (dwChannels != 1 && dwChannels != 2 && dwChannels != 3 && dwChannels != 4)
  85. {
  86. AZ_Warning("Image Processing", false, "Unsupported TIFF pixel format (channel count: %d)", dwChannels);
  87. return pRet;
  88. }
  89. uint32_t dwWidth = 0;
  90. uint32_t dwHeight = 0;
  91. TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &dwWidth);
  92. TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &dwHeight);
  93. if (dwWidth <= 0 || dwHeight <= 0)
  94. {
  95. AZ_Error("Image Processing", false, "%s failed (empty image)", __FUNCTION__);
  96. return pRet;
  97. }
  98. bool validFormat = false;
  99. // Currently, we only support uint/int TIFFs with 8 or 16 bits per channel and float TIFFs with 16 or 32 bits per channel.
  100. switch (dwFormat)
  101. {
  102. case SAMPLEFORMAT_UINT:
  103. case SAMPLEFORMAT_INT:
  104. if ((dwBitsPerChannel == 8) || (dwBitsPerChannel == 16))
  105. {
  106. pRet = LoadImageFromTIFFInternal(tif);
  107. validFormat = true;
  108. }
  109. break;
  110. case SAMPLEFORMAT_IEEEFP:
  111. if ((dwBitsPerChannel == 16) || (dwBitsPerChannel == 32))
  112. {
  113. pRet = LoadImageFromTIFFInternal(tif);
  114. validFormat = true;
  115. }
  116. break;
  117. default:
  118. // Unsupported format, invalid.
  119. break;
  120. }
  121. if (!validFormat)
  122. {
  123. AZ_Error(
  124. "Image Processing", false, "File %s has unsupported TIFF pixel format. sample channels: %d,\
  125. bits per channel: %d, sample format: %d",
  126. filename.c_str(), dwChannels, dwBitsPerChannel, dwFormat);
  127. return pRet;
  128. }
  129. if (pRet == nullptr)
  130. {
  131. AZ_Error("Image Processing", false, "Failed to read TIFF pixels");
  132. return pRet;
  133. }
  134. return pRet;
  135. }
  136. static EPixelFormat GetOutputPixelFormat(uint32_t numChannels, uint32_t bitsPerChannel, uint32_t channelFormat)
  137. {
  138. // The output formats we want to convert the TIFF into, based on the number of input channels, bit depth, and format.
  139. // The 2-channel choices below are arbitrary, we might someday want to consider converting them to 2-channel outputs.
  140. static constexpr EPixelFormat output8BitIntFormats[4] = {
  141. ePixelFormat_R8, // 1 channel in goes to 1 channel out
  142. ePixelFormat_R8G8B8X8, // 2 channels in becomes RGBA with A=100%
  143. ePixelFormat_R8G8B8X8, // 3 channels in becomes RGBA with A=100%
  144. ePixelFormat_R8G8B8A8 // 4 channels in goes to 4 channels out
  145. };
  146. static constexpr EPixelFormat output16BitIntFormats[4] = {
  147. ePixelFormat_R16, // 1 channel in goes to 1 channel out
  148. ePixelFormat_R16G16B16A16, // 2 channels in becomes RGBA with A=100%
  149. ePixelFormat_R16G16B16A16, // 3 channels in becomes RGBA with A=100%
  150. ePixelFormat_R16G16B16A16 // 4 channels in goes to 4 channels out
  151. };
  152. static constexpr EPixelFormat output16BitFloatFormats[4] = {
  153. ePixelFormat_R16F, // 1 channel in goes to 1 channel out
  154. ePixelFormat_R16G16B16A16F, // 2 channels in becomes RGBA with A=100%
  155. ePixelFormat_R16G16B16A16F, // 3 channels in becomes RGBA with A=100%
  156. ePixelFormat_R16G16B16A16F // 4 channels in goes to 4 channels out
  157. };
  158. static constexpr EPixelFormat output32BitFloatFormats[4] = {
  159. ePixelFormat_R32F, // 1 channel in goes to 1 channel out
  160. ePixelFormat_R32G32B32A32F, // 2 channels in becomes RGBA with A=100%
  161. ePixelFormat_R32G32B32A32F, // 3 channels in becomes RGBA with A=100%
  162. ePixelFormat_R32G32B32A32F // 4 channels in goes to 4 channels out
  163. };
  164. bool isIntFormat = (channelFormat == SAMPLEFORMAT_INT) || (channelFormat == SAMPLEFORMAT_UINT);
  165. if ((bitsPerChannel == 8) && isIntFormat)
  166. {
  167. return output8BitIntFormats[numChannels - 1];
  168. }
  169. else if ((bitsPerChannel == 16) && isIntFormat)
  170. {
  171. return output16BitIntFormats[numChannels - 1];
  172. }
  173. else if ((bitsPerChannel == 16) && (channelFormat == SAMPLEFORMAT_IEEEFP))
  174. {
  175. return output16BitFloatFormats[numChannels - 1];
  176. }
  177. else if ((bitsPerChannel == 32) && (channelFormat == SAMPLEFORMAT_IEEEFP))
  178. {
  179. return output32BitFloatFormats[numChannels - 1];
  180. }
  181. else
  182. {
  183. // Error, unsupported format.
  184. return ePixelFormat_Unknown;
  185. }
  186. }
  187. static IImageObject* LoadImageFromTIFFInternal(TIFF* tif)
  188. {
  189. uint32_t bitsPerChannel = 0;
  190. uint32_t numChannels = 0;
  191. uint32_t photometricFormat = 0;
  192. uint32_t sampleFormat = 0;
  193. TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitsPerChannel);
  194. TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &numChannels);
  195. TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometricFormat);
  196. TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLEFORMAT, &sampleFormat);
  197. uint32_t inputImageWidth = 0;
  198. uint32_t inputImageHeight = 0;
  199. TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &inputImageWidth);
  200. TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &inputImageHeight);
  201. uint32_t tileWidth = 0;
  202. uint32_t tileHeight = 0;
  203. TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth);
  204. TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileHeight);
  205. bool isTiled = (tileWidth > 0) && (tileHeight > 0);
  206. bool isIntFormat = (sampleFormat == SAMPLEFORMAT_INT) || (sampleFormat == SAMPLEFORMAT_UINT);
  207. EPixelFormat outputPixelFormat = GetOutputPixelFormat(numChannels, bitsPerChannel, sampleFormat);
  208. if (outputPixelFormat == ePixelFormat_Unknown)
  209. {
  210. return nullptr;
  211. }
  212. if ((photometricFormat == PHOTOMETRIC_SEPARATED) && (sampleFormat == SAMPLEFORMAT_IEEEFP))
  213. {
  214. AZ_Error("Image Processing", false, "Separated Photometric format isn't supported with floating-point images.");
  215. return nullptr;
  216. }
  217. uint32_t dstChannels = CPixelFormats::GetInstance().GetPixelFormatInfo(outputPixelFormat)->nChannels;
  218. IImageObject* pRet = IImageObject::CreateImage(inputImageWidth, inputImageHeight, 1, outputPixelFormat);
  219. uint8_t* dst;
  220. uint32_t dwPitch;
  221. pRet->GetImagePointer(0, dst, dwPitch);
  222. // Determine if this is a scanline-based or tile-based TIFF, and size our temporary buffer appropriately.
  223. size_t bufSize = 0;
  224. if (isTiled)
  225. {
  226. // Tiled TIFF, so our buffer needs to be tile-sized
  227. bufSize = TIFFTileSize(tif);
  228. }
  229. else
  230. {
  231. // Scanline TIFF, so our buffer needs to be scanline-sized.
  232. bufSize = TIFFScanlineSize(tif);
  233. // For our processing loops, we'll treat scanlines like a tile of 1 x width size.
  234. tileHeight = 1;
  235. tileWidth = inputImageWidth;
  236. }
  237. AZStd::vector<uint8_t> buf(bufSize);
  238. // There are two types of 32-bit floating point TIF semantics. Paint programs tend to use values in the 0.0 - 1.0 range.
  239. // GeoTIFF files use values where 1.0 = 1 meter by default, but also have an optional ZScale parameter to provide additional
  240. // scaling control.
  241. // By default, we'll assume this is a regular TIFF that we want to leave in the 0.0 - 1.0 range.
  242. float pixelValueScale = 1.0f;
  243. // Check to see if it's a GeoTIFF, and if so, whether or not it has the ZScale parameter.
  244. // Defined in GeoTIFF format -
  245. // http://web.archive.org/web/20160403164508/http://www.remotesensing.org/geotiff/spec/geotiffhome.html
  246. // Used to get the X, Y, Z scales from a GeoTIFF file
  247. bool isGeoTIFF = false;
  248. {
  249. uint32 tagCount = 0;
  250. double* pixelScales = NULL;
  251. static constexpr int GEOTIFF_MODELPIXELSCALE_TAG = 33550;
  252. if (TIFFGetField(tif, GEOTIFF_MODELPIXELSCALE_TAG, &tagCount, &pixelScales) == 1)
  253. {
  254. isGeoTIFF = true;
  255. // if there's an xyz scale, and the Z scale isn't 0, let's use it.
  256. if ((tagCount == 3) && (pixelScales != NULL) && (pixelScales[2] != 0.0f))
  257. {
  258. pixelValueScale = static_cast<float>(pixelScales[2]);
  259. }
  260. }
  261. }
  262. // Track min/max values for GeoTIFFs so that we can scale the values into the 0-1 range.
  263. float minChannelValue = AZStd::numeric_limits<float>::max();
  264. float maxChannelValue = AZStd::numeric_limits<float>::lowest();
  265. // Copy one channel of one pixel from source to destination, and optionally invert the value.
  266. auto CopyPixelChannel = [bitsPerChannel, pixelValueScale, &buf, &dst, &minChannelValue, &maxChannelValue]
  267. (uint32_t destPixelChannelIndex, uint32_t srcPixelChannelIndex, bool invert = false)
  268. {
  269. if (bitsPerChannel == 8)
  270. {
  271. dst[destPixelChannelIndex] = invert ? (0xFF - buf[srcPixelChannelIndex]) : buf[srcPixelChannelIndex];
  272. }
  273. else if (bitsPerChannel == 16)
  274. {
  275. // Alias the base pointers to a 16-bit channel type, then use the channel index to get to the correct pixel & channel
  276. uint16_t* buf16 = reinterpret_cast<uint16_t*>(buf.data());
  277. uint16_t* dst16 = reinterpret_cast<uint16_t*>(dst);
  278. dst16[destPixelChannelIndex] = invert ? (0xFFFF - buf16[srcPixelChannelIndex]) : buf16[srcPixelChannelIndex];
  279. }
  280. else
  281. {
  282. // Alias the base pointers to a 32-bit channel type, then use the channel index to get to the correct pixel & channel
  283. float* buf32 = reinterpret_cast<float*>(buf.data());
  284. float* dst32 = reinterpret_cast<float*>(dst);
  285. // GeoTIFFs might have a pixel scale, so apply it.
  286. const float scaledValue = buf32[srcPixelChannelIndex] * pixelValueScale;
  287. // Track min/max values, but exclude the lowest float value, as that might be a "no data" value for GeoTIFFs.
  288. if (scaledValue > AZStd::numeric_limits<float>::lowest())
  289. {
  290. minChannelValue = AZStd::min(minChannelValue, scaledValue);
  291. maxChannelValue = AZStd::max(maxChannelValue, scaledValue);
  292. }
  293. // We ignore the inversion flag for floats, it will always be false.
  294. dst32[destPixelChannelIndex] = scaledValue;
  295. }
  296. };
  297. // Set one channel of one pixel in the destination to a specific value.
  298. auto SetPixelChannel = [bitsPerChannel, &dst](uint32_t dstIdx, uint32_t value)
  299. {
  300. if (bitsPerChannel == 8)
  301. {
  302. dst[dstIdx] = static_cast<uint8_t>(value);
  303. }
  304. else if (bitsPerChannel == 16)
  305. {
  306. // Alias the base pointers to a 16-bit channel type, then use the channel index to get to the correct pixel & channel
  307. uint16_t* dst16 = reinterpret_cast<uint16_t*>(dst);
  308. dst16[dstIdx] = static_cast<uint16_t>(value);
  309. }
  310. else
  311. {
  312. // Alias the base pointers to a 32-bit channel type, then use the channel index to get to the correct pixel & channel
  313. float* dst32 = reinterpret_cast<float*>(dst);
  314. dst32[dstIdx] = static_cast<float>(value);
  315. }
  316. };
  317. // Loop across the image height, one tile at a time
  318. for (uint32_t imageY = 0; imageY < inputImageHeight; imageY += tileHeight)
  319. {
  320. // Loop across the image width, one tile at a time
  321. for (uint32 imageX = 0; imageX < inputImageWidth; imageX += tileWidth)
  322. {
  323. // Either read in a tile or a scanline
  324. [[maybe_unused]] auto result = isTiled?
  325. TIFFReadTile(tif, buf.data(), imageX, imageY, 0, 0):
  326. TIFFReadScanline(tif, buf.data(), imageY);
  327. // non-fatal error, only print the warning
  328. // For details: https://github.com/o3de/o3de/pull/8929
  329. AZ_Warning("TIFFLoader", !(result == -1), "Read tiff image data from %s error at row %d", TIFFFileName(tif), imageY);
  330. // Convert each pixel in the scanline / tile buffer.
  331. // The image might not be evenly divisible by tile height/width, so don't process any pixels outside those bounds.
  332. for (uint32 tileY = 0; (tileY < tileHeight) && ((imageY + tileY) < inputImageHeight); tileY++)
  333. {
  334. for (uint32 tileX = 0; (tileX < tileWidth) && ((imageX + tileX) < inputImageWidth); tileX++)
  335. {
  336. // Calculate the buffer start index for the source and destination pixels.
  337. // These indices are by channel, not by byte, so for example a 2x2 R16G16B16A16 image will have
  338. // pixel channel indices of 0, 4, 8, 12. If they were by byte, they'd be 0, 8, 16, 24.
  339. // Also, note that the destination image provides a "pitch" value that's the number of bytes per row,
  340. // which could include padding. Since that value is in bytes, we divide by bytes per channel so that
  341. // our index is back in channel range, not byte range.
  342. uint32 srcPixelChannelIndex = ((tileY * tileWidth) + tileX) * numChannels;
  343. uint32 destPixelChannelIndex =
  344. ((imageY + tileY) * (dwPitch / (bitsPerChannel / 8))) +
  345. ((imageX + tileX) * dstChannels);
  346. if (numChannels == 1)
  347. {
  348. // One channel, perform a straight copy.
  349. CopyPixelChannel(destPixelChannelIndex, srcPixelChannelIndex);
  350. }
  351. else if (numChannels == 2)
  352. {
  353. if (photometricFormat == PHOTOMETRIC_SEPARATED)
  354. {
  355. // convert CMY to RGB (PHOTOMETRIC_SEPARATED refers to inks in TIFF, the value is inverted)
  356. constexpr bool invert = true;
  357. CopyPixelChannel(destPixelChannelIndex + 0, srcPixelChannelIndex + 0, invert);
  358. CopyPixelChannel(destPixelChannelIndex + 1, srcPixelChannelIndex + 1, invert);
  359. SetPixelChannel(destPixelChannelIndex + 2, 0x00000000);
  360. SetPixelChannel(destPixelChannelIndex + 3, isIntFormat ? 0xFFFFFFFF : 1);
  361. }
  362. else
  363. {
  364. // Not separated, so just copy the two channels, and fill in the other two channels with defaults.
  365. CopyPixelChannel(destPixelChannelIndex + 0, srcPixelChannelIndex + 0);
  366. CopyPixelChannel(destPixelChannelIndex + 1, srcPixelChannelIndex + 1);
  367. SetPixelChannel(destPixelChannelIndex + 2, 0x00000000);
  368. SetPixelChannel(destPixelChannelIndex + 3, isIntFormat ? 0xFFFFFFFF : 1);
  369. }
  370. }
  371. else if (numChannels == 3)
  372. {
  373. // 3 channels, copy over RGB and fill in Alpha with a default.
  374. CopyPixelChannel(destPixelChannelIndex + 0, srcPixelChannelIndex + 0);
  375. CopyPixelChannel(destPixelChannelIndex + 1, srcPixelChannelIndex + 1);
  376. CopyPixelChannel(destPixelChannelIndex + 2, srcPixelChannelIndex + 2);
  377. SetPixelChannel(destPixelChannelIndex + 3, isIntFormat ? 0xFFFFFFFF : 1);
  378. }
  379. else
  380. {
  381. // 4 channels, just perform a straight copy.
  382. CopyPixelChannel(destPixelChannelIndex + 0, srcPixelChannelIndex + 0);
  383. CopyPixelChannel(destPixelChannelIndex + 1, srcPixelChannelIndex + 1);
  384. CopyPixelChannel(destPixelChannelIndex + 2, srcPixelChannelIndex + 2);
  385. CopyPixelChannel(destPixelChannelIndex + 3, srcPixelChannelIndex + 3);
  386. }
  387. }
  388. }
  389. }
  390. }
  391. // A GeoTIFF image contains real-world height values, so the values could potentially range from roughly +/- 10000 meters.
  392. // To make this data usable in-engine, it will get scaled to 0.0 - 1.0, based on the min/max values found in the file.
  393. if (isGeoTIFF && (sampleFormat == SAMPLEFORMAT_IEEEFP))
  394. {
  395. float* dst32 = reinterpret_cast<float*>(dst);
  396. for (uint32 imageY = 0; imageY < inputImageHeight; imageY++)
  397. {
  398. for (uint32 imageX = 0; imageX < inputImageWidth; imageX++)
  399. {
  400. uint32 pixelChannelIndex = (imageY * (dwPitch / (bitsPerChannel / 8))) + (imageX * dstChannels);
  401. dst32[pixelChannelIndex] =
  402. AZStd::clamp((dst32[pixelChannelIndex] - minChannelValue) / (maxChannelValue - minChannelValue), 0.0f, 1.0f);
  403. }
  404. }
  405. }
  406. return pRet;
  407. }
  408. }// namespace ImageTIFF
  409. } //namespace ImageProcessingAtom