Skip to content

Commit bcce0e9

Browse files
authored
feat: build Image/ImageFrame from Texture2D (#1083)
* refactor: add ImageFormatExtension * feat: build Image/ImageFrame from Texture2D * refactor: format.NumberOfChannels * refactor: implement ByteDepth as a extension method * refactor: implement ChannelSize as a extension method * refactor: use new constructors in TextureFrame
1 parent deeb9f0 commit bcce0e9

File tree

7 files changed

+160
-122
lines changed

7 files changed

+160
-122
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Copyright (c) 2023 homuler
2+
//
3+
// Use of this source code is governed by an MIT-style
4+
// license that can be found in the LICENSE file or at
5+
// https://opensource.org/licenses/MIT.
6+
7+
namespace Mediapipe
8+
{
9+
public static class ImageFormatExtension
10+
{
11+
/// <returns>
12+
/// The number of channels for a <paramref name="format" />.
13+
/// If channels don't make sense in the <paramref name="format" />, returns <c>0</c>.
14+
/// </returns>
15+
/// <remarks>
16+
/// Unlike the original implementation, this API won't signal SIGABRT.
17+
/// </remarks>
18+
public static int NumberOfChannels(this ImageFormat.Types.Format format)
19+
{
20+
switch (format)
21+
{
22+
case ImageFormat.Types.Format.Srgb:
23+
case ImageFormat.Types.Format.Srgb48:
24+
return 3;
25+
case ImageFormat.Types.Format.Srgba:
26+
case ImageFormat.Types.Format.Srgba64:
27+
case ImageFormat.Types.Format.Sbgra:
28+
return 4;
29+
case ImageFormat.Types.Format.Gray8:
30+
case ImageFormat.Types.Format.Gray16:
31+
return 1;
32+
case ImageFormat.Types.Format.Vec32F1:
33+
return 1;
34+
case ImageFormat.Types.Format.Vec32F2:
35+
return 2;
36+
case ImageFormat.Types.Format.Vec32F4:
37+
return 4;
38+
case ImageFormat.Types.Format.Lab8:
39+
return 3;
40+
case ImageFormat.Types.Format.Ycbcr420P:
41+
case ImageFormat.Types.Format.Ycbcr420P10:
42+
case ImageFormat.Types.Format.Unknown:
43+
default:
44+
return 0;
45+
}
46+
}
47+
48+
/// <returns>
49+
/// The depth of each channel in bytes for a <paramref name="format" />.
50+
/// If channels don't make sense in the <paramref name="format" />, returns <c>0</c>.
51+
/// </returns>
52+
/// <remarks>
53+
/// Unlike the original implementation, this API won't signal SIGABRT.
54+
/// </remarks>
55+
public static int ByteDepth(this ImageFormat.Types.Format format)
56+
{
57+
switch (format)
58+
{
59+
case ImageFormat.Types.Format.Srgb:
60+
case ImageFormat.Types.Format.Srgba:
61+
case ImageFormat.Types.Format.Sbgra:
62+
return 1;
63+
case ImageFormat.Types.Format.Srgb48:
64+
case ImageFormat.Types.Format.Srgba64:
65+
return 2;
66+
case ImageFormat.Types.Format.Gray8:
67+
return 1;
68+
case ImageFormat.Types.Format.Gray16:
69+
return 2;
70+
case ImageFormat.Types.Format.Vec32F1:
71+
case ImageFormat.Types.Format.Vec32F2:
72+
case ImageFormat.Types.Format.Vec32F4:
73+
return 4;
74+
case ImageFormat.Types.Format.Lab8:
75+
return 1;
76+
case ImageFormat.Types.Format.Ycbcr420P:
77+
case ImageFormat.Types.Format.Ycbcr420P10:
78+
case ImageFormat.Types.Format.Unknown:
79+
default:
80+
return 0;
81+
}
82+
}
83+
84+
/// <returns>
85+
/// The channel size for a <paramref name="format" />.
86+
/// If channels don't make sense in the <paramref name="format" />, returns <c>0</c>.
87+
/// </returns>
88+
/// <remarks>
89+
/// Unlike the original implementation, this API won't signal SIGABRT.
90+
/// </remarks>
91+
public static int ChannelSize(this ImageFormat.Types.Format format)
92+
{
93+
switch (format)
94+
{
95+
case ImageFormat.Types.Format.Srgb:
96+
case ImageFormat.Types.Format.Srgba:
97+
case ImageFormat.Types.Format.Sbgra:
98+
return sizeof(byte);
99+
case ImageFormat.Types.Format.Srgb48:
100+
case ImageFormat.Types.Format.Srgba64:
101+
return sizeof(ushort);
102+
case ImageFormat.Types.Format.Gray8:
103+
return sizeof(byte);
104+
case ImageFormat.Types.Format.Gray16:
105+
return sizeof(ushort);
106+
case ImageFormat.Types.Format.Vec32F1:
107+
case ImageFormat.Types.Format.Vec32F2:
108+
case ImageFormat.Types.Format.Vec32F4:
109+
// sizeof float may be wrong since it's platform-dependent, but we assume that it's constant across all supported platforms.
110+
return sizeof(float);
111+
case ImageFormat.Types.Format.Lab8:
112+
return sizeof(byte);
113+
case ImageFormat.Types.Format.Ycbcr420P:
114+
case ImageFormat.Types.Format.Ycbcr420P10:
115+
case ImageFormat.Types.Format.Unknown:
116+
default:
117+
return 0;
118+
}
119+
}
120+
}
121+
}

Packages/com.github.homuler.mediapipe/Runtime/Scripts/Extension/ImageFormatExtension.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Formats/Image.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System;
88
using Unity.Collections;
99
using Unity.Collections.LowLevel.Unsafe;
10+
using UnityEngine;
1011

1112
namespace Mediapipe
1213
{
@@ -43,6 +44,11 @@ public Image(ImageFormat.Types.Format format, int width, int height, int widthSt
4344
: this(format, width, height, widthStep, pixelData, _VoidDeleter)
4445
{ }
4546

47+
// TODO: detect format from the texture
48+
public Image(ImageFormat.Types.Format format, Texture2D texture) :
49+
this(format, texture.width, texture.height, format.NumberOfChannels() * texture.width, texture.GetRawTextureData<byte>())
50+
{ }
51+
4652
#if UNITY_EDITOR_LINUX || UNITY_STANDLONE_LINUX || UNITY_ANDROID
4753
public Image(uint target, uint name, int width, int height, GpuBufferFormat format, GlTextureBuffer.DeletionCallback callback, GlContext glContext) : base()
4854
{

Packages/com.github.homuler.mediapipe/Runtime/Scripts/Framework/Formats/ImageFrame.cs

Lines changed: 9 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System;
88
using Unity.Collections;
99
using Unity.Collections.LowLevel.Unsafe;
10+
using UnityEngine;
1011

1112
namespace Mediapipe
1213
{
@@ -65,6 +66,11 @@ public ImageFrame(ImageFormat.Types.Format format, int width, int height, int wi
6566
: this(format, width, height, widthStep, pixelData, _VoidDeleter)
6667
{ }
6768

69+
// TODO: detect format from the texture
70+
public ImageFrame(ImageFormat.Types.Format format, Texture2D texture) :
71+
this(format, texture.width, texture.height, format.NumberOfChannels() * texture.width, texture.GetRawTextureData<byte>())
72+
{ }
73+
6874
protected override void DeleteMpPtr()
6975
{
7076
UnsafeNativeMethods.mp_ImageFrame__delete(ptr);
@@ -75,112 +81,6 @@ protected override void DeleteMpPtr()
7581
[AOT.MonoPInvokeCallback(typeof(Deleter))]
7682
internal static void VoidDeleter(IntPtr _) { }
7783

78-
/// <returns>
79-
/// The number of channels for a <paramref name="format" />.
80-
/// If channels don't make sense in the <paramref name="format" />, returns <c>0</c>.
81-
/// </returns>
82-
/// <remarks>
83-
/// Unlike the original implementation, this API won't signal SIGABRT.
84-
/// </remarks>
85-
public static int NumberOfChannelsForFormat(ImageFormat.Types.Format format)
86-
{
87-
switch (format)
88-
{
89-
case ImageFormat.Types.Format.Srgb:
90-
case ImageFormat.Types.Format.Srgb48:
91-
return 3;
92-
case ImageFormat.Types.Format.Srgba:
93-
case ImageFormat.Types.Format.Srgba64:
94-
case ImageFormat.Types.Format.Sbgra:
95-
return 4;
96-
case ImageFormat.Types.Format.Gray8:
97-
case ImageFormat.Types.Format.Gray16:
98-
return 1;
99-
case ImageFormat.Types.Format.Vec32F1:
100-
return 1;
101-
case ImageFormat.Types.Format.Vec32F2:
102-
return 2;
103-
case ImageFormat.Types.Format.Lab8:
104-
return 3;
105-
case ImageFormat.Types.Format.Ycbcr420P:
106-
case ImageFormat.Types.Format.Ycbcr420P10:
107-
case ImageFormat.Types.Format.Unknown:
108-
default:
109-
return 0;
110-
}
111-
}
112-
113-
/// <returns>
114-
/// The channel size for a <paramref name="format" />.
115-
/// If channels don't make sense in the <paramref name="format" />, returns <c>0</c>.
116-
/// </returns>
117-
/// <remarks>
118-
/// Unlike the original implementation, this API won't signal SIGABRT.
119-
/// </remarks>
120-
public static int ChannelSizeForFormat(ImageFormat.Types.Format format)
121-
{
122-
switch (format)
123-
{
124-
case ImageFormat.Types.Format.Srgb:
125-
case ImageFormat.Types.Format.Srgba:
126-
case ImageFormat.Types.Format.Sbgra:
127-
return sizeof(byte);
128-
case ImageFormat.Types.Format.Srgb48:
129-
case ImageFormat.Types.Format.Srgba64:
130-
return sizeof(ushort);
131-
case ImageFormat.Types.Format.Gray8:
132-
return sizeof(byte);
133-
case ImageFormat.Types.Format.Gray16:
134-
return sizeof(ushort);
135-
case ImageFormat.Types.Format.Vec32F1:
136-
case ImageFormat.Types.Format.Vec32F2:
137-
// sizeof float may be wrong since it's platform-dependent, but we assume that it's constant across all supported platforms.
138-
return sizeof(float);
139-
case ImageFormat.Types.Format.Lab8:
140-
return sizeof(byte);
141-
case ImageFormat.Types.Format.Ycbcr420P:
142-
case ImageFormat.Types.Format.Ycbcr420P10:
143-
case ImageFormat.Types.Format.Unknown:
144-
default:
145-
return 0;
146-
}
147-
}
148-
149-
/// <returns>
150-
/// The depth of each channel in bytes for a <paramref name="format" />.
151-
/// If channels don't make sense in the <paramref name="format" />, returns <c>0</c>.
152-
/// </returns>
153-
/// <remarks>
154-
/// Unlike the original implementation, this API won't signal SIGABRT.
155-
/// </remarks>
156-
public static int ByteDepthForFormat(ImageFormat.Types.Format format)
157-
{
158-
switch (format)
159-
{
160-
case ImageFormat.Types.Format.Srgb:
161-
case ImageFormat.Types.Format.Srgba:
162-
case ImageFormat.Types.Format.Sbgra:
163-
return 1;
164-
case ImageFormat.Types.Format.Srgb48:
165-
case ImageFormat.Types.Format.Srgba64:
166-
return 2;
167-
case ImageFormat.Types.Format.Gray8:
168-
return 1;
169-
case ImageFormat.Types.Format.Gray16:
170-
return 2;
171-
case ImageFormat.Types.Format.Vec32F1:
172-
case ImageFormat.Types.Format.Vec32F2:
173-
return 4;
174-
case ImageFormat.Types.Format.Lab8:
175-
return 1;
176-
case ImageFormat.Types.Format.Ycbcr420P:
177-
case ImageFormat.Types.Format.Ycbcr420P10:
178-
case ImageFormat.Types.Format.Unknown:
179-
default:
180-
return 0;
181-
}
182-
}
183-
18484
public bool IsEmpty()
18585
{
18686
return SafeNativeMethods.mp_ImageFrame__IsEmpty(mpPtr);
@@ -223,7 +123,7 @@ public int Height()
223123
/// </remarks>
224124
public int ChannelSize()
225125
{
226-
return ChannelSizeForFormat(Format());
126+
return Format().ChannelSize();
227127
}
228128

229129
/// <returns>
@@ -235,7 +135,7 @@ public int ChannelSize()
235135
/// </remarks>
236136
public int NumberOfChannels()
237137
{
238-
return NumberOfChannelsForFormat(Format());
138+
return Format().NumberOfChannels();
239139
}
240140

241141
/// <returns>
@@ -247,7 +147,7 @@ public int NumberOfChannels()
247147
/// </remarks>
248148
public int ByteDepth()
249149
{
250-
return ByteDepthForFormat(Format());
150+
return Format().ByteDepth();
251151
}
252152

253153
public int WidthStep()

Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/Experimental/TextureFrame.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,9 @@ public IntPtr GetNativeTexturePtr()
222222

223223
public Guid GetInstanceID() => _instanceId;
224224

225-
public ImageFrame BuildImageFrame() => new ImageFrame(imageFormat, width, height, 4 * width, GetRawTextureData<byte>());
225+
public ImageFrame BuildImageFrame() => new ImageFrame(imageFormat, _texture);
226226

227-
public Image BuildCPUImage() => new Image(imageFormat, width, height, 4 * width, GetRawTextureData<byte>());
227+
public Image BuildCPUImage() => new Image(imageFormat, _texture);
228228

229229
public GpuBuffer BuildGpuBuffer(GlContext glContext)
230230
{

0 commit comments

Comments
 (0)