bool NvVkContext::uploadTextureFromDDSData(const char* ddsData, int32_t length, NvVkTexture& tex) {
	NvImage* image = new NvImage;

	bool success = false;
	if (image->loadImageFromFileData((const uint8_t*)ddsData, length, "dds")) {
		success = uploadTexture(image, tex);
	}

	delete image;

	return success;
}
uint32_t NvImage::UploadTextureFromDDSData(const char* ddsData, int32_t length) {
    GLuint texID = 0;
    NvImage* image = new NvImage;

    if (image->loadImageFromFileData((const uint8_t*)ddsData, length, "dds")) {
        texID = NvImage::UploadTexture(image);
    }

    delete image;

    return texID;
}
NvImage* NvImage::CreateFromDDSFile(const char* filename) {
    int32_t len;
    char* ddsData = NvAssetLoaderRead(filename, len);

    if (!ddsData)
        return NULL;

    NvImage* image = new NvImage;
    bool result = image->loadImageFromFileData((const uint8_t*)ddsData, len, "dds");

    NvAssetLoaderFree(ddsData);
    if (!result) {
        delete image;
        image = NULL;
    }

    return image;
}
bool NvImage::readDDS(const uint8_t* data, size_t length, NvImage& i) {

    // open file
    //FILE *fp = fopen(file, "rb");
    NvFilePtr* fp = NvFilePtr::Create( (uint8_t*)data, length, NvFileMode::READ);

    if (fp == NULL)
        return false;

    // read in file marker, make sure its a DDS file
    char filecode[4];

    //fread(filecode, 1, 4, fp);
    fp->Read( 4, filecode);

    if (strncmp(filecode, "DDS ", 4) != 0)
    {
        //fclose(fp);
        delete fp;
        return false;
    }

    // read in DDS header
    DDS_HEADER ddsh;
    DDS_HEADER_10 ddsh10;

    //fread(&ddsh, sizeof(DDS_HEADER), 1, fp);
    fp->Read( sizeof(DDS_HEADER), &ddsh);

    // check if image is a volume texture
    if ((ddsh.dwCaps2 & DDSF_VOLUME) && (ddsh.dwDepth > 0))
        i._depth = ddsh.dwDepth;
    else
        i._depth = 0;

    if ((ddsh.ddspf.dwFlags & DDSF_FOURCC) && (ddsh.ddspf.dwFourCC == FOURCC_DX10)) {
        //This DDS file uses the DX10 header extension
        //fread(&ddsh10, sizeof(DDS_HEADER_10), 1, fp);
        fp->Read( sizeof(DDS_HEADER_10), &ddsh10);
    }

    // There are flags that are supposed to mark these fields as valid, but some dds files don't set them properly
    i._width = ddsh.dwWidth;
    i._height = ddsh.dwHeight;

    if (ddsh.dwFlags & DDSF_MIPMAPCOUNT) {
        i._levelCount = ddsh.dwMipMapCount;
    }
    else
        i._levelCount = 1;

    //check cube-map faces, the DX10 parser will override this
    if ( ddsh.dwCaps2 & DDSF_CUBEMAP && !(ddsh.ddspf.dwFlags & DDSF_FOURCC && ddsh.ddspf.dwFourCC == FOURCC_DX10)) {
        //this is a cubemap, count the faces
        i._layers = 0;
        i._layers += (ddsh.dwCaps2 & DDSF_CUBEMAP_POSITIVEX) ? 1 : 0;
        i._layers += (ddsh.dwCaps2 & DDSF_CUBEMAP_NEGATIVEX) ? 1 : 0;
        i._layers += (ddsh.dwCaps2 & DDSF_CUBEMAP_POSITIVEY) ? 1 : 0;
        i._layers += (ddsh.dwCaps2 & DDSF_CUBEMAP_NEGATIVEY) ? 1 : 0;
        i._layers += (ddsh.dwCaps2 & DDSF_CUBEMAP_POSITIVEZ) ? 1 : 0;
        i._layers += (ddsh.dwCaps2 & DDSF_CUBEMAP_NEGATIVEZ) ? 1 : 0;

        //check for a complete cubemap
        if ( (i._layers != 6) || (i._width != i._height) ) {
            //fclose(fp);
            delete fp;
            return false;
        }

        i._cubeMap = true;
    }
    else {
        //not a cubemap
        i._layers = 1;
        i._cubeMap = false;
    }

    bool btcCompressed = false;
    int32_t bytesPerElement = 0;

    // figure out what the image format is
    if (ddsh.ddspf.dwFlags & DDSF_FOURCC)
    {
        switch(ddsh.ddspf.dwFourCC)
        {
        case FOURCC_DXT1:
            i._format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
            i._internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
            i._type = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
            bytesPerElement = 8;
            btcCompressed = true;
            break;

        case FOURCC_DXT2:
        case FOURCC_DXT3:
            i._format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
            i._internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
            i._type = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
            bytesPerElement = 16;
            btcCompressed = true;
            break;

        case FOURCC_DXT4:
        case FOURCC_DXT5:
            i._format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
            i._internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
            i._type = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
            bytesPerElement = 16;
            btcCompressed = true;
            break;

        case FOURCC_ATI1:
            i._format = GL_COMPRESSED_RED_RGTC1;
            i._internalFormat = GL_COMPRESSED_RED_RGTC1;
            i._type = GL_COMPRESSED_RED_RGTC1;
            bytesPerElement = 8;
            btcCompressed = true;
            break;

        case FOURCC_BC4U:
            i._format = GL_COMPRESSED_RED_RGTC1;
            i._internalFormat = GL_COMPRESSED_RED_RGTC1;
            i._type = GL_COMPRESSED_RED_RGTC1;
            bytesPerElement = 8;
            btcCompressed = true;
            break;

        case FOURCC_BC4S:
            i._format = GL_COMPRESSED_SIGNED_RED_RGTC1;
            i._internalFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
            i._type = GL_COMPRESSED_SIGNED_RED_RGTC1;
            bytesPerElement = 8;
            btcCompressed = true;
            break;

        case FOURCC_ATI2:
            i._format = GL_COMPRESSED_RG_RGTC2; //GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
            i._internalFormat = GL_COMPRESSED_RG_RGTC2; //GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
            i._type = GL_COMPRESSED_RG_RGTC2; //GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
            bytesPerElement = 16;
            btcCompressed = true;
            break;

        case FOURCC_BC5S:
            i._format = GL_COMPRESSED_SIGNED_RG_RGTC2; //GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
            i._internalFormat = GL_COMPRESSED_SIGNED_RG_RGTC2; //GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
            i._type = GL_COMPRESSED_SIGNED_RG_RGTC2; //GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
            bytesPerElement = 16;
            btcCompressed = true;
            break;

        case FOURCC_R8G8B8:
            i._format = GL_BGR;
            i._internalFormat = GL_RGB8;
            i._type = GL_UNSIGNED_BYTE;
            bytesPerElement = 3;
            break;

        case FOURCC_A8R8G8B8:
            i._format = GL_BGRA;
            i._internalFormat = GL_RGBA8;
            i._type = GL_UNSIGNED_BYTE;
            bytesPerElement = 4;
            break;

        case FOURCC_X8R8G8B8:
            i._format = GL_BGRA;
            i._internalFormat = GL_RGB8;
            i._type = GL_UNSIGNED_INT_8_8_8_8;
            bytesPerElement = 4;
            break;

        case FOURCC_R5G6B5:
            i._format = GL_BGR;
            i._internalFormat = GL_RGB5;
            i._type = GL_UNSIGNED_SHORT_5_6_5;
            bytesPerElement = 2;
            break;

        case FOURCC_A8:
            i._format = GL_ALPHA;
            i._internalFormat = GL_ALPHA8;
            i._type = GL_UNSIGNED_BYTE;
            bytesPerElement = 1;
            break;

        case FOURCC_A2B10G10R10:
            i._format = GL_RGBA;
            i._internalFormat = GL_RGB10_A2;
            i._type = GL_UNSIGNED_INT_10_10_10_2;
            bytesPerElement = 4;
            break;

        case FOURCC_A8B8G8R8:
            i._format = GL_RGBA;
            i._internalFormat = GL_RGBA8;
            i._type = GL_UNSIGNED_BYTE;
            bytesPerElement = 4;
            break;

        case FOURCC_X8B8G8R8:
            i._format = GL_RGBA;
            i._internalFormat = GL_RGB8;
            i._type = GL_UNSIGNED_INT_8_8_8_8;
            bytesPerElement = 4;
            break;

        case FOURCC_A2R10G10B10:
            i._format = GL_BGRA;
            i._internalFormat = GL_RGB10_A2;
            i._type = GL_UNSIGNED_INT_10_10_10_2;
            bytesPerElement = 4;
            break;

        case FOURCC_G16R16:
            i._format = GL_RG;
            i._internalFormat = GL_RG16;
            i._type = GL_UNSIGNED_SHORT;
            bytesPerElement = 4;
            break;

        case FOURCC_A16B16G16R16:
            i._format = GL_RGBA;
            i._internalFormat = GL_RGBA16;
            i._type = GL_UNSIGNED_SHORT;
            bytesPerElement = 8;
            break;

        case FOURCC_L8:
            i._format = GL_LUMINANCE;
            i._internalFormat = GL_LUMINANCE8;
            i._type = GL_UNSIGNED_BYTE;
            bytesPerElement = 1;
            break;

        case FOURCC_A8L8:
            i._format = GL_LUMINANCE_ALPHA;
            i._internalFormat = GL_LUMINANCE8_ALPHA8;
            i._type = GL_UNSIGNED_BYTE;
            bytesPerElement = 2;
            break;

        case FOURCC_L16:
            i._format = GL_LUMINANCE;
            i._internalFormat = GL_LUMINANCE16;
            i._type = GL_UNSIGNED_SHORT;
            bytesPerElement = 2;
            break;

        case FOURCC_Q16W16V16U16:
            i._format = GL_RGBA;
            i._internalFormat = GL_RGBA16_SNORM;
            i._type = GL_SHORT;
            bytesPerElement = 8;
            break;

        case FOURCC_R16F:
            i._format = GL_RED;
            i._internalFormat = GL_R16F;
            i._type = GL_HALF_FLOAT_ARB;
            bytesPerElement = 2;
            break;

        case FOURCC_G16R16F:
            i._format = GL_RG;
            i._internalFormat = GL_RG16F;
            i._type = GL_HALF_FLOAT_ARB;
            bytesPerElement = 4;
            break;

        case FOURCC_A16B16G16R16F:
            i._format = GL_RGBA;
            i._internalFormat = GL_RGBA16F_ARB;
            i._type = GL_HALF_FLOAT_ARB;
            bytesPerElement = 8;
            break;

        case FOURCC_R32F:
            i._format = GL_RED;
            i._internalFormat = GL_R32F;
            i._type = GL_FLOAT;
            bytesPerElement = 4;
            break;

        case FOURCC_G32R32F:
            i._format = GL_RG;
            i._internalFormat = GL_RG32F;
            i._type = GL_FLOAT;
            bytesPerElement = 8;
            break;

        case FOURCC_A32B32G32R32F:
            i._format = GL_RGBA;
            i._internalFormat = GL_RGBA32F_ARB;
            i._type = GL_FLOAT;
            bytesPerElement = 16;
            break;

        case FOURCC_DX10:
            if (!TranslateDX10Format( &ddsh10, i, bytesPerElement, btcCompressed)) {
                //fclose(fp);
                delete fp;
                return false; //translation from DX10 failed
            }
            break;

        case FOURCC_UNKNOWN:
        case FOURCC_X1R5G5B5:
        case FOURCC_A1R5G5B5:
        case FOURCC_A4R4G4B4:
        case FOURCC_R3G3B2:
        case FOURCC_A8R3G3B2:
        case FOURCC_X4R4G4B4:
        case FOURCC_A4L4:
        case FOURCC_D16_LOCKABLE:
        case FOURCC_D32:
        case FOURCC_D24X8:
        case FOURCC_D16:
        case FOURCC_D32F_LOCKABLE:
        //these are unsupported for now
        default:
            //fclose(fp);
            delete fp;
            return false;
        }
    }
    else if (ddsh.ddspf.dwFlags == DDSF_RGBA && ddsh.ddspf.dwRGBBitCount == 32)
    {
        if ( ddsh.ddspf.dwRBitMask == 0xff && ddsh.ddspf.dwGBitMask == 0xff00 && ddsh.ddspf.dwBBitMask == 0xff0000 && ddsh.ddspf.dwABitMask == 0xff000000 ) {
            //RGBA8 order
            i._format = GL_RGBA;
            i._internalFormat = GL_RGBA8;
            i._type = GL_UNSIGNED_BYTE;
        }
        else if ( ddsh.ddspf.dwRBitMask == 0xff0000 && ddsh.ddspf.dwGBitMask == 0xff00 && ddsh.ddspf.dwBBitMask == 0xff && ddsh.ddspf.dwABitMask == 0xff000000 ) {
            //BGRA8 order
            i._format = GL_BGRA;
            i._internalFormat = GL_RGBA8;
            i._type = GL_UNSIGNED_BYTE;
        }
        else if ( ddsh.ddspf.dwRBitMask == 0x3ff00000 && ddsh.ddspf.dwGBitMask == 0xffc00 && ddsh.ddspf.dwBBitMask == 0x3ff && ddsh.ddspf.dwABitMask == 0xc0000000 ) {
            //BGR10_A2 order
            i._format = GL_RGBA;
            i._internalFormat = GL_RGB10_A2;
            i._type = GL_UNSIGNED_INT_2_10_10_10_REV; //GL_UNSIGNED_INT_10_10_10_2;
        }
        else if ( ddsh.ddspf.dwRBitMask == 0x3ff && ddsh.ddspf.dwGBitMask == 0xffc00 && ddsh.ddspf.dwBBitMask == 0x3ff00000 && ddsh.ddspf.dwABitMask == 0xc0000000 ) {
            //RGB10_A2 order
            i._format = GL_RGBA;
            i._internalFormat = GL_RGB10_A2;
            i._type = GL_UNSIGNED_INT_10_10_10_2;
        }
        else {
            //we'll just guess BGRA8, because that is the common legacy format for improperly labeled files
            i._format = GL_BGRA;
            i._internalFormat = GL_RGBA8;
            i._type = GL_UNSIGNED_BYTE;
        }
        bytesPerElement = 4;
    }
    else if (ddsh.ddspf.dwFlags == DDSF_RGB  && ddsh.ddspf.dwRGBBitCount == 32)
    {
        if ( ddsh.ddspf.dwRBitMask == 0xffff && ddsh.ddspf.dwGBitMask == 0xffff0000 && ddsh.ddspf.dwBBitMask == 0x00 && ddsh.ddspf.dwABitMask == 0x00 ) {
            i._format = GL_RG;
            i._internalFormat = GL_RG16;
            i._type = GL_UNSIGNED_SHORT;
        }
        else if ( ddsh.ddspf.dwRBitMask == 0xff && ddsh.ddspf.dwGBitMask == 0xff00 && ddsh.ddspf.dwBBitMask == 0xff0000 && ddsh.ddspf.dwABitMask == 0x00 ) {
            i._format = GL_RGB;
            i._internalFormat = GL_RGBA8;
            i._type = GL_UNSIGNED_INT_8_8_8_8;
        }
        else if ( ddsh.ddspf.dwRBitMask == 0xff0000 && ddsh.ddspf.dwGBitMask == 0xff00 && ddsh.ddspf.dwBBitMask == 0xff && ddsh.ddspf.dwABitMask == 0x00 ) {
            i._format = GL_BGR;
            i._internalFormat = GL_RGBA8;
            i._type = GL_UNSIGNED_INT_8_8_8_8;
        }
        else {
            // probably a poorly labeled file with BGRX semantics
            i._format = GL_BGR;
            i._internalFormat = GL_RGBA8;
            i._type = GL_UNSIGNED_INT_8_8_8_8;
        }
        bytesPerElement = 4;
    }
    else if (ddsh.ddspf.dwFlags == DDSF_RGB  && ddsh.ddspf.dwRGBBitCount == 24)
    {
        i._format = GL_BGR;
        i._internalFormat = GL_RGB8;
        i._type = GL_UNSIGNED_BYTE;
        bytesPerElement = 3;
    }
    // these cases revived from NVHHDDS...
    else if ((ddsh.ddspf.dwRGBBitCount == 16) &&
             (ddsh.ddspf.dwRBitMask == 0x0000F800) &&
             (ddsh.ddspf.dwGBitMask == 0x000007E0) &&
             (ddsh.ddspf.dwBBitMask == 0x0000001F) &&
             (ddsh.ddspf.dwABitMask == 0x00000000))
    {
        // We support D3D's R5G6B5, which is actually RGB in linear
        // memory.  It is equivalent to GL's GL_UNSIGNED_SHORT_5_6_5
        i._format = GL_BGR;
        i._internalFormat = GL_RGB5;
        i._type = GL_UNSIGNED_SHORT_5_6_5;
        bytesPerElement = 2;
    }
    else if ((ddsh.ddspf.dwRGBBitCount == 8) &&
             (ddsh.ddspf.dwRBitMask == 0x00000000) &&
             (ddsh.ddspf.dwGBitMask == 0x00000000) &&
             (ddsh.ddspf.dwBBitMask == 0x00000000) &&
             (ddsh.ddspf.dwABitMask == 0x000000FF))
    {
        // We support D3D's A8
        i._format = GL_ALPHA;
        i._internalFormat = GL_ALPHA8;
        i._type = GL_UNSIGNED_BYTE;
        bytesPerElement = 1;
    }
    else if ((ddsh.ddspf.dwRGBBitCount == 8) &&
             (ddsh.ddspf.dwRBitMask == 0x000000FF) &&
             (ddsh.ddspf.dwGBitMask == 0x00000000) &&
             (ddsh.ddspf.dwBBitMask == 0x00000000) &&
             (ddsh.ddspf.dwABitMask == 0x00000000))
    {
        // We support D3D's L8 (flagged as 8 bits of red only)
        i._format = GL_LUMINANCE;
        i._internalFormat = GL_LUMINANCE8;
        i._type = GL_UNSIGNED_BYTE;
        bytesPerElement = 1;
    }
    else if ((ddsh.ddspf.dwRGBBitCount == 16) &&
             (((ddsh.ddspf.dwRBitMask == 0x000000FF) &&
               (ddsh.ddspf.dwGBitMask == 0x00000000) &&
               (ddsh.ddspf.dwBBitMask == 0x00000000) &&
               (ddsh.ddspf.dwABitMask == 0x0000FF00)) ||
              ((ddsh.ddspf.dwRBitMask == 0x000000FF) && // GIMP header for L8A8
               (ddsh.ddspf.dwGBitMask == 0x000000FF) &&  // Ugh
               (ddsh.ddspf.dwBBitMask == 0x000000FF) &&
               (ddsh.ddspf.dwABitMask == 0x0000FF00)))
            )
    {
        // We support D3D's A8L8 (flagged as 8 bits of red and 8 bits of alpha)
        i._format = GL_LUMINANCE_ALPHA;
        i._internalFormat = GL_LUMINANCE8_ALPHA8;
        i._type = GL_UNSIGNED_BYTE;
        bytesPerElement = 2;
    }
    // else fall back to L8 generic handling if capable.
    else if (ddsh.ddspf.dwRGBBitCount == 8)
    {
        i._format = GL_LUMINANCE;
        i._internalFormat = GL_LUMINANCE8;
        i._type = GL_UNSIGNED_BYTE;
        bytesPerElement = 1;
    }
    // else, we can't decode this file... :-(
    else
    {
        // TODO better error?
        //LOGI("! Error decoding DDS file.");
        //fclose(fp);
        delete fp;
        return false;
    }

    i._elementSize = bytesPerElement;

    i._data.clear();

    const NvGfxAPIVersion& api = NvImage::getAPIVersion();

    bool isES = (api.api == NvGfxAPI::GLES);
    bool mustExpandDXT = m_expandDXT &&
                         ((i._format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ||
                          (i._format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) ||
                          (i._format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT));

    for (int32_t face = 0; face < i._layers; face++) {
        int32_t w = i._width, h = i._height, d = (i._depth) ? i._depth : 1;
        for (int32_t level = 0; level < i._levelCount; level++) {
            int32_t bw = (btcCompressed) ? (w+3)/4 : w;
            int32_t bh = (btcCompressed) ? (h+3)/4 : h;
            int32_t size = bw*bh*d*bytesPerElement;

            uint8_t *pixels = new uint8_t[size];

            //fread( data, size, 1, fp);
            fp->Read( size, pixels);

            if ( NvImage::upperLeftOrigin && !i._cubeMap)
                i.flipSurface( pixels, w, h, d);

            if (isES)
                i.componentSwapSurface(pixels, w, h, d);

            // do we need to expand DXT?
            if (mustExpandDXT) {
                uint8_t* expandedPixels = i.expandDXT(pixels, w, h, d);
                delete[] pixels;
                pixels = expandedPixels;
            }

            i._data.push_back(pixels);

            //reduce mip sizes
            w = ( w > 1) ? w >> 1 : 1;
            h = ( h > 1) ? h >> 1 : 1;
            d = ( d > 1) ? d >> 1 : 1;
        }
    }

    if (mustExpandDXT) {
        i._format = GL_RGBA;
        i._type = GL_UNSIGNED_BYTE;
    }

    //fclose(fp);
    delete fp;
    return true;
}
bool NvImage::readTarga( const uint8_t* fileData, size_t size, NvImage& i )
{
	NV_ASSERT( fileData != NULL );

	const uint8_t* pTga = fileData;

	const uint8_t* pHeader = pTga;
	NV_ASSERT( pHeader[0x02] == IMAGE_FULL_COLOR ); // Only Full-color image is supported.

	uint8_t bpp = pHeader[0x10];
	int bytePerPixel = i._elementSize = bpp / 8;

	const NvGfxAPIVersion& api = NvImage::getAPIVersion();
	bool isES = ( api.api == NvGfxAPI::GLES );

	// Determine texture format with BPP
	switch( bpp ) {
		case 24:
			i._format = isES ? GL_RGB : GL_BGR;
			i._internalFormat = GL_RGB8;
			i._type = GL_UNSIGNED_BYTE;
			break;
		case 32:
			i._format = isES ? GL_RGBA : GL_BGRA;
			i._internalFormat = GL_RGBA8;
			i._type = GL_UNSIGNED_BYTE;
			break;
		default:
			NV_ALWAYS_ASSERT();
			break;
	}

	uint8_t discripter = pHeader[0x11];
	NV_ASSERT( ( discripter & eTGA_DISCRIPTER_RIGHT_TO_LEFT ) == 0 ); // Horizontal sequence must be left to right.

	i._width = *reinterpret_cast<const uint16_t*>( &pHeader[0x0c] );
	i._height = *reinterpret_cast<const uint16_t*>( &pHeader[0x0e] );

	// Other parameters are not related to Targa.
	i._levelCount = 1;	// MipMap level
	i._depth = 0;		// If it's a volume texture.
	i._layers = 1;
	i._cubeMap = false;

	const uint32_t headerSize = 0x12;
	const uint8_t* pDataSource = pTga + headerSize;

	int imageByteSize = i._width * i._height * bytePerPixel;
	i._data.clear();

	uint8_t* pPixelData = new uint8_t[imageByteSize];

	//if( bFlipHorizontal ) {
	//	uint8_t* pDataTemp = pDataSource;
	//	const int rowSize = bytePerPixel * width;
	//	const int half = width / 2;

	//	for( int i = 0; i < height; ++i ) {
	//		for( int k = 0; k < half; ++k ) {
	//			for( int m = 0; m < bytePerPixel; ++m ) {
	//				uint8_t temp = pDataTemp[k * bytePerPixel + m];
	//				pDataTemp[k * bytePerPixel + m] = pDataTemp[( width - 1 - k ) * bytePerPixel + m];
	//				pDataTemp[( width - 1 - k ) * bytePerPixel + m] = temp;
	//			}
	//		}
	//		pDataTemp += rowSize;
	//	}
	//}

	//bFlipVertical = bFlipVertical ^ ( discripter & eTGA_DISCRIPTER_UP_TO_DOWN ? true : false );
	bool bFlipVertical = discripter & eTGA_DISCRIPTER_UP_TO_DOWN ? true : false;

	//if( bFlipVertical ) {
	//	// should be up-side-down for OpenGL UV Coordinate
	//	const int rowSize = bytePerPixel * i._width;
	//	for( int y = i._height - 1; y >= 0; --y ) {
	//		memcpy( pPixelData + ( y * rowSize ), pDataSource, rowSize );
	//		pDataSource += rowSize;
	//	}
	//}
	//else {
	//	memcpy( pPixelData, pDataSource, imageByteSize );
	//}
	memcpy( pPixelData, pDataSource, imageByteSize );
	if( bFlipVertical ) {
		i.flipSurface( pPixelData, i._width, i._height, i._depth );
	}

	// swap B <-> R
	// *default color sequence is BGR or BGRA
	if( isES ) {
		i.componentSwapSurface( pPixelData, i._width, i._height, i._depth );
	}
//#ifdef ANDROID
	//for( int n = 0; n < imageByteSize; n += bytePerPixel ) {
	//	uint8_t temp = pPixelData[n];
	//	pPixelData[n] = pPixelData[n + 2];
	//	pPixelData[n + 2] = temp;
	//}
	//info.channelOrderReverse = false;
//#endif

	i._data.push_back( pPixelData );

	return true;
}
static VkFormat TranslateNvFormat(const NvImage &i) {
	uint32_t fmt = i.getInternalFormat();

	switch (fmt) {
	case NVIMAGE_RGBA32F:
		return VK_FORMAT_R32G32B32A32_SFLOAT;

	case NVIMAGE_RGBA32UI:
		return VK_FORMAT_R32G32B32A32_UINT;

	case NVIMAGE_RGBA32I:
		return VK_FORMAT_R32G32B32A32_SINT;

	case NVIMAGE_RGB32F:
		return VK_FORMAT_R32G32B32_SFLOAT;

	case NVIMAGE_RGB32UI:
		return VK_FORMAT_R32G32B32_UINT;

	case NVIMAGE_RGB32I:
		return VK_FORMAT_R32G32B32_SINT;

	case NVIMAGE_RGBA16F:
		return VK_FORMAT_R16G16B16A16_SFLOAT;

	case NVIMAGE_RGBA16:
		return VK_FORMAT_R16G16B16A16_UNORM;

	case NVIMAGE_RGBA16UI:
		return VK_FORMAT_R16G16B16A16_UINT;

	case NVIMAGE_RGBA16_SNORM:
		return VK_FORMAT_R16G16B16A16_SNORM;

	case NVIMAGE_RGBA16I:
		return VK_FORMAT_R16G16B16A16_SINT;

	case NVIMAGE_RG32F:
		return VK_FORMAT_R32G32_SFLOAT;

	case NVIMAGE_RG32UI:
		return VK_FORMAT_R32G32B32_UINT;

	case NVIMAGE_RG32I:
		return VK_FORMAT_R32G32B32_SINT;

	case NVIMAGE_RGB10_A2:
		return VK_FORMAT_A2R10G10B10_UNORM_PACK32;

	case NVIMAGE_R11F_G11F_B10F:
		return VK_FORMAT_B10G11R11_UFLOAT_PACK32;

	case NVIMAGE_RGBA8:
		return VK_FORMAT_R8G8B8A8_UNORM;

	case NVIMAGE_SRGB8_ALPHA8:
		return VK_FORMAT_R8G8B8A8_SRGB;

	case NVIMAGE_RGBA8UI:
		return VK_FORMAT_R8G8B8A8_UINT;

	case NVIMAGE_RGBA8_SNORM:
		return VK_FORMAT_B8G8R8A8_SNORM;

	case NVIMAGE_RG16F:
		return VK_FORMAT_R16G16_SFLOAT;

	case NVIMAGE_RG16:
		return VK_FORMAT_R16G16_SINT;

	case NVIMAGE_RG16UI:
		return VK_FORMAT_R16G16_UINT;

	case NVIMAGE_RG16_SNORM:
		return VK_FORMAT_R16G16_SNORM;

	case NVIMAGE_DEPTH_COMPONENT32F:
		return VK_FORMAT_D32_SFLOAT;

	case NVIMAGE_R32F:
		return VK_FORMAT_R32_SFLOAT;

	case NVIMAGE_R32UI:
		return VK_FORMAT_R32_UINT;

	case NVIMAGE_R32I:
		return VK_FORMAT_R32_SINT;

	case NVIMAGE_RG8:
		return VK_FORMAT_R8G8_UNORM;

	case NVIMAGE_RG8UI:
		return VK_FORMAT_R8G8_UINT;

	case NVIMAGE_RG8_SNORM:
		return VK_FORMAT_R8G8_SNORM;

	case NVIMAGE_RG8I:
		return VK_FORMAT_R8G8_SINT;

	case NVIMAGE_R16F:
		return VK_FORMAT_R16_SFLOAT;

	case NVIMAGE_DEPTH_COMPONENT16:
		return VK_FORMAT_D16_UNORM;

	case NVIMAGE_R16:
		return VK_FORMAT_R16_UNORM;

	case NVIMAGE_R16UI:
		return VK_FORMAT_R16_UINT;

	case NVIMAGE_R16_SNORM:
		return VK_FORMAT_R16_SNORM;

	case NVIMAGE_R16I:
		return VK_FORMAT_R16_SINT;

	case NVIMAGE_R8:
		return VK_FORMAT_R8_UNORM;

	case NVIMAGE_R8UI:
		return VK_FORMAT_R8_UINT;

	case NVIMAGE_R8_SNORM:
		return VK_FORMAT_R8_SNORM;

	case NVIMAGE_R8I:
		return VK_FORMAT_R8_SINT;

	case NVIMAGE_ALPHA8:
		return VK_FORMAT_R8_UNORM;

	case NVIMAGE_RGB9_E5:
		return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32;

	case NVIMAGE_COMPRESSED_RGBA_S3TC_DXT1:
		return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;

	case NVIMAGE_COMPRESSED_RGBA_S3TC_DXT3:
		return VK_FORMAT_BC3_UNORM_BLOCK;

	case NVIMAGE_COMPRESSED_RGBA_S3TC_DXT5:
		return VK_FORMAT_BC5_UNORM_BLOCK;

	case NVIMAGE_COMPRESSED_RED_RGTC1:
	case NVIMAGE_COMPRESSED_SIGNED_RED_RGTC1:
	case NVIMAGE_COMPRESSED_RG_RGTC2:
	case NVIMAGE_COMPRESSED_SIGNED_RG_RGTC2:

	case NVIMAGE_COMPRESSED_RGBA_ASTC_4x4:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_5x4:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_5x5:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_6x5:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_6x6:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_8x5:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_8x6:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_8x8:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_10x5:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_10x6:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_10x8:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_10x10:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_12x10:
	case NVIMAGE_COMPRESSED_RGBA_ASTC_12x12:

	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10:
	case NVIMAGE_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12:
		return VK_FORMAT_UNDEFINED;

	default:
		//these are errors
		return VK_FORMAT_UNDEFINED;
	};

	return VK_FORMAT_UNDEFINED;
}