Skip to content

Commit 21e7d0f

Browse files
committed
Make PixImage creation more flexible
Removes table-based creation of PixImage in favor of dispatcher pattern based on reflection. This is more flexible and future-proof since there is no table that has to be maintained.
1 parent 357c4f0 commit 21e7d0f

File tree

3 files changed

+86
-83
lines changed

3 files changed

+86
-83
lines changed

src/Aardvark.Base.Tensors.CSharp/PixImage/PixImage.cs

+34-83
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
5+
using System.Reflection;
56
using System.Text;
67
using System.Threading;
78

@@ -522,105 +523,55 @@ protected static PixFileFormat GetFormatOfExtension(string filename)
522523
throw new ArgumentException("File name has unknown extension: " + ext);
523524
}
524525

525-
public static string GetPreferredExtensionOfFormat(PixFileFormat format)
526+
// Helper class to create PixImage from given Type
527+
private static class Dispatch
526528
{
527-
return s_preferredExtensionOfFormat.Value[format];
528-
}
529+
private static class CreateDispatcher
530+
{
531+
public static PixImage<T> Create<T>(Col.Format format, long x, long y, long channels)
532+
=> new PixImage<T>(format, x, y, channels);
529533

530-
private static Dictionary<PixFormat, Func<long, long, long, PixImage>> s_pixImageCreatorMap =
531-
new Dictionary<PixFormat, Func<long, long, long, PixImage>>()
534+
public static PixImage<T> CreateArray<T>(T[] data, Col.Format format, long x, long y, long channels)
535+
=> new PixImage<T>(format, data.CreateImageVolume(new V3l(x, y, channels)));
536+
}
537+
538+
private const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;
539+
private static readonly MethodInfo s_createMethod = typeof(CreateDispatcher).GetMethod("Create", flags);
540+
private static readonly MethodInfo s_createArrayMethod = typeof(CreateDispatcher).GetMethod("CreateArray", flags);
541+
542+
public static PixImage Create(PixFormat format, long x, long y, long channels)
532543
{
533-
{ PixFormat.ByteBW, (x, y, c) => new PixImage<byte>(Col.Format.BW, x, y, c) },
534-
{ PixFormat.ByteGray, (x, y, c) => new PixImage<byte>(Col.Format.Gray, x, y, c) },
535-
{ PixFormat.ByteBGR, (x, y, c) => new PixImage<byte>(Col.Format.BGR, x, y, c) },
536-
{ PixFormat.ByteBGRA, (x, y, c) => new PixImage<byte>(Col.Format.BGRA, x, y, c) },
537-
{ PixFormat.ByteRGBA, (x, y, c) => new PixImage<byte>(Col.Format.RGBA, x, y, c) },
538-
{ PixFormat.ByteRGB, (x, y, c) => new PixImage<byte>(Col.Format.RGB, x, y, c) },
539-
{ PixFormat.ByteBGRP, (x, y, c) => new PixImage<byte>(Col.Format.BGRP, x, y, c) },
540-
541-
{ PixFormat.SByteBW, (x, y, c) => new PixImage<sbyte>(Col.Format.BW, x, y, c) },
542-
{ PixFormat.SByteGray, (x, y, c) => new PixImage<sbyte>(Col.Format.Gray, x, y, c) },
543-
{ PixFormat.SByteBGR, (x, y, c) => new PixImage<sbyte>(Col.Format.BGR, x, y, c) },
544-
{ PixFormat.SByteBGRA, (x, y, c) => new PixImage<sbyte>(Col.Format.BGRA, x, y, c) },
545-
{ PixFormat.SByteRGBA, (x, y, c) => new PixImage<sbyte>(Col.Format.RGBA, x, y, c) },
546-
{ PixFormat.SByteRGB, (x, y, c) => new PixImage<sbyte>(Col.Format.RGB, x, y, c) },
547-
{ PixFormat.SByteBGRP, (x, y, c) => new PixImage<sbyte>(Col.Format.BGRP, x, y, c) },
548-
549-
{ PixFormat.UShortGray, (x, y, c) => new PixImage<ushort>(Col.Format.Gray, x, y, c) },
550-
{ PixFormat.UShortRGB, (x, y, c) => new PixImage<ushort>(Col.Format.RGB, x, y, c) },
551-
{ PixFormat.UShortRGBA, (x, y, c) => new PixImage<ushort>(Col.Format.RGBA, x, y, c) },
552-
{ PixFormat.UShortRGBP, (x, y, c) => new PixImage<ushort>(Col.Format.RGBP, x, y, c) },
553-
554-
{ PixFormat.ShortGray, (x, y, c) => new PixImage<short>(Col.Format.Gray, x, y, c) },
555-
{ PixFormat.ShortRGB, (x, y, c) => new PixImage<short>(Col.Format.RGB, x, y, c) },
556-
{ PixFormat.ShortRGBA, (x, y, c) => new PixImage<short>(Col.Format.RGBA, x, y, c) },
557-
{ PixFormat.ShortRGBP, (x, y, c) => new PixImage<short>(Col.Format.RGBP, x, y, c) },
558-
559-
{ PixFormat.UIntGray, (x, y, c) => new PixImage<uint>(Col.Format.Gray, x, y, c) },
560-
{ PixFormat.UIntRGB, (x, y, c) => new PixImage<uint>(Col.Format.RGB, x, y, c) },
561-
{ PixFormat.UIntRGBA, (x, y, c) => new PixImage<uint>(Col.Format.RGBA, x, y, c) },
562-
{ PixFormat.UIntRGBP, (x, y, c) => new PixImage<uint>(Col.Format.RGBP, x, y, c) },
563-
564-
{ PixFormat.IntGray, (x, y, c) => new PixImage<int>(Col.Format.Gray, x, y, c) },
565-
{ PixFormat.IntRGB, (x, y, c) => new PixImage<int>(Col.Format.RGB, x, y, c) },
566-
{ PixFormat.IntRGBA, (x, y, c) => new PixImage<int>(Col.Format.RGBA, x, y, c) },
567-
{ PixFormat.IntRGBP, (x, y, c) => new PixImage<int>(Col.Format.RGBP, x, y, c) },
568-
569-
{ PixFormat.HalfGray, (x, y, c) => new PixImage<Half>(Col.Format.Gray, x, y, c) },
570-
{ PixFormat.HalfRGB, (x, y, c) => new PixImage<Half>(Col.Format.RGB, x, y, c) },
571-
{ PixFormat.HalfRGBA, (x, y, c) => new PixImage<Half>(Col.Format.RGBA, x, y, c) },
572-
{ PixFormat.HalfRGBP, (x, y, c) => new PixImage<Half>(Col.Format.RGBP, x, y, c) },
573-
574-
{ PixFormat.FloatGray, (x, y, c) => new PixImage<float>(Col.Format.Gray, x, y, c) },
575-
{ PixFormat.FloatRGB, (x, y, c) => new PixImage<float>(Col.Format.RGB, x, y, c) },
576-
{ PixFormat.FloatRGBA, (x, y, c) => new PixImage<float>(Col.Format.RGBA, x, y, c) },
577-
{ PixFormat.FloatRGBP, (x, y, c) => new PixImage<float>(Col.Format.RGBP, x, y, c) },
578-
579-
{ PixFormat.DoubleGray, (x, y, c) => new PixImage<double>(Col.Format.Gray, x, y, c) },
580-
{ PixFormat.DoubleRGB, (x, y, c) => new PixImage<double>(Col.Format.RGB, x, y, c) },
581-
{ PixFormat.DoubleRGBA, (x, y, c) => new PixImage<double>(Col.Format.RGBA, x, y, c) },
582-
{ PixFormat.DoubleRGBP, (x, y, c) => new PixImage<double>(Col.Format.RGBP, x, y, c) },
583-
};
544+
var mi = s_createMethod.MakeGenericMethod(format.Type);
545+
return (PixImage)mi.Invoke(null, new object[] { format.Format, x, y, channels });
546+
}
584547

