Skip to content

Crash when saving a 2048x2048 image #2

@iMrShadow

Description

@iMrShadow

Hello! I am experiencing an interesting crash when working with large textures - in this case 2048x2048. I am using a function to restore the Z axis of normal maps when converting to PNG. It "works" for small images, but it doesn't for large. I am attaching the dds files I tested in various sizes. 4 of them should work (512x512, 1024x1024, 1024x2048, 2018x1024), the last one will crash (tile_roofShingles...dds)

Normal Maps.zip

Here's the code I used.

unsafe public static void SaveNormalMap(string ddsFilePath, string destinationDirectory, TextureType textureType, DDSConversionMode conversionMode = DDSConversionMode.DEFAULT)
    {
        GetDDSImage(ddsFilePath, out ScratchImage image, out TexMetadata metadata);

// Create path for new texture file
        var path = Path.Combine(destinationDirectory, Path.GetFileNameWithoutExtension(ddsFilePath) + Converter.GetExtension(textureType)[0]);

        ScratchImage rawImage = DirectXTex.CreateScratchImage();

// Decompress to R8G8B8A8
        if (DirectXTex.IsCompressed(metadata.Format))
        {
            DirectXTex.Decompress2(image.GetImages(), image.GetImageCount(), image.GetMetadata(), (int)DXGIFormat.R8G8B8A8_UNORM, rawImage);
        }
        else
        {
// Copy the Texture if it's not compressed
            Rect rect = new() { X = 0, Y = 0, W = metadata.Width, H = metadata.Height };

            DirectXTex.CopyRectangle(image.GetImage(0, 0, 0), rect, rawImage.GetImage(0, 0, 0), TexFilterFlags.Default, 0, 0);
        }

        image.Release();

// Select the TransformImage Function (in this case we use Restore_Z and we use the RestoreZUnorm function).
        TransformImageFunc transformFunction = null;

        if (conversionMode == DDSConversionMode.RESTORE_Z)
        {
            transformFunction = RestoreZ;

            if (DirectXTex.FormatDataType(metadata.Format) == FormatType.Unorm)
            {
                transformFunction = RestoreZUnorm;
            }
        }

        ScratchImage finalImage = DirectXTex.CreateScratchImage();

// Transform the image
        if (transformFunction != null)
        {
            DirectXTex.TransformImage(rawImage.GetImage(0, 0, 0), transformFunction, finalImage);
        }

        rawImage.Release();

// Save the new image
        Guid guid = DirectXTex.GetWICCodec(GetWicDecoder(textureType));
        DirectXTex.SaveToWICFile2(finalImage.GetImages(), finalImage.GetImageCount(), 0, guid, path, null, default);


        finalImage.Release();
    }
unsafe public static void RestoreZUnorm(Vector4* outPixels, Vector4* inPixels, ulong width, ulong y)
    {
        for (ulong j = 0; j < width; ++j)
        {

            Vector4 value = inPixels[j];

            Vector4 x2 = (value * 2.0f) - Vector4.One;
            x2 = Vector4.SquareRoot(Vector4.One - Vector4.Multiply(x2, x2));
            Vector4 z = Vector4.Multiply(x2, 0.5f) + Vector4.One * 0.5f;

            outPixels[j] = value;
            outPixels[j].Z = z.Z;
        }
    }
// Enums for the modes, ignore them.
public enum DDSConversionMode
    {
        DEFAULT = 0,
        RESTORE_Z = 1,
        SWIZZLE_MASK_RG00 = 2,
        SWIZZLE_ABGR = 3,
    }

public enum TextureType
{
    Unknown,
    D3DTX,
    DDS,
    KTX,
    KTX2,
    PNG,
    JPEG,
    BMP,
    TIFF,
    TGA
}

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions