PageRenderTime 58ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/Effects/MaskLayerEffect.cs

https://bitbucket.org/rstarkov/tankiconmaker
C# | 96 lines | 89 code | 7 blank | 0 comment | 11 complexity | 44aefeb817fcef7a54346ab75bbe77e8 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-3.0, CC-BY-SA-3.0
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Collections.Generic;
  5. using System.ComponentModel;
  6. using System.Windows.Media.Imaging;
  7. using ImageMagick;
  8. using RT.Util.Lingo;
  9. using RT.Util.Serialization;
  10. namespace TankIconMaker.Effects
  11. {
  12. [TypeConverter(typeof(MaskModeTranslation.Conv))]
  13. enum MaskMode
  14. {
  15. Combined,
  16. Opacity,
  17. Grayscale
  18. }
  19. class MaskLayerEffect : EffectBase
  20. {
  21. public override int Version { get { return 1; } }
  22. public override string TypeName { get { return App.Translation.EffectMaskLayer.EffectName; } }
  23. public override string TypeDescription { get { return App.Translation.EffectMaskLayer.EffectDescription; } }
  24. public string MaskLayerId { get; set; }
  25. public static MemberTr MaskLayerIdTr(Translation tr) { return new MemberTr(tr.Category.Mask, tr.EffectMaskLayer.MaskLayerId); }
  26. public MaskMode MaskMode { get; set; }
  27. public static MemberTr MaskModeTr(Translation tr) { return new MemberTr(tr.Category.Mask, tr.EffectMaskLayer.MaskMode); }
  28. public bool Invert { get; set; }
  29. public static MemberTr InvertTr(Translation tr) { return new MemberTr(tr.Category.Mask, tr.EffectMaskLayer.InvertTr); }
  30. public MaskLayerEffect()
  31. {
  32. MaskLayerId = string.Empty;
  33. MaskMode = Effects.MaskMode.Combined;
  34. Invert = false;
  35. }
  36. public unsafe override BitmapBase Apply(RenderTask renderTask, BitmapBase layer)
  37. {
  38. Tank tank = renderTask.Tank;
  39. LayerBase maskLayer;
  40. if (string.IsNullOrEmpty(MaskLayerId))
  41. return layer;
  42. maskLayer = renderTask.Style.Layers.FirstOrDefault(x => x.Id == MaskLayerId);
  43. if (maskLayer == null)
  44. throw new StyleUserError(App.Translation.EffectMaskLayer.ErrorInvalidId.Fmt(MaskLayerId));
  45. if (renderTask.IsLayerAlreadyReferenced(maskLayer))
  46. throw new StyleUserError(App.Translation.EffectMaskLayer.ErrorRecursiveLayerReference.Fmt(MaskLayerId));
  47. var maskImg = renderTask.RenderLayer(maskLayer);
  48. using (layer.UseWrite())
  49. {
  50. using (maskImg.UseRead())
  51. {
  52. for (int i = 0; i < layer.Width; ++i)
  53. {
  54. for (int j = 0; j < layer.Height; ++j)
  55. {
  56. decimal alpha = 0;
  57. if (i < maskImg.Width && j < maskImg.Height)
  58. {
  59. switch (MaskMode)
  60. {
  61. case Effects.MaskMode.Opacity:
  62. alpha = maskImg.Data[i * 4 + maskImg.Stride * j + 3];
  63. break;
  64. case Effects.MaskMode.Grayscale:
  65. alpha = (maskImg.Data[i * 4 + maskImg.Stride * j]
  66. + maskImg.Data[i * 4 + maskImg.Stride * j + 1]
  67. + maskImg.Data[i * 4 + maskImg.Stride * j + 2]
  68. ) / 3;
  69. break;
  70. case Effects.MaskMode.Combined:
  71. alpha = (maskImg.Data[i * 4 + maskImg.Stride * j]
  72. + maskImg.Data[i * 4 + maskImg.Stride * j + 1]
  73. + maskImg.Data[i * 4 + maskImg.Stride * j + 2]
  74. ) / 3 * maskImg.Data[i * 4 + maskImg.Stride * j + 3] / 255m;
  75. break;
  76. }
  77. }
  78. if (Invert)
  79. alpha = 255m - alpha;
  80. var opacity = layer.Data[i * 4 + layer.Stride * j + 3] * (alpha / 255m);
  81. layer.Data[i * 4 + layer.Stride * j + 3] = (byte) opacity;
  82. }
  83. }
  84. }
  85. }
  86. return layer;
  87. }
  88. }
  89. }