585-
private static Dictionary<Type, Func<Array, Col.Format, long, long, long, PixImage>> s_pixImageArrayCreatorMap =
586-
new Dictionary<Type, Func<Array, Col.Format, long, long, long, PixImage>>()
548+
public static PixImage Create(Array array, Col.Format format, long x, long y, long channels)
587549
{
588-
{ typeof(byte[]), (a, f, x, y, c) =>
589-
new PixImage<byte>(f, ((byte[])a).CreateImageVolume(new V3l(x, y, c))) },
590-
{ typeof(sbyte[]), (a, f, x, y, c) =>
591-
new PixImage<sbyte>(f, ((sbyte[])a).CreateImageVolume(new V3l(x, y, c))) },
592-
{ typeof(ushort[]), (a, f, x, y, c) =>
593-
new PixImage<ushort>(f, ((ushort[])a).CreateImageVolume(new V3l(x, y, c))) },
594-
{ typeof(short[]), (a, f, x, y, c) =>
595-
new PixImage<short>(f, ((short[])a).CreateImageVolume(new V3l(x, y, c))) },
596-
{ typeof(uint[]), (a, f, x, y, c) =>
597-
new PixImage<uint>(f, ((uint[])a).CreateImageVolume(new V3l(x, y, c))) },
598-
{ typeof(int[]), (a, f, x, y, c) =>
599-
new PixImage<int>(f, ((int[])a).CreateImageVolume(new V3l(x, y, c))) },
600-
{ typeof(Half[]), (a, f, x, y, c) =>
601-
new PixImage<Half>(f, ((Half[])a).CreateImageVolume(new V3l(x, y, c))) },
602-
{ typeof(float[]), (a, f, x, y, c) =>
603-
new PixImage<float>(f, ((float[])a).CreateImageVolume(new V3l(x, y, c))) },
604-
{ typeof(double[]), (a, f, x, y, c) =>
605-
new PixImage<double>(f, ((double[])a).CreateImageVolume(new V3l(x, y, c))) },
606-
};
550+
var mi = s_createArrayMethod.MakeGenericMethod(array.GetType().GetElementType());
551+
return (PixImage)mi.Invoke(null, new object[] { array, format, x, y, channels });
552+
}
553+
}
607554

