public static IWICColorContext[] GetColorContexts(this IWICBitmapDecoder bitmapDecoder) { bitmapDecoder.GetColorContexts(0, null, out int length); var colorContexts = new IWICColorContext[length]; if (length > 0) { bitmapDecoder.GetColorContexts(length, colorContexts, out length); } return(colorContexts); }
void CheckGetColorContexts(MainForm form, DataEntry[] de, Func <uint, IWICColorContext[], uint> method) { IWICColorContext[] contexts = null; IWICImagingFactory factory = new WICImagingFactory() as IWICImagingFactory; try { try { contexts = new IWICColorContext[method(0, null)]; } catch (Exception e) { form.CheckHRESULT(this, WinCodecError.WINCODEC_ERR_UNSUPPORTEDOPERATION, e, "0, NULL", de); return; } if (contexts.Length > 0) { for (int i = 0; i < contexts.Length; i++) { contexts[i] = factory.CreateColorContext(); } try { method((uint)contexts.Length, contexts); int index = 0; foreach (IWICColorContext c in contexts) { if (c == null) { form.Add(this, method.ToString(Resources._0_NULLItem), de, new DataEntry(Resources.Index, index)); } index++; } } catch (Exception e) { form.Add(this, method.ToString(Resources._0_Failed), de, new DataEntry(e)); } } } finally { contexts.ReleaseComObject(); factory.ReleaseComObject(); } }
public static IWICColorContext[] GetColorContexts(this IWICBitmapFrameDecode bitmapFrameDecode) { var wic = new WICImagingFactory(); bitmapFrameDecode.GetColorContexts(0, null, out int length); var colorContexts = new IWICColorContext[length]; if (length > 0) { for (int i = 0; i < length; i++) { colorContexts[i] = wic.CreateColorContext(); } bitmapFrameDecode.GetColorContexts(length, colorContexts, out _); } return(colorContexts); }
protected override bool ProcessEncoder(MainForm form, IWICBitmapEncoder encoder, object tag) { IWICImagingFactory factory = (IWICImagingFactory) new WICImagingFactory(); IWICBitmap bitmap = factory.CreateBitmap(16, 16, Consts.GUID_WICPixelFormat32bppBGRA, WICBitmapCreateCacheOption.WICBitmapCacheOnLoad); IWICPalette palette = factory.CreatePalette(); palette.InitializePredefined(WICBitmapPaletteType.WICBitmapPaletteTypeFixedBW, false); IWICColorContext context = factory.CreateColorContext(); context.InitializeFromExifColorSpace(ExifColorSpace.sRGB); ComponentInfoHelper.CheckEquals <IWICBitmapEncoderInfo>(form, encoder.GetEncoderInfo, this, Extensions.CompareInfos); Check(form, encoder.SetPalette, palette); Check(form, encoder.SetThumbnail, bitmap); Check(form, encoder.SetPreview, bitmap); try { encoder.SetColorContexts(1, new IWICColorContext[] { context }); } catch (Exception e) { form.CheckHRESULT(this, WinCodecError.WINCODEC_ERR_UNSUPPORTEDOPERATION, e); } try { encoder.Commit(); form.Add(this, string.Format(CultureInfo.CurrentUICulture, Resources._0_ShouldFail, "IWICBitmapEncoder::Commit(...)"), new DataEntry(Resources.FrameCount, 0)); } catch (Exception e) { form.CheckHRESULT(this, WinCodecError.WINCODEC_ERR_FRAMEMISSING, e, new DataEntry(Resources.FrameCount, 0)); } palette.ReleaseComObject(); bitmap.ReleaseComObject(); factory.ReleaseComObject(); context.ReleaseComObject(); return(base.ProcessEncoder(form, encoder, tag)); }
public static void InitializeFromMemory(this IWICColorContext colorContext, byte[] pbBuffer) { colorContext.InitializeFromMemory(pbBuffer, pbBuffer.Length); }
public static byte[] GetProfileBytes(this IWICColorContext colorContext) { FetchIntoBuffer <byte> fetcher = colorContext.GetProfileBytes; return(fetcher.FetchArray()); }
public void GetColorContexts(uint cCount, ref IWICColorContext ppIColorContexts, out uint pcActualCount) { Log.Trace("GetColorContexts called"); pcActualCount = 0; }
public WicMetadataReader(WicTransform prev, bool basicOnly = false) : base(prev) { if (Context.PixelFormat.NumericRepresentation == PixelNumericRepresentation.Indexed) { var pal = AddRef(Wic.CreatePalette()); Frame.CopyPalette(pal); Context.HasAlpha = pal.HasAlpha(); Context.IsGreyscale = pal.IsGrayscale(); } else { Context.HasAlpha = Context.PixelFormat.AlphaRepresentation != PixelAlphaRepresentation.None; Context.IsGreyscale = Context.PixelFormat.ColorRepresentation == PixelColorRepresentation.Grey; } #if NET46 if (Frame.TryGetMetadataQueryReader(out var metareader)) { AddRef(metareader); // Exif orientation if (metareader.TryGetMetadataByName("System.Photo.Orientation", out var ovar)) { ushort orientation = 1; if (ovar.UnmanagedType == VarEnum.VT_UI2) { orientation = (ushort)ovar.Value; } var opt = WICBitmapTransformOptions.WICBitmapTransformRotate0; if (orientation == 3 || orientation == 4) { opt = WICBitmapTransformOptions.WICBitmapTransformRotate180; } else if (orientation == 6 || orientation == 7) { opt = WICBitmapTransformOptions.WICBitmapTransformRotate90; } else if (orientation == 5 || orientation == 8) { opt = WICBitmapTransformOptions.WICBitmapTransformRotate270; } if (orientation == 2 || orientation == 4 || orientation == 5 || orientation == 7) { opt |= WICBitmapTransformOptions.WICBitmapTransformFlipHorizontal; } Context.TransformOptions = opt; } if (basicOnly) { return; } // other requested properties var propdic = new Dictionary <string, PropVariant>(); foreach (string prop in Context.Settings.MetadataNames ?? Enumerable.Empty <string>()) { if (metareader.TryGetMetadataByName(prop, out var pvar) && pvar.Value != null) { propdic[prop] = pvar; } } Context.Metadata = propdic; } #endif // ICC profiles //http://ninedegreesbelow.com/photography/embedded-color-space-information.html uint ccc = Frame.GetColorContextCount(); var profiles = new IWICColorContext[ccc]; var profile = default(IWICColorContext); if (ccc > 0) { for (int i = 0; i < ccc; i++) { profiles[i] = AddRef(Wic.CreateColorContext()); } Frame.GetColorContexts(ccc, profiles); } foreach (var cc in profiles) { var cct = cc.GetType(); if (cct == WICColorContextType.WICColorContextProfile) { uint ccs = cc.GetProfileBytes(0, null); var ccb = ArrayPool <byte> .Shared.Rent((int)ccs); cc.GetProfileBytes(ccs, ccb); var cp = new ColorProfileInfo(new ArraySegment <byte>(ccb, 0, (int)ccs)); ArrayPool <byte> .Shared.Return(ccb); // 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 if (cp.IsValid && ((cp.IsDisplayRgb && !cp.IsStandardSrgb) || (cp.IsCmyk && Context.PixelFormat.ColorRepresentation == PixelColorRepresentation.Cmyk) /* || (Context.IsGreyscale && cp.DataColorSpace == "GRAY") */)) { profile = cc; break; } } else if (cct == WICColorContextType.WICColorContextExifColorSpace && cc.GetExifColorSpace() == ExifColorSpace.AdobeRGB) { profile = cc; break; } } Context.SourceColorContext = profile ?? (Context.PixelFormat.ColorRepresentation == PixelColorRepresentation.Cmyk ? cmykProfile.Value : null); Context.DestColorContext = srgbProfile.Value; }
public static void AddMetadataReader(WicProcessingContext ctx, bool basicOnly = false) { if (ctx.DecoderFrame.Frame == null) { return; } if (ctx.DecoderFrame.Frame.TryGetMetadataQueryReader(out var metareader)) { ctx.AddRef(metareader); // Exif orientation if (metareader.TryGetMetadataByName("System.Photo.Orientation", out var pv)) { #pragma warning disable 0618 // VarEnum is obsolete if (pv.UnmanagedType == VarEnum.VT_UI2) { ctx.DecoderFrame.ExifOrientation = (Orientation)Math.Min(Math.Max((ushort)Orientation.Normal, (ushort)pv.Value), (ushort)Orientation.Rotate270); } #pragma warning restore 0618 var opt = ctx.DecoderFrame.ExifOrientation.ToWicTransformOptions(); if (ctx.DecoderFrame.SupportsPlanarPipeline && opt != WICBitmapTransformOptions.WICBitmapTransformRotate0 && ctx.DecoderFrame.Frame is IWICPlanarBitmapSourceTransform ptrans) { uint pw = 1, ph = 1; var pdesc = new WICBitmapPlaneDescription[2]; var pfmts = new[] { Consts.GUID_WICPixelFormat8bppY, Consts.GUID_WICPixelFormat16bppCbCr }; ctx.DecoderFrame.SupportsPlanarPipeline = ptrans.DoesSupportTransform(ref pw, ref ph, opt, WICPlanarOptions.WICPlanarOptionsDefault, pfmts, pdesc, 2); } } if (basicOnly) { return; } // other requested properties var propdic = new Dictionary <string, PropVariant>(); foreach (string prop in ctx.Settings.MetadataNames ?? Enumerable.Empty <string>()) { if (metareader.TryGetMetadataByName(prop, out var pvar) && pvar.Value != null) { propdic[prop] = pvar; } } ctx.DecoderFrame.Metadata = propdic; } if (basicOnly) { return; } // ICC profiles //http://ninedegreesbelow.com/photography/embedded-color-space-information.html uint ccc = ctx.DecoderFrame.Frame.GetColorContextCount(); var profiles = new IWICColorContext[ccc]; var profile = default(IWICColorContext); if (ccc > 0) { for (int i = 0; i < ccc; i++) { profiles[i] = ctx.AddRef(Wic.Factory.CreateColorContext()); } ctx.DecoderFrame.Frame.GetColorContexts(ccc, profiles); } foreach (var cc in profiles) { var cct = cc.GetType(); if (cct == WICColorContextType.WICColorContextProfile) { uint ccs = cc.GetProfileBytes(0, null); var ccb = ArrayPool <byte> .Shared.Rent((int)ccs); cc.GetProfileBytes(ccs, ccb); var cp = new ColorProfileInfo(new ArraySegment <byte>(ccb, 0, (int)ccs)); ArrayPool <byte> .Shared.Return(ccb); // 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 if (cp.IsValid && ((cp.IsDisplayRgb && !cp.IsStandardSrgb) || (cp.IsCmyk && ctx.Source.Format.ColorRepresentation == PixelColorRepresentation.Cmyk) /* || (Context.IsGreyscale && cp.DataColorSpace == "GRAY") */)) { profile = cc; break; } } else if (cct == WICColorContextType.WICColorContextExifColorSpace && cc.GetExifColorSpace() == ExifColorSpace.AdobeRGB) { profile = cc; break; } } ctx.SourceColorContext = profile ?? (ctx.Source.Format.ColorRepresentation == PixelColorRepresentation.Cmyk ? cmykProfile.Value : null); ctx.DestColorContext = srgbProfile.Value; }
void CheckGetColorContexts(MainForm form, DataEntry[] de, Func<uint, IWICColorContext[], uint> method) { IWICColorContext[] contexts = null; IWICImagingFactory factory = new WICImagingFactory() as IWICImagingFactory; try { try { contexts = new IWICColorContext[method(0, null)]; } catch (Exception e) { form.CheckHRESULT(this, WinCodecError.WINCODEC_ERR_UNSUPPORTEDOPERATION, e, "0, NULL", de); return; } if (contexts.Length > 0) { for (int i = 0; i < contexts.Length; i++) { contexts[i] = factory.CreateColorContext(); } try { method((uint)contexts.Length, contexts); int index = 0; foreach (IWICColorContext c in contexts) { if (c == null) { form.Add(this, method.ToString(Resources._0_NULLItem), de, new DataEntry(Resources.Index, index)); } index++; } } catch (Exception e) { form.Add(this, method.ToString(Resources._0_Failed), de, new DataEntry(e)); } } } finally { contexts.ReleaseComObject(); factory.ReleaseComObject(); } }
public WicMetadataReader(WicTransform prev, bool basicOnly = false) : base(prev) { var pfi = AddRef(Wic.CreateComponentInfo(Context.PixelFormat)) as IWICPixelFormatInfo2; if (pfi.GetNumericRepresentation() == WICPixelFormatNumericRepresentation.WICPixelFormatNumericRepresentationIndexed) { var pal = AddRef(Wic.CreatePalette()); Frame.CopyPalette(pal); Context.HasAlpha = pal.HasAlpha(); Context.IsGreyscale = pal.IsGrayscale(); } else { uint chans = pfi.GetChannelCount(); bool trans = pfi.SupportsTransparency(); Context.HasAlpha = trans; Context.IsGreyscale = chans == 1u; Context.IsCmyk = (chans == 4u && !trans) || (chans == 5u && trans); } var metareader = Frame.GetMetadataQueryReaderNoThrow(); if (metareader != null) { AddRef(metareader); // Exif orientation if (metareader.HasMetadataName("System.Photo.Orientation")) { ushort orientation = 1; var ovar = new PropVariant(); metareader.GetMetadataByName("System.Photo.Orientation", ovar); if (ovar.UnmanagedType == VarEnum.VT_UI2) { orientation = (ushort)ovar.Value; } var opt = WICBitmapTransformOptions.WICBitmapTransformRotate0; if (orientation == 3 || orientation == 4) { opt = WICBitmapTransformOptions.WICBitmapTransformRotate180; } else if (orientation == 6 || orientation == 7) { opt = WICBitmapTransformOptions.WICBitmapTransformRotate90; } else if (orientation == 5 || orientation == 8) { opt = WICBitmapTransformOptions.WICBitmapTransformRotate270; } if (orientation == 2 || orientation == 4 || orientation == 5 || orientation == 7) { opt |= WICBitmapTransformOptions.WICBitmapTransformFlipHorizontal; } Context.TransformOptions = opt; } if (basicOnly) { return; } // other requested properties var propdic = new Dictionary <string, PropVariant>(); foreach (string prop in Context.Settings.MetadataNames ?? Enumerable.Empty <string>()) { if (metareader.HasMetadataName(prop)) { var pvar = new PropVariant(); metareader.GetMetadataByName(prop, pvar); if (pvar.Value != null) { propdic[prop] = pvar; } } } Context.Metadata = propdic; } // ICC profiles //http://ninedegreesbelow.com/photography/embedded-color-space-information.html uint ccc = Frame.GetColorContextCount(); var profiles = new IWICColorContext[ccc]; var profile = (IWICColorContext)null; if (ccc > 0) { for (int i = 0; i < ccc; i++) { profiles[i] = AddRef(Wic.CreateColorContext()); } Frame.GetColorContexts(ccc, profiles); } foreach (var cc in profiles) { var cct = cc.GetType(); if (cct == WICColorContextType.WICColorContextProfile) { uint ccs = cc.GetProfileBytes(0, null); var ccb = new byte[ccs]; cc.GetProfileBytes(ccs, ccb); // 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 var cp = new ColorProfileInfo(ccb); if (cp.IsValid && ((cp.IsDisplayRgb && !cp.IsStandardSrgb) || (Context.IsCmyk && cp.IsCmyk) /* || (Context.IsGreyscale && cp.DataColorSpace == "GRAY") */)) { profile = cc; break; } } else if (cct == WICColorContextType.WICColorContextExifColorSpace && cc.GetExifColorSpace() == ExifColorSpace.AdobeRGB) { profile = cc; break; } } Context.SourceColorContext = profile ?? (Context.IsCmyk ? cmykProfile.Value : null); Context.DestColorContext = srgbProfile.Value; }
public static byte[] GetProfileBytes(this IWICColorContext colorContext) { return(FetchIntoBufferHelper.FetchArray <byte>(colorContext.GetProfileBytes)); }
public WicColorContext(IWICColorContext palette) : this((object)palette) { }
public static bool TryInitialize(this IWICColorTransform trans, IWICBitmapSource source, IWICColorContext ctxSrc, IWICColorContext ctxDest, Guid fmtDest) { int hr = ProxyFunctions.InitializeColorTransform(trans, source, ctxSrc, ctxDest, fmtDest); if (hr < 0 && hr != (int)WinCodecError.ERROR_INVALID_PROFILE) { Marshal.ThrowExceptionForHR(hr); } return(hr >= 0); }
public static void AddMetadataReader(WicProcessingContext ctx, bool basicOnly = false) { if (ctx.DecoderFrame.Frame is null) { return; } if (ctx.DecoderFrame.Frame.TryGetMetadataQueryReader(out var metareader)) { ctx.AddRef(metareader); // Exif orientation var pvorient = default(PropVariant); if (ctx.Settings.OrientationMode != OrientationMode.Ignore && metareader.TryGetMetadataByName("System.Photo.Orientation", out pvorient)) { #pragma warning disable 0618 // VarEnum is obsolete if (ctx.Settings.OrientationMode == OrientationMode.Normalize && pvorient.UnmanagedType == VarEnum.VT_UI2) { ctx.DecoderFrame.ExifOrientation = (Orientation)Math.Min(Math.Max((ushort)Orientation.Normal, (ushort)pvorient.Value), (ushort)Orientation.Rotate270); } #pragma warning restore 0618 var opt = ctx.DecoderFrame.ExifOrientation.ToWicTransformOptions(); if (ctx.DecoderFrame.SupportsPlanarPipeline && opt != WICBitmapTransformOptions.WICBitmapTransformRotate0 && ctx.DecoderFrame.Frame is IWICPlanarBitmapSourceTransform ptrans) { uint pw = 1, ph = 1; var desc = new WICBitmapPlaneDescription[2]; ctx.DecoderFrame.SupportsPlanarPipeline = ptrans.DoesSupportTransform(ref pw, ref ph, opt, WICPlanarOptions.WICPlanarOptionsDefault, planarPixelFormats, desc, 2); } } if (basicOnly) { return; } // other requested properties var propdic = new Dictionary <string, PropVariant>(); foreach (string prop in ctx.Settings.MetadataNames ?? Enumerable.Empty <string>()) { if (metareader.TryGetMetadataByName(prop, out var pvar) && pvar.Value != null) { propdic[prop] = pvar; } } if (ctx.Settings.OrientationMode == OrientationMode.Preserve && pvorient != null) { propdic["System.Photo.Orientation"] = pvorient; } ctx.DecoderFrame.Metadata = propdic; } if (basicOnly) { return; } // ICC profiles //http://ninedegreesbelow.com/photography/embedded-color-space-information.html uint ccc = ctx.DecoderFrame.Frame.GetColorContextCount(); var fmt = ctx.Source.Format; var profiles = new IWICColorContext[ccc]; var profile = default(IWICColorContext); if (ccc > 0) { for (int i = 0; i < ccc; i++) { profiles[i] = ctx.AddRef(Wic.Factory.CreateColorContext()); } ctx.DecoderFrame.Frame.GetColorContexts(ccc, profiles); } foreach (var cc in profiles) { var cct = cc.GetType(); if (cct == WICColorContextType.WICColorContextProfile) { int ccs = (int)cc.GetProfileBytes(0, null); // don't try to read giant profiles. 4MiB is more than enough if ((uint)ccs > (1024 * 1024 * 4)) { continue; } using (var ccb = MemoryPool <byte> .Shared.Rent(ccs)) { MemoryMarshal.TryGetArray(ccb.Memory.Slice(0, ccs), out ArraySegment <byte> cca); cc.GetProfileBytes((uint)cca.Count, cca.Array); var cpi = ColorProfile.Cache.GetOrAdd(cca); // 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 if (cpi.IsValid && ( (cpi.DataColorSpace == ColorProfile.ProfileColorSpace.Rgb && (fmt.ColorRepresentation == PixelColorRepresentation.Bgr || fmt.ColorRepresentation == PixelColorRepresentation.Rgb) && !cpi.IsSrgb) || (cpi.DataColorSpace == ColorProfile.ProfileColorSpace.Grey && fmt.ColorRepresentation == PixelColorRepresentation.Grey && !cpi.IsSrgbCurve) || (cpi.DataColorSpace == ColorProfile.ProfileColorSpace.Cmyk && fmt.ColorRepresentation == PixelColorRepresentation.Cmyk) )) { profile = cc; if (cpi.IsRgbMatrix || cpi.IsGreyTrc) { ctx.SourceColorProfile = cpi; } break; } } } else if (cct == WICColorContextType.WICColorContextExifColorSpace && cc.GetExifColorSpace() == ExifColorSpace.AdobeRGB) { profile = cc; break; } } var defaultColorContext = fmt.ColorRepresentation == PixelColorRepresentation.Grey ? Wic.GreyContext.Value : Wic.SrgbContext.Value; ctx.SourceColorContext = profile ?? (fmt.ColorRepresentation == PixelColorRepresentation.Cmyk ? Wic.CmykContext.Value : null); ctx.DestColorContext = ctx.Settings.ColorProfileMode <= ColorProfileMode.NormalizeAndEmbed || ctx.SourceColorContext is null ? defaultColorContext : ctx.SourceColorContext; var defaultColorProfile = fmt.ColorRepresentation == PixelColorRepresentation.Grey ? ColorProfile.sGrey : ColorProfile.sRGB; ctx.SourceColorProfile = ctx.SourceColorProfile ?? defaultColorProfile; ctx.DestColorProfile = ctx.Settings.ColorProfileMode <= ColorProfileMode.NormalizeAndEmbed ? defaultColorProfile : ctx.SourceColorProfile; }
IWICColorContext[] CheckGetSupported(MainForm form, bool supported, Func <uint, IWICColorContext[], uint> getter, DataEntry[] de) { IWICColorContext[] value = null; uint size = 0; try { size = getter(0, null); if (supported) { if (size > 0) { value = new IWICColorContext[size]; IWICImagingFactory factory = new WICImagingFactory() as IWICImagingFactory; for (uint i = 0; i < size; i++) { value[i] = factory.CreateColorContext(); } factory.ReleaseComObject(); } } else { form.Add(this, getter.ToString(Resources._0_ShouldFail, "0, NULL, ..."), de, new DataEntry(Resources.Expected, WinCodecError.WINCODEC_ERR_UNSUPPORTEDOPERATION)); } } catch (Exception e) { if (supported) { form.Add(this, getter.ToString(Resources._0_Failed, "0, NULL, ..."), de, new DataEntry(e)); } else { form.CheckHRESULT(this, WinCodecError.WINCODEC_ERR_UNSUPPORTEDOPERATION, e, "0, NULL, ...", de); } } if (size > 0) { try { uint newSize = getter(size, value); if (newSize == size) { int index = 0; foreach (IWICColorContext c in value) { if (c == null) { form.Add(this, getter.ToString(Resources._0_NULLItem), de, new DataEntry(Resources.Index, index)); } index++; } } else { form.Add(this, getter.ToString(Resources._0_NotExpectedValue), de, new DataEntry(Resources.Expected, size), new DataEntry(Resources.Actual, newSize)); } } catch (Exception e) { form.Add(this, getter.ToString(Resources._0_Failed), de, new DataEntry(e)); } } return(value); }