diff --git a/CesiumGltf/include/CesiumGltf/ImageAsset.h b/CesiumGltf/include/CesiumGltf/ImageAsset.h index aab21b9c9..f61412cd5 100644 --- a/CesiumGltf/include/CesiumGltf/ImageAsset.h +++ b/CesiumGltf/include/CesiumGltf/ImageAsset.h @@ -23,6 +23,11 @@ struct CESIUMGLTF_API ImageAssetMipPosition { * @brief The size in bytes of this mip. */ size_t byteSize; + + /** + * @brief The pitch (or stride) between rows of this mip in bytes. + */ + size_t rowPitch; }; /** diff --git a/CesiumGltfReader/src/ImageDecoder.cpp b/CesiumGltfReader/src/ImageDecoder.cpp index 9d653dcaf..75b2504e1 100644 --- a/CesiumGltfReader/src/ImageDecoder.cpp +++ b/CesiumGltfReader/src/ImageDecoder.cpp @@ -231,8 +231,10 @@ ImageReaderResult ImageDecoder::readImage( &imageOffset); ktx_size_t imageSize = ktxTexture_GetImageSize(ktxTexture(pTexture), level); + ktx_uint32_t rowPitch = + ktxTexture_GetRowPitch(ktxTexture(pTexture), level); - image.mipPositions[level] = {imageOffset, imageSize}; + image.mipPositions[level] = {imageOffset, imageSize, rowPitch}; } } else { CESIUM_ASSERT(pTexture->numLevels == 1); @@ -390,13 +392,16 @@ std::optional ImageDecoder::generateMipMaps(ImageAsset& image) { totalPixelCount += mipWidth * mipHeight; } + const size_t imageRowPitch = + static_cast(image.width * image.channels * image.bytesPerChannel); // Byte size of the base image. - const size_t imageByteSize = static_cast( - image.width * image.height * image.channels * image.bytesPerChannel); + const size_t imageByteSize = + imageRowPitch * static_cast(image.height); image.mipPositions.resize(mipCount); image.mipPositions[0].byteOffset = 0; image.mipPositions[0].byteSize = imageByteSize; + image.mipPositions[0].rowPitch = imageRowPitch; image.pixelData.resize(static_cast( totalPixelCount * image.channels * image.bytesPerChannel)); @@ -421,11 +426,13 @@ std::optional ImageDecoder::generateMipMaps(ImageAsset& image) { mipHeight >>= 1; } - byteSize = static_cast( - mipWidth * mipHeight * image.channels * image.bytesPerChannel); + size_t rowPitch = + static_cast(mipWidth * image.channels * image.bytesPerChannel); + byteSize = rowPitch * static_cast(mipHeight); image.mipPositions[mipIndex].byteOffset = byteOffset; image.mipPositions[mipIndex].byteSize = byteSize; + image.mipPositions[mipIndex].rowPitch = rowPitch; if (!ImageDecoder::unsafeResize( &image.pixelData[lastByteOffset], diff --git a/CesiumRasterOverlays/src/GeoJsonDocumentRasterOverlay.cpp b/CesiumRasterOverlays/src/GeoJsonDocumentRasterOverlay.cpp index 9f35a2441..37e6a3a7b 100644 --- a/CesiumRasterOverlays/src/GeoJsonDocumentRasterOverlay.cpp +++ b/CesiumRasterOverlays/src/GeoJsonDocumentRasterOverlay.cpp @@ -601,11 +601,13 @@ class CESIUMRASTEROVERLAYS_API GeoJsonDocumentRasterOverlayTileProvider final for (uint32_t i = 0; i < mipLevels; i++) { const int32_t width = std::max(textureSize.x >> i, 1); const int32_t height = std::max(textureSize.y >> i, 1); + const int32_t rowPitch = width * result.pImage->channels * + result.pImage->bytesPerChannel; result.pImage->mipPositions.emplace_back( CesiumGltf::ImageAssetMipPosition{ totalSize, - (size_t)(width * height * result.pImage->channels * - result.pImage->bytesPerChannel)}); + size_t(rowPitch * height), + size_t(rowPitch)}); totalSize += result.pImage->mipPositions[i].byteSize; } result.pImage->pixelData.resize(totalSize, std::byte{0}); diff --git a/CesiumVectorData/test/TestVectorRasterizer.cpp b/CesiumVectorData/test/TestVectorRasterizer.cpp index 0c84b40cd..c1b26a521 100644 --- a/CesiumVectorData/test/TestVectorRasterizer.cpp +++ b/CesiumVectorData/test/TestVectorRasterizer.cpp @@ -250,7 +250,10 @@ TEST_CASE("VectorRasterizer::rasterize") { for (size_t i = 0; i < 4; i++) { int32_t width = 256 >> i; int32_t height = 256 >> i; - asset->mipPositions[i] = {totalSize, (size_t)(width * height * 4)}; + asset->mipPositions[i] = { + totalSize, + size_t(width * height * 4), + size_t(width * 4)}; totalSize += asset->mipPositions[i].byteSize; }