555+
public static string GetPreferredExtensionOfFormat(PixFileFormat format)
556+
{
557+
return s_preferredExtensionOfFormat.Value[format];
558+
}
608559

609560
#endregion
610561

611562
#region Static Creator Functions
612563

613-
public static PixImage Create(PixFormat pixFormat, long sx, long sy, long ch)
614-
=> s_pixImageCreatorMap[pixFormat](sx, sy, ch);
564+
public static PixImage Create(PixFormat format, long sx, long sy, long ch)
565+
=> Dispatch.Create(format, sx, sy, ch);
615566

616-
public static PixImage Create(PixFormat pixFormat, long sx, long sy)
617-
=> s_pixImageCreatorMap[pixFormat](sx, sy, pixFormat.Format.ChannelCount());
567+
public static PixImage Create(PixFormat format, long sx, long sy)
568+
=> Dispatch.Create(format, sx, sy, format.ChannelCount);
618569

619570
public static PixImage Create(Array array, Col.Format format, long sx, long sy, long ch)
620-
=> s_pixImageArrayCreatorMap[array.GetType()](array, format, sx, sy, ch);
571+
=> Dispatch.Create(array, format, sx, sy, ch);
621572

622573
public static PixImage Create(Array array, Col.Format format, long sx, long sy)
623-
=> s_pixImageArrayCreatorMap[array.GetType()](array, format, sx, sy, format.ChannelCount());
574+
=> Dispatch.Create(array, format, sx, sy, format.ChannelCount());
624575

625576
public static Volume<T> CreateVolume<T>(V3i size) => size.ToV3l().CreateImageVolume<T>();
626577

src/Aardvark.Base/Math/Colors/Color.cs

+9
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,7 @@ public PixFormat(Type type, Col.Format format)
19321932

19331933
public static readonly PixFormat ByteBW = new PixFormat(typeof(byte), Col.Format.BW);
19341934
public static readonly PixFormat ByteGray = new PixFormat(typeof(byte), Col.Format.Gray);
1935+
public static readonly PixFormat ByteRG = new PixFormat(typeof(byte), Col.Format.RG);
19351936
public static readonly PixFormat ByteBGR = new PixFormat(typeof(byte), Col.Format.BGR);
19361937
public static readonly PixFormat ByteRGB = new PixFormat(typeof(byte), Col.Format.RGB);
19371938
public static readonly PixFormat ByteBGRA = new PixFormat(typeof(byte), Col.Format.BGRA);
@@ -1941,6 +1942,7 @@ public PixFormat(Type type, Col.Format format)
19411942

