From e5f5d7ed111dcb462fa8c16540d3fb5fb983c659 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 21 Apr 2016 13:21:39 +0200 Subject: [PATCH] Utility/PixelFormat: Add ComputeSize method Former-commit-id: 8d9017541a812c98ba96c694cbd10da895338d1d --- include/Nazara/Utility/Image.hpp | 2 +- include/Nazara/Utility/PixelFormat.hpp | 2 ++ include/Nazara/Utility/PixelFormat.inl | 20 ++++++++++++++++ src/Nazara/Utility/Image.cpp | 32 +++++++++++++++++--------- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/include/Nazara/Utility/Image.hpp b/include/Nazara/Utility/Image.hpp index cefc606af..65c03d6bd 100644 --- a/include/Nazara/Utility/Image.hpp +++ b/include/Nazara/Utility/Image.hpp @@ -131,7 +131,7 @@ namespace Nz Image& operator=(const Image& image); - static void Copy(UInt8* destination, const UInt8* source, UInt8 bpp, unsigned int width, unsigned int height, unsigned int depth = 1, unsigned int dstWidth = 0, unsigned int dstHeight = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0); + static void Copy(UInt8* destination, const UInt8* source, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth = 1, unsigned int dstWidth = 0, unsigned int dstHeight = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0); static UInt8 GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth = 1); static UInt8 GetMaxLevel(ImageType type, unsigned int width, unsigned int height, unsigned int depth = 1); template static ImageRef New(Args&&... args); diff --git a/include/Nazara/Utility/PixelFormat.hpp b/include/Nazara/Utility/PixelFormat.hpp index 78d90da37..72197d7c6 100644 --- a/include/Nazara/Utility/PixelFormat.hpp +++ b/include/Nazara/Utility/PixelFormat.hpp @@ -28,6 +28,8 @@ namespace Nz using ConvertFunction = std::function; using FlipFunction = std::function; + static inline std::size_t ComputeSize(PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth); + static bool Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* src, void* dst); static bool Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* start, const void* end, void* dst); diff --git a/include/Nazara/Utility/PixelFormat.inl b/include/Nazara/Utility/PixelFormat.inl index 8a00588e0..2d09273b9 100644 --- a/include/Nazara/Utility/PixelFormat.inl +++ b/include/Nazara/Utility/PixelFormat.inl @@ -9,6 +9,26 @@ namespace Nz { + inline std::size_t PixelFormat::ComputeSize(PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth) + { + if (IsCompressed(format)) + { + switch (format) + { + case PixelFormatType_DXT1: + case PixelFormatType_DXT3: + case PixelFormatType_DXT5: + return (((width + 3) / 4) * ((height + 3) / 4) * (format == PixelFormatType_DXT1) ? 8 : 16) * depth; + + default: + NazaraError("Unsupported format"); + return 0; + } + } + else + return width * height * depth * GetBytesPerPixel(format); + } + inline bool PixelFormat::Convert(PixelFormatType srcFormat, PixelFormatType dstFormat, const void* src, void* dst) { if (srcFormat == dstFormat) diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 0965ed06e..6d05b493c 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -179,7 +179,7 @@ namespace Nz UInt8 bpp = PixelFormat::GetBytesPerPixel(m_sharedImage->format); UInt8* dstPtr = GetPixelPtr(m_sharedImage->levels[0].get(), bpp, dstPos.x, dstPos.y, dstPos.z, m_sharedImage->width, m_sharedImage->height); - Copy(dstPtr, srcPtr, bpp, srcBox.width, srcBox.height, srcBox.depth, m_sharedImage->width, m_sharedImage->height, source.GetWidth(), source.GetHeight()); + Copy(dstPtr, srcPtr, m_sharedImage->format, srcBox.width, srcBox.height, srcBox.depth, m_sharedImage->width, m_sharedImage->height, source.GetWidth(), source.GetHeight()); } bool Image::Create(ImageType type, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, UInt8 levelCount) @@ -273,7 +273,7 @@ namespace Nz // Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs try { - levels[i].reset(new UInt8[w * h * d * PixelFormat::GetBytesPerPixel(format)]); + levels[i].reset(new UInt8[PixelFormat::ComputeSize(format, w, h, d)]); if (w > 1) w >>= 1; @@ -341,7 +341,7 @@ namespace Nz for (unsigned int i = 0; i < levels.size(); ++i) { - unsigned int size = width*height*depth*bpp; + std::size_t size = PixelFormat::ComputeSize(m_sharedImage->format, width, height, depth); levels[i].reset(new UInt8[size]); UInt8* ptr = levels[i].get(); @@ -380,6 +380,12 @@ namespace Nz return false; } + if (PixelFormat::IsCompressed(m_sharedImage->format)) + { + NazaraError("Cannot access pixels from compressed image"); + return false; + } + if (!box.IsValid()) { NazaraError("Invalid rectangle"); @@ -439,6 +445,12 @@ namespace Nz return false; } + if (PixelFormat::IsCompressed(m_sharedImage->format)) + { + NazaraError("Cannot access pixels from compressed image"); + return false; + } + if (!rect.IsValid()) { NazaraError("Invalid rectangle"); @@ -683,10 +695,7 @@ namespace Nz unsigned int Image::GetMemoryUsage(UInt8 level) const { - return (GetLevelSize(m_sharedImage->width, level)) * - (GetLevelSize(m_sharedImage->height, level)) * - ((m_sharedImage->type == ImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level)) * - PixelFormat::GetBytesPerPixel(m_sharedImage->format); + return PixelFormat::ComputeSize(m_sharedImage->format, GetLevelSize(m_sharedImage->width, level), GetLevelSize(m_sharedImage->height, level), ((m_sharedImage->type == ImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level))); } Color Image::GetPixelColor(unsigned int x, unsigned int y, unsigned int z) const @@ -1261,7 +1270,7 @@ namespace Nz EnsureOwnership(); - Copy(m_sharedImage->levels[level].get(), pixels, PixelFormat::GetBytesPerPixel(m_sharedImage->format), + Copy(m_sharedImage->levels[level].get(), pixels, m_sharedImage->format, GetLevelSize(m_sharedImage->width, level), GetLevelSize(m_sharedImage->height, level), GetLevelSize(m_sharedImage->depth, level), @@ -1317,7 +1326,7 @@ namespace Nz UInt8 bpp = PixelFormat::GetBytesPerPixel(m_sharedImage->format); UInt8* dstPixels = GetPixelPtr(m_sharedImage->levels[level].get(), bpp, box.x, box.y, box.z, width, height); - Copy(dstPixels, pixels, bpp, + Copy(dstPixels, pixels, m_sharedImage->format, box.width, box.height, box.depth, width, height, srcWidth, srcHeight); @@ -1341,7 +1350,7 @@ namespace Nz return *this; } - void Image::Copy(UInt8* destination, const UInt8* source, UInt8 bpp, unsigned int width, unsigned int height, unsigned int depth, unsigned int dstWidth, unsigned int dstHeight, unsigned int srcWidth, unsigned int srcHeight) + void Image::Copy(UInt8* destination, const UInt8* source, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, unsigned int dstWidth, unsigned int dstHeight, unsigned int srcWidth, unsigned int srcHeight) { if (dstWidth == 0) dstWidth = width; @@ -1356,9 +1365,10 @@ namespace Nz srcHeight = height; if ((height == 1 || (dstWidth == width && srcWidth == width)) && (depth == 1 || (dstHeight == height && srcHeight == height))) - std::memcpy(destination, source, width*height*depth*bpp); + std::memcpy(destination, source, PixelFormat::ComputeSize(format, width, height, depth)); else { + unsigned int bpp = PixelFormat::GetBytesPerPixel(format); unsigned int lineStride = width * bpp; unsigned int dstLineStride = dstWidth * bpp; unsigned int dstFaceStride = dstLineStride * dstHeight;