Skip to content

Commit e0b5550

Browse files
committed
more disposables and tidying, bump version
1 parent f3b9457 commit e0b5550

File tree

8 files changed

+75
-61
lines changed

8 files changed

+75
-61
lines changed

src/MagicScaler/Core/PixelFormats.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Collections.ObjectModel;
55

66
using PhotoSauce.MagicScaler.Interop;
7-
using System.Runtime.InteropServices;
87

98
namespace PhotoSauce.MagicScaler
109
{
@@ -258,15 +257,17 @@ static PixelFormat()
258257
[Bgrx128BppLinearFloat.FormatGuid] = Bgrx128BppLinearFloat
259258
};
260259

261-
uint fet = 10u;
262-
var oar = new object[fet];
263-
var cen = Wic.Factory.CreateComponentEnumerator(WICComponentType.WICPixelFormat, WICComponentEnumerateOptions.WICComponentEnumerateDefault);
260+
uint count = 10u;
261+
var formats = new object[count];
262+
263+
using (var cenum = new ComHandle<IEnumUnknown>(Wic.Factory.CreateComponentEnumerator(WICComponentType.WICPixelFormat, WICComponentEnumerateOptions.WICComponentEnumerateDefault)))
264264
do
265265
{
266-
fet = cen.Next(fet, oar);
267-
for (int i = 0; i < fet; i++)
266+
count = cenum.ComObject.Next(count, formats);
267+
for (int i = 0; i < count; i++)
268+
using (var pixh = new ComHandle<IWICPixelFormatInfo2>(formats[i]))
268269
{
269-
var pix = oar[i] as IWICPixelFormatInfo2;
270+
var pix = pixh.ComObject;
270271
uint cch = pix.GetFriendlyName(0, null);
271272
var sbn = new StringBuilder((int)cch);
272273
pix.GetFriendlyName(cch, sbn);
@@ -289,16 +290,12 @@ static PixelFormat()
289290
PixelAlphaRepresentation.None
290291
};
291292

292-
Marshal.ReleaseComObject(pix);
293-
294293
if (fmt.ColorRepresentation == PixelColorRepresentation.Grey || fmt.ColorRepresentation == PixelColorRepresentation.Bgr || fmt.ColorRepresentation == PixelColorRepresentation.Rgb)
295294
fmt.Colorspace = fmt.NumericRepresentation == PixelNumericRepresentation.Fixed || fmt.NumericRepresentation == PixelNumericRepresentation.Float ? PixelColorspace.scRgb : PixelColorspace.sRgb;
296295

297296
dic.Add(fmt.FormatGuid, fmt);
298297
}
299-
} while (fet > 0);
300-
301-
Marshal.ReleaseComObject(cen);
298+
} while (count > 0);
302299

303300
Cache = new ReadOnlyDictionary<Guid, PixelFormat>(dic);
304301
}

src/MagicScaler/Interop/PropVariant.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
using System;
1717
using System.Linq;
18+
using System.Buffers;
1819
using System.Collections;
1920
using System.Runtime.InteropServices;
2021
using System.Runtime.CompilerServices;
@@ -136,7 +137,7 @@ public bool Equals(PropVariant other)
136137
if ((Value is Array) != (other.Value is Array))
137138
return false;
138139

139-
if ((Value is Array))
140+
if (Value is Array)
140141
return ((IEnumerable)Value).Cast<object>().SequenceEqual(((IEnumerable)other.Value).Cast<object>());
141142

142143
return Equals(Value, other.Value);
@@ -145,9 +146,9 @@ public bool Equals(PropVariant other)
145146
public static bool operator ==(PropVariant left, PropVariant right) => left?.Equals(right) ?? ReferenceEquals(left, right);
146147
public static bool operator !=(PropVariant left, PropVariant right) => !(left == right);
147148