19421943
public static readonly PixFormat SByteBW = new PixFormat(typeof(sbyte), Col.Format.BW);
19431944
public static readonly PixFormat SByteGray = new PixFormat(typeof(sbyte), Col.Format.Gray);
1945+
public static readonly PixFormat SByteRG = new PixFormat(typeof(sbyte), Col.Format.RG);
19441946
public static readonly PixFormat SByteBGR = new PixFormat(typeof(sbyte), Col.Format.BGR);
19451947
public static readonly PixFormat SByteRGB = new PixFormat(typeof(sbyte), Col.Format.RGB);
19461948
public static readonly PixFormat SByteBGRA = new PixFormat(typeof(sbyte), Col.Format.BGRA);
@@ -1949,6 +1951,7 @@ public PixFormat(Type type, Col.Format format)
19491951
public static readonly PixFormat SByteRGBP = new PixFormat(typeof(sbyte), Col.Format.RGBP);
19501952

19511953
public static readonly PixFormat UShortGray = new PixFormat(typeof(ushort), Col.Format.Gray);
1954+
public static readonly PixFormat UShortRG = new PixFormat(typeof(ushort), Col.Format.RG);
19521955
public static readonly PixFormat UShortBGR = new PixFormat(typeof(ushort), Col.Format.BGR);
19531956
public static readonly PixFormat UShortRGB = new PixFormat(typeof(ushort), Col.Format.RGB);
19541957
public static readonly PixFormat UShortBGRA = new PixFormat(typeof(ushort), Col.Format.BGRA);
@@ -1957,6 +1960,7 @@ public PixFormat(Type type, Col.Format format)
19571960
public static readonly PixFormat UShortRGBP = new PixFormat(typeof(ushort), Col.Format.RGBP);
19581961

19591962
public static readonly PixFormat ShortGray = new PixFormat(typeof(short), Col.Format.Gray);
1963+
public static readonly PixFormat ShortRG = new PixFormat(typeof(short), Col.Format.RG);
19601964
public static readonly PixFormat ShortBGR = new PixFormat(typeof(short), Col.Format.BGR);
19611965
public static readonly PixFormat ShortRGB = new PixFormat(typeof(short), Col.Format.RGB);
19621966
public static readonly PixFormat ShortBGRA = new PixFormat(typeof(short), Col.Format.BGRA);
@@ -1965,6 +1969,7 @@ public PixFormat(Type type, Col.Format format)
19651969
public static readonly PixFormat ShortRGBP = new PixFormat(typeof(short), Col.Format.RGBP);
19661970

19671971
public static readonly PixFormat UIntGray = new PixFormat(typeof(uint), Col.Format.Gray);
1972+
public static readonly PixFormat UIntRG = new PixFormat(typeof(uint), Col.Format.RG);
19681973
public static readonly PixFormat UIntBGR = new PixFormat(typeof(uint), Col.Format.BGR);
19691974
public static readonly PixFormat UIntRGB = new PixFormat(typeof(uint), Col.Format.RGB);
19701975
public static readonly PixFormat UIntBGRA = new PixFormat(typeof(uint), Col.Format.BGRA);
@@ -1973,6 +1978,7 @@ public PixFormat(Type type, Col.Format format)
19731978
public static readonly PixFormat UIntRGBP = new PixFormat(typeof(uint), Col.Format.RGBP);
19741979

19751980
public static readonly PixFormat IntGray = new PixFormat(typeof(int), Col.Format.Gray);
1981+
public static readonly PixFormat IntRG = new PixFormat(typeof(int), Col.Format.RG);
19761982
public static readonly PixFormat IntBGR = new PixFormat(typeof(int), Col.Format.BGR);
19771983
public static readonly PixFormat IntRGB = new PixFormat(typeof(int), Col.Format.RGB);
19781984
public static readonly PixFormat IntBGRA = new PixFormat(typeof(int), Col.Format.BGRA);
@@ -1981,6 +1987,7 @@ public PixFormat(Type type, Col.Format format)
19811987
public static readonly PixFormat IntRGBP = new PixFormat(typeof(int), Col.Format.RGBP);
19821988

