Skip to content

Commit 88a8adb

Browse files
authored
Merge pull request #2030 from shimat/feature/2009-imgcodecs-coverage
imgcodecs: add Animation, ImageCollection, metadata I/O, imcount (#2009)
2 parents 3396c62 + 518b6ba commit 88a8adb

22 files changed

Lines changed: 2362 additions & 36 deletions

.github/copilot-instructions.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,20 @@ Place each submodule facade in its module folder as `Cv2.<Sub>.cs` (e.g. `Module
166166

167167
See `src/OpenCvSharpExtern/ximgproc_EdgeDrawing.h`, `src/OpenCvSharp/Modules/ximgproc/EdgeDrawing.cs` for a complete example covering: factory, OutputArray methods, std::vector methods, nested Params struct with bool fields, and VectorOfVec6d.
168168

169+
## Enum member naming
170+
171+
C++ enum members are `ALL_CAPS_WITH_UNDERSCORES` (e.g. `IMWRITE_JPEG_QUALITY`, `NORM_L2SQR`). When wrapping them as a C# enum, **default to PascalCase**, stripping the module/family prefix (`IMWRITE_JPEG_QUALITY``JpegQuality`). Keep the original casing (or a near-verbatim form) only when one of these narrow exceptions applies:
172+
173+
1. **The value itself is an unbreakable acronym/abbreviation, standing alone (nothing else glued onto it).** Test: read it aloud — do you spell out the letters (like an acronym) rather than pronounce it as a word? If so, PascalCasing it (`Exif`, `L2Sqr`) destroys the acronym for no benefit. Keep it verbatim (`EXIF`, `L2SQR`). Precedent: `NormTypes.INF`/`L1`/`L2SQR`, `ImageMetadataType.EXIF`/`XMP`/`ICCP`/`CICP`.
174+
2. **The value has no natural word boundaries — it's an opaque code, not a phrase.** Test: does inserting word breaks add any information, or does it just capitalize letters arbitrarily? If the latter, keep it verbatim. Precedent: `ColorConversionCodes.BGR2GRAY` (whole body kept verbatim, only the `COLOR_` prefix stripped), `FASTType.TYPE_5_8`.
175+
3. **The prefix identifies a specific vendor/backend and is semantically load-bearing.** Test: does stripping the prefix delete information a reader needs (which camera SDK/backend this property belongs to)? If so, keep the prefix verbatim; the suffix can still be PascalCased normally. Precedent: `VideoCaptureProperties`' `XI_`/`OPENNI_`/`PVAPI_`/`GIGA_`/`IOS_`-prefixed members.
176+
177+
When none of the three applies, PascalCase — don't keep a verbatim name "to be safe." The exceptions are narrow and should be justifiable by one of the tests above, not a default.
178+
179+
**Compounds win over exception 1.** The "standalone" qualifier in exception 1 matters: once an acronym is glued to another word/acronym to form one compound member name, PascalCase the whole compound rather than leaving the acronym in caps — an ALL-CAPS-then-lowercase transition mid-identifier (`TIFFResUnit`, `CCITTRle`) is harder to read than a clean compound (`TiffResUnit`, `CcittRle`). This is why the pre-existing `ImwriteFlags.TiffResUnit`/`JpegQuality`/`PngCompression`/`PamTupleType` PascalCase acronyms that would otherwise qualify for exception 1 in isolation — they're prefixes in a compound, not standalone values. Same reasoning covers `ImwriteTiffCompressionFlags.CcittRle`/`CcittFax3` and the standalone-but-left-PascalCase `Lzw`/`Jbig`/`Dcs`/`Rle` siblings in that same enum (and its `ImwriteEXRCompressionFlags`/`ImwriteHDRCompressionFlags` cousins) — treating every acronym-derived compression-scheme name as ordinary vocabulary, consistently within the enum, beats selectively all-capping only some of them.
180+
181+
**Enum type names are a separate question — mirror the C++ type identifier verbatim, don't run it through this heuristic.** OpenCV's own C++ type names are inconsistently cased across acronyms (`ImwriteJPEGSamplingFactorParams`, `ImwriteEXRTypeFlags`, `ImwritePNGFlags`, `ImwritePAMFlags`, `ImwriteWEBPLosslessMode`, `ImwriteHDRCompressionFlags`, `ImwriteBMPCompressionFlags`, `ImwriteGIFCompressionFlags` are capitalized, but `ImwriteTiffCompressionFlags`/`ImwriteTiffPredictorFlags`/`ImwriteTiffResolutionUnitFlags` use `Tiff`) — that inconsistency is inherited straight from `opencv2/imgcodecs.hpp`, not introduced on the C# side. Keep mirroring the C++ type name 1:1 regardless: it keeps the C# type grep-able against OpenCV's own headers/docs, which matters more than internal cosmetic consistency for a type name. This has always been this codebase's practice (`ImwriteEXRTypeFlags`/`ImwritePNGFlags`/`ImwritePAMFlags` pre-date this rule and already mirror C++ verbatim).
182+
169183
## Repository structure
170184

171185
OpenCvSharp has three layers:

src/OpenCvSharp/Cv2/Cv2_imgcodecs.cs

Lines changed: 412 additions & 25 deletions
Large diffs are not rendered by default.

src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_imgcodecs.cs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,52 @@ public static partial ExceptionStatus imgcodecs_imread(
2020
public static partial ExceptionStatus imgcodecs_imreadmulti(
2121
[MarshalAs(UnmanagedType.LPUTF8Str)] string fileName, IntPtr mats, int flags, out int returnValue);
2222

23+
// acpOk is 0 (and returnValue 0) on Windows when 'fileName' can't be represented in the process
24+
// ANSI code page; the managed caller retries via an ASCII-safe temp copy.
25+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
26+
public static partial ExceptionStatus imgcodecs_imreadmulti_range(
27+
[MarshalAs(UnmanagedType.LPUTF8Str)] string fileName, IntPtr mats, int start, int count, int flags, out int acpOk, out int returnValue);
28+
29+
// imcount (UTF-8 everywhere). On Windows, acpOk is 0 (and returnValue 0) when the path can't be
30+
// represented in the process ANSI code page; the managed caller retries via an ASCII-safe temp copy.
31+
32+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
33+
public static partial ExceptionStatus imgcodecs_imcount(
34+
[MarshalAs(UnmanagedType.LPUTF8Str)] string fileName, int flags, out int acpOk, out IntPtr returnValue);
35+
36+
// imreadWithMetadata / imwriteWithMetadata / imdecodeWithMetadata / imencodeWithMetadata
37+
38+
// acpOk/managed-retry contract: see imgcodecs_imreadmulti_range.
39+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
40+
public static partial ExceptionStatus imgcodecs_imreadWithMetadata(
41+
[MarshalAs(UnmanagedType.LPUTF8Str)] string fileName, IntPtr metadataTypes, IntPtr metadata, int flags, out int acpOk, out IntPtr returnValue);
42+
43+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
44+
public static partial ExceptionStatus imgcodecs_imwriteWithMetadata(
45+
[MarshalAs(UnmanagedType.LPUTF8Str)] string fileName, IntPtr img,
46+
[In] int[] metadataTypes, int metadataTypesLength, IntPtr metadata,
47+
[In] int[] @params, int paramsLength, out int acpOk, out int returnValue);
48+
49+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
50+
internal static partial ExceptionStatus imgcodecs_imdecodeWithMetadata(
51+
in InputArrayProxy buf, IntPtr metadataTypes, IntPtr metadata, int flags, out IntPtr returnValue);
52+
53+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
54+
internal static partial ExceptionStatus imgcodecs_imencodeWithMetadata(
55+
[MarshalAs(UnmanagedType.LPStr)] string ext, in InputArrayProxy img,
56+
[In] int[] metadataTypes, int metadataTypesLength, IntPtr metadata, IntPtr buf,
57+
[In] int[] @params, int paramsLength, out int returnValue);
58+
59+
// imdecodemulti / imencodemulti
60+
61+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
62+
internal static partial ExceptionStatus imgcodecs_imdecodemulti(
63+
in InputArrayProxy buf, int flags, IntPtr mats, Range range, out int returnValue);
64+
65+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
66+
public static partial ExceptionStatus imgcodecs_imencodemulti(
67+
[MarshalAs(UnmanagedType.LPStr)] string ext, IntPtr imgs, IntPtr buf, [In] int[] @params, int paramsLength, out int returnValue);
68+
2369
// imwrite (UTF-8 everywhere; the native side converts to a wide path on Windows so non-ANSI names work)
2470

2571
[LibraryImport(DllExtern, EntryPoint = "imgcodecs_imwrite"), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
@@ -61,6 +107,88 @@ internal static partial ExceptionStatus imgcodecs_imdecode_InputArray(
61107
internal static partial ExceptionStatus imgcodecs_imencode_vector(
62108
[MarshalAs(UnmanagedType.LPStr)] string ext, in InputArrayProxy img, IntPtr buf, [In] int[] @params, int paramsLength, out int returnValue);
63109

110+
// Animation
111+
112+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
113+
public static partial ExceptionStatus imgcodecs_Animation_new(int loopCount, Scalar bgColor, out IntPtr returnValue);
114+
115+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
116+
public static partial ExceptionStatus imgcodecs_Animation_delete(IntPtr obj);
117+
118+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
119+
public static partial ExceptionStatus imgcodecs_Animation_get_loop_count(IntPtr obj, out int returnValue);
120+
121+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
122+
public static partial ExceptionStatus imgcodecs_Animation_set_loop_count(IntPtr obj, int value);
123+
124+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
125+
public static partial ExceptionStatus imgcodecs_Animation_get_bgcolor(IntPtr obj, out Scalar returnValue);
126+
127+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
128+
public static partial ExceptionStatus imgcodecs_Animation_set_bgcolor(IntPtr obj, Scalar value);
129+
130+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
131+
public static partial ExceptionStatus imgcodecs_Animation_get_durations(IntPtr obj, IntPtr outVec);
132+
133+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
134+
public static partial ExceptionStatus imgcodecs_Animation_set_durations(IntPtr obj, [In] int[] data, int length);
135+
136+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
137+
public static partial ExceptionStatus imgcodecs_Animation_get_frames(IntPtr obj, IntPtr outVec);
138+
139+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
140+
public static partial ExceptionStatus imgcodecs_Animation_set_frames(IntPtr obj, IntPtr frames);
141+
142+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
143+
public static partial ExceptionStatus imgcodecs_Animation_get_still_image(IntPtr obj, out IntPtr returnValue);
144+
145+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
146+
public static partial ExceptionStatus imgcodecs_Animation_set_still_image(IntPtr obj, IntPtr image);
147+
148+
// imreadanimation / imdecodeanimation / imwriteanimation / imencodeanimation
149+
150+
// acpOk/managed-retry contract: see imgcodecs_imreadmulti_range.
151+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
152+
public static partial ExceptionStatus imgcodecs_imreadanimation(
153+
[MarshalAs(UnmanagedType.LPUTF8Str)] string fileName, IntPtr animation, int start, int count, out int acpOk, out int returnValue);
154+
155+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
156+
internal static partial ExceptionStatus imgcodecs_imdecodeanimation(
157+
in InputArrayProxy buf, IntPtr animation, int start, int count, out int returnValue);
158+
159+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
160+
public static partial ExceptionStatus imgcodecs_imwriteanimation(
161+
[MarshalAs(UnmanagedType.LPUTF8Str)] string fileName, IntPtr animation, [In] int[] @params, int paramsLength, out int acpOk, out int returnValue);
162+
163+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
164+
public static partial ExceptionStatus imgcodecs_imencodeanimation(
165+
[MarshalAs(UnmanagedType.LPStr)] string ext, IntPtr animation, IntPtr buf, [In] int[] @params, int paramsLength, out int returnValue);
166+
167+
// ImageCollection
168+
169+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
170+
public static partial ExceptionStatus imgcodecs_ImageCollection_new1(out IntPtr returnValue);
171+
172+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
173+
public static partial ExceptionStatus imgcodecs_ImageCollection_new2(
174+
[MarshalAs(UnmanagedType.LPUTF8Str)] string fileName, int flags, out IntPtr returnValue);
175+
176+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
177+
public static partial ExceptionStatus imgcodecs_ImageCollection_delete(IntPtr obj);
178+
179+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
180+
public static partial ExceptionStatus imgcodecs_ImageCollection_init(
181+
IntPtr obj, [MarshalAs(UnmanagedType.LPUTF8Str)] string fileName, int flags);
182+
183+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
184+
public static partial ExceptionStatus imgcodecs_ImageCollection_size(IntPtr obj, out IntPtr returnValue);
185+
186+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
187+
public static partial ExceptionStatus imgcodecs_ImageCollection_at(IntPtr obj, int index, out IntPtr returnValue);
188+
189+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
190+
public static partial ExceptionStatus imgcodecs_ImageCollection_releaseCache(IntPtr obj, int index);
191+
64192
// haveImageReader (UTF-8 everywhere; native probes via a wide path on Windows)
65193

66194
[LibraryImport(DllExtern, EntryPoint = "imgcodecs_haveImageReader"), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
using OpenCvSharp.Internal;
2+
using OpenCvSharp.Internal.Util;
3+
using OpenCvSharp.Internal.Vectors;
4+
5+
namespace OpenCvSharp;
6+
7+
/// <summary>
8+
/// Represents an animation with multiple frames.
9+
/// Stores and manages data for animated sequences such as those from animated formats (e.g., GIF, AVIF, APNG, WebP).
10+
/// It provides support for looping, background color settings, frame timing, and frame storage.
11+
/// </summary>
12+
public class Animation : CvObject
13+
{
14+
/// <summary>
15+
/// Constructs an Animation object with optional loop count and background color.
16+
/// </summary>
17+
/// <param name="loopCount">
18+
/// The number of times the animation should loop. 0 (default) indicates infinite looping.
19+
/// Negative values or values beyond 0xffff (65535) are reset to 0.
20+
/// </param>
21+
/// <param name="bgColor">Background color of the animation in BGR(A) format. Defaults to an empty color.</param>
22+
public Animation(int loopCount = 0, Scalar? bgColor = null)
23+
{
24+
NativeMethods.HandleException(
25+
NativeMethods.imgcodecs_Animation_new(loopCount, bgColor ?? Scalar.All(0), out var p));
26+
SetSafeHandle(new OpenCvPtrSafeHandle(p, ownsHandle: true,
27+
static h => NativeMethods.HandleException(NativeMethods.imgcodecs_Animation_delete(h))));
28+
}
29+
30+
/// <summary>
31+
/// Number of times the animation should loop. 0 means infinite looping.
32+
/// </summary>
33+
public int LoopCount
34+
{
35+
get
36+
{
37+
ThrowIfDisposed();
38+
NativeMethods.HandleException(
39+
NativeMethods.imgcodecs_Animation_get_loop_count(CvPtr, out var ret));
40+
GC.KeepAlive(this);
41+
return ret;
42+
}
43+
set
44+
{
45+
ThrowIfDisposed();
46+
NativeMethods.HandleException(
47+
NativeMethods.imgcodecs_Animation_set_loop_count(CvPtr, value));
48+
GC.KeepAlive(this);
49+
}
50+
}
51+
52+
/// <summary>
53+
/// Background color of the animation in BGRA format.
54+
/// </summary>
55+
public Scalar BgColor
56+
{
57+
get
58+
{
59+
ThrowIfDisposed();
60+
NativeMethods.HandleException(
61+
NativeMethods.imgcodecs_Animation_get_bgcolor(CvPtr, out var ret));
62+
GC.KeepAlive(this);
63+
return ret;
64+
}
65+
set
66+
{
67+
ThrowIfDisposed();
68+
NativeMethods.HandleException(
69+
NativeMethods.imgcodecs_Animation_set_bgcolor(CvPtr, value));
70+
GC.KeepAlive(this);
71+
}
72+
}
73+
74+
/// <summary>
75+
/// Duration for each frame in milliseconds.
76+
/// </summary>
77+
public int[] Durations
78+
{
79+
get
80+
{
81+
ThrowIfDisposed();
82+
using var vec = new StdVector<int>();
83+
NativeMethods.HandleException(
84+
NativeMethods.imgcodecs_Animation_get_durations(CvPtr, vec.CvPtr));
85+
GC.KeepAlive(this);
86+
return vec.ToArray();
87+
}
88+
set
89+
{
90+
ThrowIfDisposed();
91+
ArgumentNullException.ThrowIfNull(value);
92+
NativeMethods.HandleException(
93+
NativeMethods.imgcodecs_Animation_set_durations(CvPtr, value, value.Length));
94+
GC.KeepAlive(this);
95+
}
96+
}
97+
98+
/// <summary>
99+
/// Frames of the animation. The getter returns freshly-copied <see cref="Mat"/> headers that the
100+
/// caller owns and is responsible for disposing.
101+
/// </summary>
102+
public Mat[] Frames
103+
{
104+
get
105+
{
106+
ThrowIfDisposed();
107+
using var vec = new VectorOfMat();
108+
NativeMethods.HandleException(
109+
NativeMethods.imgcodecs_Animation_get_frames(CvPtr, vec.CvPtr));
110+
GC.KeepAlive(this);
111+
return vec.ToArray();
112+
}
113+
set
114+
{
115+
ThrowIfDisposed();
116+
ArgumentNullException.ThrowIfNull(value);
117+
using var vec = new VectorOfMat(value);
118+
NativeMethods.HandleException(
119+
NativeMethods.imgcodecs_Animation_set_frames(CvPtr, vec.CvPtr));
120+
GC.KeepAlive(this);
121+
GC.KeepAlive(value);
122+
}
123+
}
124+
125+
/// <summary>
126+
/// Image that can be used for the format in addition to the animation, or if animation is not supported
127+
/// in the reader (like in PNG). The getter returns a freshly-copied <see cref="Mat"/> header that the
128+
/// caller owns and is responsible for disposing.
129+
/// </summary>
130+
public Mat StillImage
131+
{
132+
get
133+
{
134+
ThrowIfDisposed();
135+
NativeMethods.HandleException(
136+
NativeMethods.imgcodecs_Animation_get_still_image(CvPtr, out var ret));
137+
GC.KeepAlive(this);
138+
return new Mat(ret);
139+
}
140+
set
141+
{
142+
ThrowIfDisposed();
143+
ArgumentNullException.ThrowIfNull(value);
144+
NativeMethods.HandleException(
145+
NativeMethods.imgcodecs_Animation_set_still_image(CvPtr, value.CvPtr));
146+
GC.KeepAlive(this);
147+
GC.KeepAlive(value);
148+
}
149+
}
150+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// ReSharper disable InconsistentNaming
2+
3+
namespace OpenCvSharp;
4+
5+
/// <summary>
6+
/// Type of metadata chunk stored in / retrieved from an image file by the *WithMetadata family of functions.
7+
/// </summary>
8+
public enum ImageMetadataType
9+
{
10+
/// <summary>
11+
/// Used when metadata type is unrecognized or not set.
12+
/// </summary>
13+
Unknown = -1,
14+
15+
/// <summary>
16+
/// EXIF metadata (e.g., camera info, GPS, orientation).
17+
/// </summary>
18+
EXIF = 0,
19+
20+
/// <summary>
21+
/// XMP metadata (eXtensible Metadata Platform - Adobe format).
22+
/// </summary>
23+
XMP = 1,
24+
25+
/// <summary>
26+
/// ICC Profile (color profile for color management).
27+
/// </summary>
28+
ICCP = 2,
29+
30+
/// <summary>
31+
/// cICP Profile (video signal type).
32+
/// </summary>
33+
CICP = 3
34+
}

src/OpenCvSharp/Modules/imgcodecs/Enum/ImreadModes.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,10 @@ public enum ImreadModes
7272
/// <summary>
7373
/// If set, do not rotate the image according to EXIF's orientation flag.
7474
/// </summary>
75-
IgnoreOrientation = 128
75+
IgnoreOrientation = 128,
76+
77+
/// <summary>
78+
/// If set, always convert image to the 3 channel RGB color image.
79+
/// </summary>
80+
ColorRgb = 256
7681
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace OpenCvSharp;
2+
3+
/// <summary>
4+
/// Imwrite BMP specific values for the IMWRITE_BMP_COMPRESSION parameter key.
5+
/// </summary>
6+
public enum ImwriteBMPCompressionFlags
7+
{
8+
/// <summary>
9+
/// Use BI_RGB. OpenCV v4.12.0 or before supports encoding with this compression only.
10+
/// </summary>
11+
Rgb = 0,
12+
13+
/// <summary>
14+
/// Use BI_BITFIELDS. OpenCV v4.13.0 or later can support encoding with this compression. (only for 32 BPP images)
15+
/// </summary>
16+
Bitfields = 3
17+
}

0 commit comments

Comments
 (0)