{"record":{"id":"42b0e4ccf24bae8d","repo":"SixLabors/ImageSharp","slug":"matrix-is-degenerate-check-input-values-42b0e4","errorCode":null,"errorMessage":"Matrix is degenerate. Check input values.","messagePattern":"Matrix is degenerate\\. Check input values\\.","errorType":"exception","errorClass":"DegenerateTransformException","httpStatus":null,"severity":"error","filePath":"src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor.cs","lineNumber":26,"sourceCode":"/// <summary>\n/// Defines a projective transformation applicable to an <see cref=\"Image\"/>.\n/// </summary>\npublic sealed class ProjectiveTransformProcessor : CloningImageProcessor\n{\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"ProjectiveTransformProcessor\"/> class.\n    /// </summary>\n    /// <param name=\"matrix\">The transform matrix.</param>\n    /// <param name=\"sampler\">The sampler to perform the transform operation.</param>\n    /// <param name=\"targetDimensions\">The target dimensions.</param>\n    public ProjectiveTransformProcessor(Matrix4x4 matrix, IResampler sampler, Size targetDimensions)\n    {\n        Guard.NotNull(sampler, nameof(sampler));\n        Guard.MustBeValueType(sampler);\n\n        if (TransformUtilities.IsDegenerate(matrix))\n        {\n            throw new DegenerateTransformException(\"Matrix is degenerate. Check input values.\");\n        }\n\n        this.Sampler = sampler;\n        this.TransformMatrix = matrix;\n        this.DestinationSize = targetDimensions;\n    }\n\n    /// <summary>\n    /// Gets the sampler to perform interpolation of the transform operation.\n    /// </summary>\n    public IResampler Sampler { get; }\n\n    /// <summary>\n    /// Gets the matrix used to supply the projective transform.\n    /// </summary>\n    public Matrix4x4 TransformMatrix { get; }\n\n    /// <summary>","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor.cs#L8-L44","documentation":"The ProjectiveTransformProcessor constructor validates that the 4x4 projective matrix is non-degenerate — a degenerate matrix collapses the projective plane and produces an unrenderable mapping. TransformUtilities.IsDegenerate guards this in the constructor, throwing DegenerateTransformException before sampling starts.","triggerScenarios":"Creating a ProjectiveTransformProcessor or calling projective Mutate/Transform overloads with a matrix whose determinant (or relevant projective invariant) is zero, typically from a hand-built Matrix4x4 or from degenerate point correspondences.","commonSituations":"Hard-coded projective matrices with a zero row/column; concatenating transforms that cancel; building projective matrices from 4 coplanar source points via GaussianEliminationSolver (see the singular-matrix error at the same call depth).","solutions":["Check Matrix4x4.GetDeterminant() before constructing the processor","Correct or clamp the matrix values that produce the degenerate result","Catch DegenerateTransformException and substitute a fallback (identity or affine) transform","When building matrices from points, ensure they form a proper quad with non-zero area"],"exampleFix":"// before\nvar m = new Matrix4x4(\n    1, 0, 0, 0,\n    0, 1, 0, 0,\n    0, 0, 0, 0, // last row zeroed => degenerate\n    0, 0, 0, 1);\nimage.Mutate(x => x.Transform(new ProjectiveTransformBuilder().AppendMatrix(m)));\n// after\nvar m = new Matrix4x4(\n    1, 0, 0, 0,\n    0, 1, 0, 0,\n    0, 0, 1, 0,\n    0, 0, 0, 1); // ensure non-zero determinant\nimage.Mutate(x => x.Transform(new ProjectiveTransformBuilder().AppendMatrix(m)));","handlingStrategy":"validation","validationCode":"static bool IsNonDegenerate(Matrix4x4 m) => MathF.Abs(m.GetDeterminant()) > 1e-6f;\nif (!IsNonDegenerate(matrix)) throw new InvalidOperationException(\"Projective matrix is degenerate.\");","typeGuard":"static bool IsUsableProjectiveMatrix(Matrix4x4 m) => !float.IsNaN(m.GetDeterminant()) && MathF.Abs(m.GetDeterminant()) > float.Epsilon;","tryCatchPattern":"try\n{\n    image.Mutate(x => x.Transform(new ProjectiveTransformBuilder().AppendMatrix(m)));\n}\ncatch (DegenerateTransformException ex)\n{\n    // substitute identity or last-known-good matrix\n    throw;\n}","preventionTips":["Validate matrix determinant before constructing ProjectiveTransformProcessor","Avoid zeroing out rows or columns of hand-built matrices","Build matrices via ProjectiveTransformBuilder.Append* helpers with validated point pairs","When concatenating, re-check the determinant of the composed matrix"],"tags":["projective-transform","matrix","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"59ce6af6fc29027cda277ef62d4d1694a8acce91","analyzedAt":"2026-09-13T18:34:59.331Z","contentChangedAt":"2026-09-13T18:34:59.331Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}