19831989
public static readonly PixFormat HalfGray = new PixFormat(typeof(Half), Col.Format.Gray);
1990+
public static readonly PixFormat HalfRG = new PixFormat(typeof(Half), Col.Format.RG);
19841991
public static readonly PixFormat HalfBGR = new PixFormat(typeof(Half), Col.Format.BGR);
19851992
public static readonly PixFormat HalfRGB = new PixFormat(typeof(Half), Col.Format.RGB);
19861993
public static readonly PixFormat HalfBGRA = new PixFormat(typeof(Half), Col.Format.BGRA);
@@ -1989,6 +1996,7 @@ public PixFormat(Type type, Col.Format format)
19891996
public static readonly PixFormat HalfRGBP = new PixFormat(typeof(Half), Col.Format.RGBP);
19901997

19911998
public static readonly PixFormat FloatGray = new PixFormat(typeof(float), Col.Format.Gray);
1999+
public static readonly PixFormat FloatRG = new PixFormat(typeof(float), Col.Format.RG);
19922000
public static readonly PixFormat FloatBGR = new PixFormat(typeof(float), Col.Format.BGR);
19932001
public static readonly PixFormat FloatRGB = new PixFormat(typeof(float), Col.Format.RGB);
19942002
public static readonly PixFormat FloatBGRA = new PixFormat(typeof(float), Col.Format.BGRA);
@@ -1997,6 +2005,7 @@ public PixFormat(Type type, Col.Format format)
19972005
public static readonly PixFormat FloatRGBP = new PixFormat(typeof(float), Col.Format.RGBP);
19982006

19992007
public static readonly PixFormat DoubleGray = new PixFormat(typeof(double), Col.Format.Gray);
2008+
public static readonly PixFormat DoubleRG = new PixFormat(typeof(double), Col.Format.RG);
20002009
public static readonly PixFormat DoubleBGR = new PixFormat(typeof(double), Col.Format.BGR);
20012010
public static readonly PixFormat DoubleRGB = new PixFormat(typeof(double), Col.Format.RGB);
20022011
public static readonly PixFormat DoubleBGRA = new PixFormat(typeof(double), Col.Format.BGRA);

src/Tests/Aardvark.Base.Tests/Images/PixImageTests.cs

+43
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.Text;
55
using Aardvark.Base;
6+
using System.Runtime.InteropServices;
67

78
namespace Aardvark.Tests.Images
89
{
@@ -330,5 +331,47 @@ public void FormatConversionRGToBGR()
330331
#endregion
331332

332333
#endregion
334+
335+
#region Creation
336+
337+
struct Foo
338+
{
339+
public string Hugo;
340+
public int Bar;
341+
}
342+
343+
[Test]
344+
public void CreateWithCustomFormat()
345+
{
346+
var format = new PixFormat(typeof(Foo), Col.Format.RG);
347+
var pi = PixImage.Create(format, 4, 4).AsPixImage<Foo>();
348+
349+
pi.Volume[3, 2, 0] = new Foo() { Hugo = "Hey", Bar = 43 };
350+
351+
var result = pi.Volume[3, 2, 0];
352+
Assert.AreEqual("Hey", result.Hugo);
353+
Assert.AreEqual(43, result.Bar);
354+
}
355+
356+
[Test]
357+
public void CreateArrayWithCustomFormat()
358+
{
359+
var data = new Foo[]
360+
{
361+
new Foo() { Hugo = "A", Bar = 1 },
362+
new Foo() { Hugo = "B", Bar = 2 },
363+
new Foo() { Hugo = "C", Bar = 3 },
364+
new Foo() { Hugo = "D", Bar = 4 },
365+
};
366+
367+
var pi = PixImage.Create(data, Col.Format.Gray, 2, 2).AsPixImage<Foo>();
368+
369+
for (int i = 0; i < data.Length; i++)
370+
{
371+
Assert.AreEqual(data[i], pi.Matrix[i % 2, i / 2]);
372+
}
373+
}
374+
375+
#endregion
333376
}
334377
}

0 commit comments

Comments
 (0)