Added NzImage::Get/SetPixel(Face)

NzImage::Update(const nzUInt8* pixels, const NzRectui& rect) now takes a
third argument to specify the layer of the 3D image (if a 3D image),
default to 0
Optimized NzPixelFormat conversion from RGBA4
Added NzColor
This commit is contained in:
Lynix
2012-05-27 11:57:34 +02:00
parent 7659fdf460
commit 96ea5fdaa7
6 changed files with 711 additions and 14 deletions

View File

@@ -237,6 +237,100 @@ unsigned int NzImage::GetHeight() const
return m_sharedImage->height;
}
NzColor NzImage::GetPixel(unsigned int x, unsigned int y, unsigned int z) const
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
{
NazaraError("Image must be valid");
return NzColor();
}
if (m_sharedImage->type == nzImageType_Cubemap)
{
NazaraError("GetPixel is not designed for cubemaps, use GetPixelFace instead");
return NzColor();
}
if (NzPixelFormat::IsCompressed(m_sharedImage->format))
{
NazaraError("Cannot access pixels from compressed image");
return NzColor();
}
if (x >= m_sharedImage->width)
{
NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(m_sharedImage->width) + ')');
return NzColor();
}
if (y >= m_sharedImage->height)
{
NazaraError("Y value exceeds width (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')');
return NzColor();
}
if (z >= m_sharedImage->depth)
{
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(m_sharedImage->depth) + ')');
return NzColor();
}
#endif
NzColor color;
const nzUInt8* pixel = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*z+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
if (!NzPixelFormat::Convert(m_sharedImage->format, nzPixelFormat_RGBA8, pixel, &color.r))
NazaraError("Failed to convert image's format to RGBA8");
return color;
}
NzColor NzImage::GetPixelFace(nzCubemapFace face, unsigned int x, unsigned int y) const
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
{
NazaraError("Image must be valid");
return NzColor();
}
if (m_sharedImage->type != nzImageType_Cubemap)
{
NazaraError("GetPixelFace is designed for cubemaps, use GetPixel instead");
return NzColor();
}
if (NzPixelFormat::IsCompressed(m_sharedImage->format))
{
NazaraError("Cannot access pixels from compressed image");
return NzColor();
}
if (x >= m_sharedImage->width)
{
NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(m_sharedImage->width) + ')');
return NzColor();
}
if (y >= m_sharedImage->height)
{
NazaraError("Y value exceeds width (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')');
return NzColor();
}
#endif
NzColor color;
const nzUInt8* pixel = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX)+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
if (!NzPixelFormat::Convert(m_sharedImage->format, nzPixelFormat_RGBA8, pixel, &color.r))
NazaraError("Failed to convert image's format to RGBA8");
return color;
}
nzUInt8* NzImage::GetPixels()
{
EnsureOwnership();
@@ -246,7 +340,7 @@ nzUInt8* NzImage::GetPixels()
unsigned int NzImage::GetSize() const
{
return m_sharedImage->width * m_sharedImage->height * m_sharedImage->depth * NzPixelFormat::GetBPP(m_sharedImage->format);
return m_sharedImage->width * m_sharedImage->height * ((m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth) * NzPixelFormat::GetBPP(m_sharedImage->format);
}
nzImageType NzImage::GetType() const
@@ -289,6 +383,102 @@ bool NzImage::LoadFromStream(NzInputStream& stream, const NzImageParams& params)
return NzResourceLoader<NzImage, NzImageParams>::LoadResourceFromStream(this, stream, params);
}
bool NzImage::SetPixel(const NzColor& color, unsigned int x, unsigned int y, unsigned int z)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
{
NazaraError("Image must be valid");
return false;
}
if (m_sharedImage->type == nzImageType_Cubemap)
{
NazaraError("SetPixel is not designed for cubemaps, use SetPixelFace instead");
return false;
}
if (NzPixelFormat::IsCompressed(m_sharedImage->format))
{
NazaraError("Cannot access pixels from compressed image");
return false;
}
if (x >= m_sharedImage->width)
{
NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(m_sharedImage->width) + ')');
return false;
}
if (y >= m_sharedImage->height)
{
NazaraError("Y value exceeds width (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')');
return false;
}
if (z >= m_sharedImage->depth)
{
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(m_sharedImage->depth) + ')');
return false;
}
#endif
nzUInt8* pixel = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*z+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, pixel))
{
NazaraError("Failed to convert RGBA8 to image's format");
return false;
}
return true;
}
bool NzImage::SetPixelFace(const NzColor& color, nzCubemapFace face, unsigned int x, unsigned int y)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
{
NazaraError("Image must be valid");
return false;
}
if (m_sharedImage->type != nzImageType_Cubemap)
{
NazaraError("SetPixelFace is designed for cubemaps, use SetPixel instead");
return false;
}
if (NzPixelFormat::IsCompressed(m_sharedImage->format))
{
NazaraError("Cannot access pixels from compressed image");
return false;
}
if (x >= m_sharedImage->width)
{
NazaraError("X value exceeds width (" + NzString::Number(x) + " >= (" + NzString::Number(m_sharedImage->width) + ')');
return false;
}
if (y >= m_sharedImage->height)
{
NazaraError("Y value exceeds width (" + NzString::Number(y) + " >= (" + NzString::Number(m_sharedImage->height) + ')');
return false;
}
#endif
nzUInt8* pixel = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX)+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, pixel))
{
NazaraError("Failed to convert RGBA8 to image's format");
return false;
}
return true;
}
bool NzImage::Update(const nzUInt8* pixels)
{
#if NAZARA_UTILITY_SAFE
@@ -318,7 +508,7 @@ bool NzImage::Update(const nzUInt8* pixels)
return true;
}
bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect)
bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
@@ -345,18 +535,24 @@ bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect)
return false;
}
if (rect.width > m_sharedImage->width || rect.height > m_sharedImage->height)
if (rect.x+rect.width > m_sharedImage->width || rect.y+rect.height > m_sharedImage->height)
{
NazaraError("Rectangle dimensions are out of bounds");
return false;
}
if (z >= m_sharedImage->depth)
{
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(m_sharedImage->depth) + ')');
return false;
}
#endif
EnsureOwnership();
nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format);
nzUInt8* dstPixels = m_sharedImage->pixels + (rect.x + rect.y * m_sharedImage->width) * bpp;
nzUInt8* dstPixels = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*z + rect.y) + rect.x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
unsigned int srcStride = rect.width * bpp;
unsigned int dstStride = m_sharedImage->width * bpp;
@@ -382,7 +578,7 @@ bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels)
if (m_sharedImage->type != nzImageType_Cubemap)
{
NazaraError("Update is only designed for cubemaps, use Update instead");
NazaraError("Update is designed for cubemaps, use Update instead");
return false;
}
@@ -412,7 +608,7 @@ bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRect
if (m_sharedImage->type != nzImageType_Cubemap)
{
NazaraError("Update is only designed for cubemaps, use Update instead");
NazaraError("Update is designed for cubemaps, use Update instead");
return false;
}
@@ -428,7 +624,7 @@ bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRect
return false;
}
if (rect.width > m_sharedImage->width || rect.height > m_sharedImage->height)
if (rect.x+rect.width > m_sharedImage->width || rect.y+rect.height > m_sharedImage->height)
{
NazaraError("Rectangle dimensions are out of bounds");
return false;
@@ -439,7 +635,7 @@ bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRect
nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format);
nzUInt8* dstPixels = m_sharedImage->pixels + (rect.x + rect.y * m_sharedImage->width + (face-nzCubemapFace_PositiveX)*m_sharedImage->width*m_sharedImage->height) * bpp;
nzUInt8* dstPixels = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX) + rect.y) + rect.x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
unsigned int srcStride = rect.width * bpp;
unsigned int dstStride = m_sharedImage->width * bpp;

View File

@@ -14,7 +14,7 @@ namespace
{
inline nzUInt8 c4to8(nzUInt8 c)
{
return c * (255.f/15.f);
return c * (255/15);
}
inline nzUInt8 c5to8(nzUInt8 c)
@@ -327,7 +327,7 @@ namespace
*ptr++ = (l << 11) |
(l << 6) |
(l << 1) |
1;
1;
start += 1;
}
@@ -480,9 +480,9 @@ namespace
{
while (start < end)
{
*dst++ = (c4to8((start[1] & 0xF0) >> 4));
*dst++ = (c4to8((start[0] & 0x0F) >> 0));
*dst++ = (c4to8((start[0] & 0xF0) >> 4));
*dst++ = c4to8((start[1] & 0xF0) >> 4);
*dst++ = c4to8((start[0] & 0x0F) >> 0);
*dst++ = c4to8((start[0] & 0xF0) >> 4);
start += 2;
}