diff options
Diffstat (limited to 'dep/src/g3dlite/GImage.cpp')
-rw-r--r-- | dep/src/g3dlite/GImage.cpp | 1166 |
1 files changed, 0 insertions, 1166 deletions
diff --git a/dep/src/g3dlite/GImage.cpp b/dep/src/g3dlite/GImage.cpp deleted file mode 100644 index 9527e96cf67..00000000000 --- a/dep/src/g3dlite/GImage.cpp +++ /dev/null @@ -1,1166 +0,0 @@ -/** - \file GImage.cpp - \author Morgan McGuire, http://graphics.cs.williams.edu - Copyright 2002-2010, Morgan McGuire - - \created 2002-05-27 - \edited 2010-01-04 - */ -#include "G3D/platform.h" -#include "G3D/GImage.h" -#include "G3D/debug.h" -#include "G3D/stringutils.h" -#include "G3D/TextInput.h" -#include "G3D/TextOutput.h" -#include "G3D/BinaryInput.h" -#include "G3D/BinaryOutput.h" -#include "G3D/Log.h" -#include "G3D/fileutils.h" - -#ifdef G3D_LINUX -# include <png.h> -#else -# include "png.h" -#endif - -#include <sys/stat.h> -#include <assert.h> -#include <sys/types.h> - -////////////////////////////////////////////////////////////////////////////////////////////// - -namespace G3D { - -void GImage::LtoRGBA( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int v = in[i]; - int i4 = i * 4; - - out[i4 + 0] = v; - out[i4 + 1] = v; - out[i4 + 2] = v; - out[i4 + 3] = 255; - } -} - - -void GImage::LtoRGB( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int v = in[i]; - int i3 = i * 3; - - out[i3 + 0] = v; - out[i3 + 1] = v; - out[i3 + 2] = v; - } -} - - -void GImage::RGBtoRGBA( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int i3 = i * 3; - int i4 = i3 + i; - - out[i4 + 0] = in[i3 + 0]; - out[i4 + 1] = in[i3 + 1]; - out[i4 + 2] = in[i3 + 2]; - out[i4 + 3] = 255; - } -} - - -void GImage::RGBAtoRGB( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int i3 = i * 3; - int i4 = i3 + i; - - out[i3 + 0] = in[i4 + 0]; - out[i3 + 1] = in[i4 + 1]; - out[i3 + 2] = in[i4 + 2]; - } -} - - -void GImage::RGBtoBGRA( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int i3 = i * 3; - int i4 = i3 + i; - - out[i4 + 2] = in[i3 + 0]; - out[i4 + 1] = in[i3 + 1]; - out[i4 + 0] = in[i3 + 2]; - out[i4 + 3] = 255; - } -} - - - -void GImage::RGBtoBGR( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int i3 = i * 3; - - int r = in[i3 + 0]; - int g = in[i3 + 1]; - int b = in[i3 + 2]; - - out[i3 + 2] = r; - out[i3 + 1] = g; - out[i3 + 0] = b; - } -} - - -void GImage::RGBxRGBtoRGBA( - const uint8* colorRGB, - const uint8* alphaRGB, - uint8* out, - int numPixels) { - - for (int i = numPixels - 1; i >= 0; --i) { - int i3 = i * 3; - int i4 = i3 + i; - - out[i4 + 0] = colorRGB[i3 + 0]; - out[i4 + 1] = colorRGB[i3 + 1]; - out[i4 + 2] = colorRGB[i3 + 2]; - out[i4 + 3] = alphaRGB[i3 + 0]; - } -} - - -void GImage::RGBtoARGB( - const uint8* in, - uint8* out, - int numPixels) { - - for (int i = 0; i < numPixels; ++i) { - int i3 = i * 3; - int i4 = i3 + i; - - out[i4 + 0] = 255; - out[i4 + 1] = in[i3 + 0]; - out[i4 + 2] = in[i3 + 1]; - out[i4 + 3] = in[i3 + 2]; - } -} - - -void GImage::flipRGBVertical( - const uint8* in, - uint8* out, - int width, - int height) { - - - // Allocate a temp row so the operation - // is still safe if in == out - uint8* temp = (uint8*)System::malloc(width * 3); - alwaysAssertM(temp != NULL, "Out of memory"); - - int oneRow = width * 3; - int N = height / 2; - - // if height is an odd value, don't swap odd middle row - for (int i = 0; i < N; ++i) { - int topOff = i * oneRow; - int botOff = (height - i - 1) * oneRow; - System::memcpy(temp, in + topOff, oneRow); - System::memcpy(out + topOff, in + botOff, oneRow); - System::memcpy(out + botOff, temp, oneRow); - } - - System::free(temp); -} - - -void GImage::flipRGBAVertical( - const uint8* in, - uint8* out, - int width, - int height) { - - - // Allocate a temp row so the operation - // is still safe if in == out - uint8* temp = (uint8*)System::malloc(width * 4); - alwaysAssertM(temp != NULL, "Out of memory"); - - int oneRow = width * 4; - - // if height is an odd value, don't swap odd middle row - for (int i = 0; i < height / 2; ++i) { - int topOff = i * oneRow; - int botOff = (height - i - 1) * oneRow; - System::memcpy(temp, in + topOff, oneRow); - System::memcpy(out + topOff, in + botOff, oneRow); - System::memcpy(out + botOff, temp, oneRow); - } - - System::free(temp); -} - -//////////////////////////////////////////////////////////////////////////////////////// - -void GImage::decode( - BinaryInput& input, - Format format) { - - switch (format) { - case PPM_ASCII: - decodePPMASCII(input); - break; - - case PPM_BINARY: - decodePPM(input); - break; - - case PNG: - decodePNG(input); - break; - - case JPEG: - decodeJPEG(input); - break; - - case TGA: - decodeTGA(input); - break; - - case BMP: - decodeBMP(input); - break; - - case ICO: - decodeICO(input); - break; - - case PCX: - decodePCX(input); - break; - - default: - debugAssert(false); - } - - debugAssert(m_width >= 0); - debugAssert(m_height >= 0); - debugAssert(m_channels == 1 || m_channels == 3 || m_channels == 4); - debugAssert(m_byte != NULL); -} - - -void GImage::decodePCX( - BinaryInput& input) { - - uint8 manufacturer = input.readUInt8(); - uint8 version = input.readUInt8(); - uint8 encoding = input.readUInt8(); - uint8 bitsPerPixel = input.readUInt8(); - - uint16 xmin = input.readUInt16(); - uint16 ymin = input.readUInt16(); - uint16 xmax = input.readUInt16(); - uint16 ymax = input.readUInt16(); - - uint16 horizDPI = input.readUInt16(); - uint16 vertDPI = input.readUInt16(); - - Color3uint8 colorMap[16]; - input.readBytes(colorMap, 48); - - input.skip(1); - - uint8 planes = input.readUInt8(); - uint16 bytesPerLine = input.readUInt16(); - uint16 paletteType = input.readUInt16(); - input.skip(4 + 54); - - (void)bytesPerLine; - - m_width = xmax - xmin + 1; - m_height = ymax - ymin + 1; - m_channels = 3; - - if ((manufacturer != 0x0A) || (encoding != 0x01)) { - throw GImage::Error("PCX file is corrupted", input.getFilename()); - } - - (void)version; - (void)vertDPI; - (void)horizDPI; - - if ((bitsPerPixel != 8) || ((planes != 1) && (planes != 3))) { - throw GImage::Error("Only 8-bit paletted and 24-bit PCX files supported.", input.getFilename()); - } - - // Prepare the pointer object for the pixel data - m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3); - - if ((paletteType == 1) && (planes == 3)) { - - Color3uint8* pixel = pixel3(); - - // Iterate over each scan line - for (int row = 0; row < m_height; ++row) { - // Read each scan line once per plane - for (int plane = 0; plane < planes; ++plane) { - int p = row * m_width; - int p1 = p + m_width; - while (p < p1) { - uint8 value = input.readUInt8(); - int length = 1; - - if (value >= 192) { - // This is the length, not the value. Mask off - // the two high bits and read the true index. - length = value & 0x3F; - value = input.readUInt8(); - } - - // Set the whole run - for (int i = length - 1; i >= 0; --i, ++p) { - debugAssert(p < m_width * m_height); - pixel[p][plane] = value; - } - } - } - } - - } else if (planes == 1) { - - Color3uint8 palette[256]; - - int imageBeginning = input.getPosition(); - int paletteBeginning = input.getLength() - 769; - - input.setPosition(paletteBeginning); - - uint8 dummy = input.readUInt8(); - - if (dummy != 12) { - Log::common()->println("\n*********************"); - Log::common()->printf("Warning: Corrupted PCX file (palette marker byte was missing) \"%s\"\nLoading anyway\n\n", input.getFilename().c_str()); - } - - input.readBytes(palette, sizeof(palette)); - input.setPosition(imageBeginning); - - Color3uint8* pixel = pixel3(); - - // The palette indices are run length encoded. - int p = 0; - while (p < m_width * m_height) { - uint8 index = input.readUInt8(); - uint8 length = 1; - - if (index >= 192) { - // This is the length, not the index. Mask off - // the two high bits and read the true index. - length = index & 0x3F; - index = input.readUInt8(); - } - - Color3uint8 color = palette[index]; - - // Set the whole run - for (int i = length - 1; i >= 0; --i, ++p) { - if (p > m_width * m_height) { - break; - } - pixel[p] = color; - } - - } - - } else { - throw GImage::Error("Unsupported PCX file type.", input.getFilename()); - } -} - - -GImage::Format GImage::resolveFormat(const std::string& filename) { - BinaryInput b(filename, G3D_LITTLE_ENDIAN); - if (b.size() <= 0) { - throw Error("File not found.", filename); - } - - return resolveFormat(filename, b.getCArray(), b.size(), AUTODETECT); -} - - -GImage::Format GImage::resolveFormat( - const std::string& filename, - const uint8* data, - int dataLen, - Format maybeFormat) { - - // Return the provided format if it is specified. - if (maybeFormat != AUTODETECT) { - return maybeFormat; - } - - std::string extension = toUpper(filenameExt(filename)); - - if ((extension == "PPM") || (extension == "PGM") || (extension == "PBM")) { - // There are two PPM formats (binary and ASCII); we handle them differently - if (dataLen > 3) { - if (!memcmp(data, "P6", 2) || !memcmp(data, "P5", 2)) { - return PPM_BINARY; - } else { - return PPM_ASCII; - } - } - } - - Format tmp = stringToFormat(extension); - if ((tmp != AUTODETECT) && (tmp != UNKNOWN)) { - return tmp; - } - - // Try and autodetect from the file itself by looking at the first - // character. - - // We can't look at the character if it is null. - debugAssert(data != NULL); - - if ((dataLen > 3) && (! memcmp(data, "P3", 2) || (! memcmp(data, "P2", 2)) || (! memcmp(data, "P1", 2)))) { - return PPM_ASCII; - } - - if ((dataLen > 3) && (!memcmp(data, "P6", 2) ||!memcmp(data, "P5", 2))) { - return PPM_BINARY; - } - - if (dataLen > 8) { - if (!png_sig_cmp((png_bytep)data, 0, 8)) { - return PNG; - } - } - - if ((dataLen > 0) && (data[0] == 'B')) { - return BMP; - } - - if (dataLen > 10) { - if ((dataLen > 11) && (data[0] == 0xFF) && - (memcmp(&data[6], "JFIF", 4) == 0)) { - return JPEG; - } - } - - if (dataLen > 40) { - if (memcmp(&data[dataLen - 18], "TRUEVISION-XFILE", 16) == 0) { - return TGA; - } - } - - if ((dataLen > 4) && (data[0] == 0) && (data[1] == 0) && (data[2] == 0) && (data[3] == 1)) { - return ICO; - } - - if ((dataLen > 0) && (data[0] == 10)) { - return PCX; - } - - return UNKNOWN; -} - - -GImage::GImage( - const std::string& filename, - Format format, - const MemoryManager::Ref& m) : - m_memMan(m), - m_byte(NULL), - m_channels(0), - m_width(0), - m_height(0) { - - load(filename, format); -} - - -void GImage::load( - const std::string& filename, - Format format) { - - clear(); - - try { - BinaryInput b(filename, G3D_LITTLE_ENDIAN); - if (b.size() <= 0) { - throw Error("File not found.", filename); - } - - alwaysAssertM(this != NULL, "Corrupt GImage"); - decode(b, resolveFormat(filename, b.getCArray(), b.size(), format)); - } catch (const std::string& error) { - throw Error(error, filename); - } -} - - -GImage::GImage( - const uint8* data, - int length, - Format format, - const MemoryManager::Ref& m) : - m_memMan(m), - m_byte(NULL), - m_channels(0), - m_width(0), - m_height(0) { - - BinaryInput b(data, length, G3D_LITTLE_ENDIAN); - // It is safe to cast away the const because we - // know we don't corrupt the data. - - decode(b, resolveFormat("", data, length, format)); -} - - -GImage::GImage( - int width, - int height, - int channels, - const MemoryManager::Ref& mem) : - m_memMan(mem), - m_byte(0), - m_channels(0), - m_width(0), - m_height(0) { - - resize(width, height, channels); -} - - -void GImage::resize( - int width, - int height, - int channels, - bool zero) { - - debugAssert(width >= 0); - debugAssert(height >= 0); - debugAssert(channels >= 1); - - clear(); - - m_width = width; - m_height = height; - m_channels = channels; - size_t sz = width * height * channels; - - if (sz > 0) { - m_byte = (uint8*)m_memMan->alloc(sz); - if (zero) { - System::memset(m_byte, 0, sz); - } - debugAssert(isValidHeapPointer(m_byte)); - } -} - - -void GImage::_copy( - const GImage& other) { - - clear(); - - m_width = other.m_width; - m_height = other.m_height; - m_channels = other.m_channels; - int s = m_width * m_height * m_channels * sizeof(uint8); - m_byte = (uint8*)m_memMan->alloc(s); - debugAssert(isValidHeapPointer(m_byte)); - memcpy(m_byte, other.m_byte, s); -} - - -void GImage::flipHorizontal() { - uint8 temp[4]; - int rowBytes = m_width * m_channels; - for (int y = 0; y < m_height; ++y) { - uint8* row = m_byte + y * rowBytes; - for (int x = 0; x < m_width / 2; ++x) { - System::memcpy(temp, row + x * m_channels, m_channels); - System::memcpy(row + x * m_channels, row + (m_width - x - 1) * m_channels, m_channels); - System::memcpy(row + (m_width - x - 1) * m_channels, temp, m_channels); - } - } -} - - -void GImage::flipVertical() { - uint8* old = m_byte; - m_byte = (uint8*)m_memMan->alloc(m_width * m_height * m_channels); - - // We could do this with only a single-row temp buffer, but then - // we'd have to copy twice as much data. - int rowBytes = m_width * m_channels; - for (int y = 0; y < m_height; ++y) { - System::memcpy(m_byte + y * rowBytes, old + (m_height - y - 1) * rowBytes, rowBytes); - } - - m_memMan->free(old); -} - - -void GImage::rotate90CW(int numTimes) { - - uint8* old = NULL; - numTimes = iWrap(numTimes, 4); - if (numTimes > 0) { - (uint8*)m_memMan->alloc(m_width * m_height * m_channels); - } - for (int j = 0; j < numTimes; ++j) { - { - uint8* temp = old; - uint8* old = m_byte; - m_byte = temp; - } - - { - int temp = m_width; - m_width = m_height; - m_height = temp; - } - - int rowBytes = m_width * m_channels; - for (int y = 0; y < m_height; ++y) { - for (int x = 0; x < m_width; ++x) { - uint8* dst = m_byte + x + y * rowBytes; - uint8* src = old + y + (m_height - x - 1) * rowBytes; - System::memcpy(dst, src, m_channels); - } - } - } - m_memMan->free(old); -} - - - -GImage::GImage( - const GImage& other, - const MemoryManager::Ref& m) : m_memMan(m), m_byte(NULL) { - - _copy(other); -} - - -GImage::~GImage() { - clear(); -} - - -void GImage::clear() { - m_width = 0; - m_height = 0; - m_memMan->free(m_byte); - m_byte = NULL; -} - - -GImage& GImage::operator=(const GImage& other) { - _copy(other); - return *this; -} - - -bool GImage::copySubImage( - GImage & dest, const GImage & src, - int srcX, int srcY, int srcWidth, int srcHeight) { - if ((src.m_width < srcX + srcWidth) || - (src.m_height < srcY + srcHeight) || - (srcY < 0) || - (srcX < 0)) { - - return false; - } - - dest.resize(srcWidth, srcHeight, src.m_channels); - - bool ret; - ret = pasteSubImage(dest, src, 0, 0, srcX, srcY, srcWidth, srcHeight); - debugAssert(ret); - - return true; -} - - -bool GImage::pasteSubImage( - GImage & dest, const GImage & src, - int destX, int destY, - int srcX, int srcY, int srcWidth, int srcHeight) { - - if ((src.m_width < srcX + srcWidth) || - (src.m_height < srcY + srcHeight) || - (dest.m_width < destX + srcWidth) || - (dest.m_height < destY + srcHeight) || - (srcY < 0) || - (srcX < 0) || - (destY < 0) || - (destX < 0) || - (src.channels() != dest.channels())) { - - return false; - } - - for (int i = 0; i < srcHeight; i++) { - const uint8* srcRow = src.byte() + - ((i + srcY) * src.m_width + srcX) * src.channels(); - uint8* destRow = dest.byte() + - ((i + destY) * dest.width() + destX) * dest.channels(); - memcpy(destRow, srcRow, srcWidth * src.m_channels); - } - - return true; -} - - -bool GImage::supportedFormat( - const std::string& format) { - - return (stringToFormat(format) != UNKNOWN); -} - - -GImage::Format GImage::stringToFormat( - const std::string& format) { - - std::string extension = toUpper(format); - - if ((extension == "JPG") || (extension == "JPEG")) { - return JPEG; - } else if (extension == "TGA") { - return TGA; - } else if (extension == "BMP") { - return BMP; - } else if (extension == "PCX") { - return PCX; - } else if (extension == "ICO") { - return ICO; - } else if (extension == "PNG") { - return PNG; - } else { - return UNKNOWN; - } - // Don't put PPM here, since it has two versions -} - - -void GImage::save( - const std::string& filename, - Format format) const { - - BinaryOutput b(filename, G3D_LITTLE_ENDIAN); - encode(resolveFormat(filename, NULL, 0, format), b); - b.commit(false); -} - - -void GImage::encode( - Format format, - uint8*& outData, - int& outLength) const { - - BinaryOutput out; - - encode(format, out); - - outData = (uint8*)System::malloc(out.size()); - debugAssert(outData); - outLength = out.size(); - - out.commit(outData); -} - - -void GImage::encode( - Format format, - BinaryOutput& out) const { - - switch (format) { - case PPM_ASCII: - encodePPMASCII(out); - break; - - case PPM_BINARY: - encodePPM(out); - break; - - case PNG: - encodePNG(out); - break; - - case JPEG: - encodeJPEG(out); - break; - - case BMP: - encodeBMP(out); - break; - - case TGA: - encodeTGA(out); - break; - - default: - debugAssert(false); - } -} - - -void GImage::insertRedAsAlpha(const GImage& alpha, GImage& output) const { - debugAssert(alpha.width() == width()); - debugAssert(alpha.height() == height()); - - // make sure output GImage is valid - if (output.width() != width() || output.height() != height() || output.channels() != 4) { - output.resize(width(), height(), 4); - } - - int N = m_width * m_height; - for (int i = 0; i < N; ++i) { - output.byte()[i * 4 + 0] = byte()[i * m_channels + 0]; - output.byte()[i * 4 + 1] = byte()[i * m_channels + 1]; - output.byte()[i * 4 + 2] = byte()[i * m_channels + 2]; - output.byte()[i * 4 + 3] = alpha.byte()[i * alpha.m_channels]; - } -} - - -void GImage::stripAlpha(GImage& output) const { - - if (output.m_width != m_width || output.m_height != m_height || output.m_channels != 3) { - output.resize(m_width, m_height, 3); - } - - int N = m_width * m_height; - for (int i = 0; i < N; ++i) { - output.byte()[i * 3 + 0] = byte()[i * m_channels + 0]; - output.byte()[i * 3 + 1] = byte()[i * m_channels + 1]; - output.byte()[i * 3 + 2] = byte()[i * m_channels + 2]; - } -} - - -int GImage::sizeInMemory() const { - return sizeof(GImage) + m_width * m_height * m_channels; -} - - -void GImage::computeNormalMap( - const GImage& bump, - GImage& normal, - const BumpMapPreprocess& preprocess) { - computeNormalMap(bump.m_width, bump.m_height, bump.m_channels, - bump.byte(), normal, preprocess); -} - -void GImage::computeNormalMap( - int width, - int height, - int channels, - const uint8* src, - GImage& normal, - const BumpMapPreprocess& preprocess) { - - float whiteHeightInPixels = preprocess.zExtentPixels; - bool lowPassBump = preprocess.lowPassFilter; - bool scaleHeightByNz = preprocess.scaleZByNz; - - if (whiteHeightInPixels < 0.0f) { - // Default setting scales so that a gradient ramp - // over the whole image becomes a 45-degree angle - - // Account for potentially non-square aspect ratios - whiteHeightInPixels = max(width, height) * -whiteHeightInPixels; - } - - debugAssert(whiteHeightInPixels >= 0); - - const int w = width; - const int h = height; - const int stride = channels; - - normal.resize(w, h, 4); - - const uint8* const B = src; - Color4uint8* const N = normal.pixel4(); - - // 1/s for the scale factor that each ELEVATION should be multiplied by. - // We avoid actually multiplying by this and instead just divide it out of z. - float elevationInvScale = 255.0f / whiteHeightInPixels; - - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; ++x) { - // Index into normal map pixel - int i = x + y * w; - - // Index into bump map *byte* - int j = stride * i; - - Vector3 delta; - - // Get a value from B (with wrapping lookup) relative to (x, y) - // and divide by 255 - #define ELEVATION(DX, DY) ((int)B[(((DX + x + w) % w) + \ - ((DY + y + h) % h) * w) * stride]) - - - // Sobel filter to compute the normal. - // - // Y Filter (X filter is the transpose) - // [ -1 -2 -1 ] - // [ 0 0 0 ] - // [ 1 2 1 ] - - // Write the Y value directly into the x-component so we don't have - // to explicitly compute a cross product at the end. Does not - // go out of bounds because the above is computed mod (width, height) - delta.y = -( ELEVATION(-1, -1) * 1 + ELEVATION( 0, -1) * 2 + ELEVATION( 1, -1) * 1 + - -ELEVATION(-1, 1) * 1 + -ELEVATION( 0, 1) * 2 + -ELEVATION( 1, 1) * 1); - - delta.x = -(-ELEVATION(-1, -1) * 1 + ELEVATION( 1, -1) * 1 + - -ELEVATION(-1, 0) * 2 + ELEVATION( 1, 0) * 2 + - -ELEVATION(-1, 1) * 1 + ELEVATION( 1, 1) * 1); - - // The scale of each filter row is 4, the filter width is two pixels, - // and the "normal" range is 0-255. - delta.z = 4 * 2 * elevationInvScale; - - // Delta is now scaled in pixels; normalize - delta = delta.direction(); - - // Copy over the bump value into the alpha channel. - float H = B[j] / 255.0f; - - if (lowPassBump) { - H = (ELEVATION(-1, -1) + ELEVATION( 0, -1) + ELEVATION(1, -1) + - ELEVATION(-1, 0) + ELEVATION( 0, 0) + ELEVATION(1, 0) + - ELEVATION(-1, 1) + ELEVATION( 0, 1) + ELEVATION(1, 1)) / (255.0f * 9.0f); - } -# undef ELEVATION - - if (scaleHeightByNz) { - // delta.z can't possibly be negative, so we avoid actually - // computing the absolute value. - H *= delta.z; - } - - N[i].a = iRound(H * 255.0f); - - // Pack into byte range - delta = delta * 127.5f + Vector3(127.5f, 127.5f, 127.5f); - N[i].r = iClamp(iRound(delta.x), 0, 255); - N[i].g = iClamp(iRound(delta.y), 0, 255); - N[i].b = iClamp(iRound(delta.z), 0, 255); - } - } -} - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -void GImage::convertToL8() { - switch (m_channels) { - case 1: - return; - - case 3: - { - // Average - Color3uint8* src = (Color3uint8*)m_byte; - m_byte = NULL; - resize(m_width, m_height, 1); - for (int i = m_width * m_height - 1; i >= 0; --i) { - const Color3uint8 s = src[i]; - uint8& d = m_byte[i]; - d = ((int)s.r + (int)s.g + (int)s.b) / 3; - } - m_memMan->free(src); - } - break; - - case 4: - { - // Average - Color4uint8* src = (Color4uint8*)m_byte; - m_byte = NULL; - resize(m_width, m_height, 1); - for (int i = m_width * m_height - 1; i >= 0; --i) { - const Color4uint8 s = src[i]; - uint8& d = m_byte[i]; - d = ((int)s.r + (int)s.g + (int)s.b) / 3; - } - m_memMan->free(src); - } - return; - - default: - alwaysAssertM(false, "Bad number of channels in input image"); - } -} - - -void GImage::convertToRGBA() { - switch (m_channels) { - case 1: - { - // Spread - uint8* old = m_byte; - m_byte = NULL; - resize(m_width, m_height, 4); - for (int i = m_width * m_height - 1; i >= 0; --i) { - const uint8 s = old[i]; - Color4uint8& d = ((Color4uint8*)m_byte)[i]; - d.r = d.g = d.b = s; - d.a = 255; - } - m_memMan->free(m_byte); - } - break; - - case 3: - { - // Add alpha - Color3uint8* old = (Color3uint8*)m_byte; - m_byte = NULL; - resize(m_width, m_height, 4); - for (int i = m_width * m_height - 1; i >= 0; --i) { - const Color3uint8 s = old[i]; - Color4uint8& d = ((Color4uint8*)m_byte)[i]; - d.r = s.r; - d.g = s.g; - d.b = s.b; - d.a = 255; - } - m_memMan->free(old); - } - break; - - case 4: - // Already RGBA - return; - - default: - alwaysAssertM(false, "Bad number of channels in input image"); - } -} - - -void GImage::convertToRGB() { - switch (m_channels) { - case 1: - { - // Spread - uint8* old = m_byte; - m_byte = NULL; - resize(m_width, m_height, 3); - for (int i = m_width * m_height - 1; i >= 0; --i) { - const uint8 s = old[i]; - Color3uint8& d = ((Color3uint8*)m_byte)[i]; - d.r = d.g = d.b = s; - } - m_memMan->free(old); - } - break; - - case 3: - return; - - case 4: - // Strip alpha - { - Color4uint8* old = (Color4uint8*)m_byte; - m_byte = NULL; - resize(m_width, m_height, 3); - for (int i = m_width * m_height - 1; i >= 0; --i) { - const Color4uint8 s = old[i]; - Color3uint8& d = ((Color3uint8*)m_byte)[i]; - d.r = s.r; - d.g = s.g; - d.b = s.b; - } - m_memMan->free(old); - } - break; - - default: - alwaysAssertM(false, "Bad number of channels in input image"); - } -} - - -void GImage::R8G8B8_to_Y8U8V8(int width, int height, const uint8* _in, uint8* _out) { - const Color3uint8* in = reinterpret_cast<const Color3uint8*>(_in); - Color3uint8* out = reinterpret_cast<Color3uint8*>(_out); - - Color3uint8 p; - for (int i = width * height - 1; i >= 0; --i) { - p.r = iClamp(iRound(in->r * 0.229 + in->g * 0.587 + in->b * 0.114), 0, 255); - p.g = iClamp(iRound(in->r * -0.147 + in->g * -0.289 + in->b * 0.436) + 127, 0, 255); - p.b = iClamp(iRound(in->r * 0.615 + in->g * -0.515 + in->b * -0.100) + 127, 0, 255); - *out = p; - ++in; - ++out; - } -} - - - -void GImage::Y8U8V8_to_R8G8B8(int width, int height, const uint8* _in, uint8* _out) { - const Color3uint8* in = reinterpret_cast<const Color3uint8*>(_in); - Color3uint8* out = reinterpret_cast<Color3uint8*>(_out); - - Color3uint8 p; - for (int i = width * height - 1; i >= 0; --i) { - p.r = iClamp(iRound(in->r * 1.0753 + (in->b - 127) * 1.2256), 0, 255); - p.g = iClamp(iRound(in->r * 1.0753 + (in->g - 127) * -0.3946 + (in->b - 127) * -0.4947), 0, 255); - p.b = iClamp(iRound(in->r * 1.0753 + (in->g - 127) * 2.0320 + (in->b - 127) * 0.0853), 0, 255); - *out = p; - ++in; - ++out; - } -} - - -void GImage::makeCheckerboard(GImage& im, int checkerSize, const Color4uint8& A, const Color4uint8& B) { - for (int y = 0; y < im.m_height; ++y) { - for (int x = 0; x < im.m_width; ++x) { - bool checker = isOdd((x / checkerSize) + (y / checkerSize)); - const Color4uint8& color = checker ? A : B; - for (int c = 0; c < im.m_channels; ++c) { - uint8* v = im.byte() + (x + y * im.m_width) * im.m_channels + c; - *v = color[c]; - } - } - } -} - -} - |