148-
public override bool Equals(object o) => Equals(o as PropVariant);
149+
public override bool Equals(object o) => o is PropVariant other && Equals(other);
149150
public override int GetHashCode() => Value?.GetHashCode() ?? 0;
150-
public override string ToString() => $"{(UnmanagedType & ~VarEnum.VT_VECTOR)}: {(Value is Array ? string.Join(" ", (Array)Value) : Value)}";
151+
public override string ToString() => $"{UnmanagedType & ~VarEnum.VT_VECTOR}: {(Value is Array ? string.Join(" ", (Array)Value) : Value)}";
151152

152153
internal sealed class Marshaler : ICustomMarshaler
153154
{
@@ -244,8 +245,8 @@ unsafe public IntPtr MarshalManagedToNative(object o)
244245
else
245246
{
246247
var gch = GCHandle.Alloc(a, GCHandleType.Pinned);
247-
Unsafe.CopyBlockUnaligned(pNativeBuffer.ToPointer(), Marshal.UnsafeAddrOfPinnedArrayElement(a, 0).ToPointer(), (uint)bufflen);
248-
gch.Free();
248+
using (var mh = new MemoryHandle(Marshal.UnsafeAddrOfPinnedArrayElement(a, 0).ToPointer(), gch))
249+
Unsafe.CopyBlock(pNativeBuffer.ToPointer(), mh.Pointer, (uint)bufflen);
249250
}
250251

251252
var upv = new UnmanagedPropVariant { vt = unmanagedType };

src/MagicScaler/Magic/PadTransform.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ void IPixelTransformInternal.Init(WicProcessingContext ctx)
104104
{
105105
if (!padRect.IsEmpty)
106106
{
107+
MagicTransforms.AddExternalFormatConverter(ctx);
108+
107109
var innerRect = new Rectangle(padRect.Left, padRect.Top, (int)ctx.Source.Width, (int)ctx.Source.Height);
108110
var outerRect = Rectangle.FromLTRB(0, 0, innerRect.Right + padRect.Right, innerRect.Bottom + padRect.Bottom);
109111
ctx.Source = new PadTransformInternal(ctx.Source, padColor, innerRect, outerRect);

src/MagicScaler/MagicScaler.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
99
<LangVersion>latest</LangVersion>
1010
<Features>strict</Features>
11-
<VersionPrefix>0.9.0</VersionPrefix>
11+
<VersionPrefix>0.9.1</VersionPrefix>
1212
<Authors>Clinton Ingram</Authors>
1313
<Company>PhotoSauce</Company>
1414
<Product>MagicScaler</Product>
1515
<Copyright>Copyright © 2015-2018 Clinton Ingram</Copyright>
1616
<RepositoryType>git</RepositoryType>
1717
<RepositoryUrl>https://github.com/saucecontrol/PhotoSauce</RepositoryUrl>
18-
<PackageIconUrl>http://photosauce.net/icon64x64.png</PackageIconUrl>
19-
<PackageProjectUrl>http://photosauce.net/</PackageProjectUrl>
18+
<PackageIconUrl>https://photosauce.net/icon64x64.png</PackageIconUrl>
19+
<PackageProjectUrl>https://photosauce.net/</PackageProjectUrl>
2020
<PackageLicenseUrl>https://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
2121
<PackageReleaseNotes>See https://github.com/saucecontrol/PhotoSauce/releases</PackageReleaseNotes>
2222
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace PhotoSauce.MagicScaler.Interop
5+
{
6+
internal readonly struct ComHandle<T> : IDisposable where T : class
7+
{
8+
public T ComObject { get; }
9+
10+
public ComHandle(object obj)
11+
{
12+
if (!Marshal.IsComObject(obj)) throw new ArgumentException("Must be a COM object", nameof(obj));
13+
if (!(obj is T com)) throw new ArgumentException("Interface not supported: " + typeof(T).Name, nameof(obj));
14+
15+
ComObject = com;
16+
}
17+
18+
public void Dispose()
19+
{
20+
if (!(ComObject is null) && Marshal.IsComObject(ComObject))
21+
Marshal.ReleaseComObject(ComObject);
22+
}
23+
}
24+
}

src/MagicScaler/Utilities/StreamAsIStream.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,10 @@ private class StreamAsIStream : IStream
1212
{
1313
private readonly Stream stream;
1414

15-
internal StreamAsIStream(Stream backingStream)
16-
{
15+
internal StreamAsIStream(Stream backingStream) =>
1716
stream = backingStream ?? throw new ArgumentNullException(nameof(backingStream));
18-
}
1917

20-
void IStream.Read(byte[] pv, int cb, IntPtr pcbRead)
21-
{
22-
Marshal.WriteInt32(pcbRead, stream.Read(pv, 0, cb));
23-
}
18+
void IStream.Read(byte[] pv, int cb, IntPtr pcbRead) => Marshal.WriteInt32(pcbRead, stream.Read(pv, 0, cb));
2419

2520
void IStream.Write(byte[] pv, int cb, IntPtr pcbWritten)
2621
{
@@ -38,10 +33,8 @@ void IStream.Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
3833
Marshal.WriteInt64(plibNewPosition, pos);
3934
}
4035

41-
void IStream.Stat(out STATSTG pstatstg, int grfStatFlag)
42-
{
36+
void IStream.Stat(out STATSTG pstatstg, int grfStatFlag) =>
4337
pstatstg = new STATSTG { cbSize = stream.Length, type = 2 /*STGTY_STREAM*/ };
44-
}
4538

4639
void IStream.SetSize(long libNewSize) => stream.SetLength(libNewSize);
4740

src/MagicScaler/Utilities/WinCodecExtensions.cs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,26 @@ internal static class Wic
99
{
1010
private static IWICColorContext getDefaultColorContext(Guid pixelFormat)
1111
{
12-
var pfi = Factory.CreateComponentInfo(pixelFormat) as IWICPixelFormatInfo;
13-
var cc = pfi.GetColorContext();
14-
Marshal.ReleaseComObject(pfi);
15-
16-
return cc;
12+
using (var pfi = new ComHandle<IWICPixelFormatInfo>(Factory.CreateComponentInfo(pixelFormat)))
13+
return pfi.ComObject.GetColorContext();
1714
}
1815

1916
private static IWICColorContext getResourceColorContext(string name)
2017
{
2118
string resName = nameof(PhotoSauce) + "." + nameof(MagicScaler) + ".Resources." + name;
22-
var asm = typeof(IWICColorContext).GetTypeInfo().Assembly;
23-
using (var stm = asm.GetManifestResourceStream(resName))
19+
using (var stm = typeof(Wic).GetTypeInfo().Assembly.GetManifestResourceStream(resName))
20+
using (var buff = MemoryPool<byte>.Shared.Rent((int)stm.Length))
2421
{
25-
var cc = Factory.CreateColorContext();
26-
27-
byte[] prof = ArrayPool<byte>.Shared.Rent((int)stm.Length);
28-
stm.Read(prof, 0, (int)stm.Length);
29-
cc.InitializeFromMemory(prof, (uint)stm.Length);
30-
ArrayPool<byte>.Shared.Return(prof);
22+
MemoryMarshal.TryGetArray(buff.Memory.Slice(0, (int)stm.Length), out ArraySegment<byte> cca);
23+
stm.Read(cca.Array, cca.Offset, cca.Count);
3124

25+
var cc = Factory.CreateColorContext();
26+
cc.InitializeFromMemory(cca.Array, (uint)cca.Count);
3227
return cc;
3328
}
3429
}
3530

36-
public static readonly IWICImagingFactory Factory = new WICImagingFactory2() as IWICImagingFactory;
31+
public static readonly IWICImagingFactory Factory = new WICImagingFactory2() as IWICImagingFactory ?? throw new PlatformNotSupportedException();
3732

3833
public static readonly Lazy<IWICColorContext> CmykContext = new Lazy<IWICColorContext>(() => getDefaultColorContext(Consts.GUID_WICPixelFormat32bppCMYK));
3934
public static readonly Lazy<IWICColorContext> SrgbContext = new Lazy<IWICColorContext>(() => getResourceColorContext("sRGB-v4.icc"));

src/MagicScaler/WIC/WicTransforms.cs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -150,28 +150,30 @@ public static void AddMetadataReader(WicProcessingContext ctx, bool basicOnly =
150150
var cct = cc.GetType();
151151
if (cct == WICColorContextType.WICColorContextProfile)
152152
{
153-
uint ccs = cc.GetProfileBytes(0, null);
153+
int ccs = (int)cc.GetProfileBytes(0, null);
154154

155155
// don't try to read giant profiles. 4MiB is more than enough
156-
if (ccs > (1024 * 1024 * 4))
156+
if ((uint)ccs > (1024 * 1024 * 4))
157157
continue;
158158

159-
var ccb = ArrayPool<byte>.Shared.Rent((int)ccs);
160-
cc.GetProfileBytes(ccs, ccb);
161-
var cpi = ColorProfile.Cache.GetOrAdd(new ArraySegment<byte>(ccb, 0, (int)ccs));
162-
ArrayPool<byte>.Shared.Return(ccb);
163-
164-
// match only color profiles that match our intended use. if we have a standard sRGB profile, don't save it; we don't need to convert
165-
if (cpi.IsValid && (
166-
(cpi.DataColorSpace == ColorProfile.ProfileColorSpace.Rgb && (fmt.ColorRepresentation == PixelColorRepresentation.Bgr || fmt.ColorRepresentation == PixelColorRepresentation.Rgb) && !cpi.IsSrgb)
167-
|| (cpi.DataColorSpace == ColorProfile.ProfileColorSpace.Grey && fmt.ColorRepresentation == PixelColorRepresentation.Grey && !cpi.IsSrgbCurve)
168-
|| (cpi.DataColorSpace == ColorProfile.ProfileColorSpace.Cmyk && fmt.ColorRepresentation == PixelColorRepresentation.Cmyk)
169-
))
159+
using (var ccb = MemoryPool<byte>.Shared.Rent(ccs))
170160
{
171-
profile = cc;
172-
if (cpi.IsRgbMatrix || cpi.IsGreyTrc)
173-
ctx.SourceColorProfile = cpi;
174-
break;
161+
MemoryMarshal.TryGetArray(ccb.Memory.Slice(0, ccs), out ArraySegment<byte> cca);
162+
cc.GetProfileBytes((uint)cca.Count, cca.Array);
163+
var cpi = ColorProfile.Cache.GetOrAdd(cca);
164+
165+
// match only color profiles that match our intended use. if we have a standard sRGB profile, don't save it; we don't need to convert
166+
if (cpi.IsValid && (
167+
(cpi.DataColorSpace == ColorProfile.ProfileColorSpace.Rgb && (fmt.ColorRepresentation == PixelColorRepresentation.Bgr || fmt.ColorRepresentation == PixelColorRepresentation.Rgb) && !cpi.IsSrgb)
168+
|| (cpi.DataColorSpace == ColorProfile.ProfileColorSpace.Grey && fmt.ColorRepresentation == PixelColorRepresentation.Grey && !cpi.IsSrgbCurve)
169+
|| (cpi.DataColorSpace == ColorProfile.ProfileColorSpace.Cmyk && fmt.ColorRepresentation == PixelColorRepresentation.Cmyk)
170+
))
171+
{
172+
profile = cc;
173+
if (cpi.IsRgbMatrix || cpi.IsGreyTrc)
174+
ctx.SourceColorProfile = cpi;
175+
break;
176+
}
175177
}
176178
}
177179
else if (cct == WICColorContextType.WICColorContextExifColorSpace && cc.GetExifColorSpace() == ExifColorSpace.AdobeRGB)

0 commit comments

Comments
 (0)