Fix wrong spelling of 'Extentions' to 'Extensions' and Add blending to 'ImageExtension'

This commit is contained in:
miku-666
2023-04-08 22:34:44 +02:00
parent a5a408a30e
commit 59cd8575b1
11 changed files with 133 additions and 37 deletions

View File

@@ -0,0 +1,12 @@
namespace PckStudio.Extensions
{
public enum BlendMode
{
Add,
Subtract,
Multiply,
Average,
DescendingOrder,
AscendingOrder
}
}

View File

@@ -1,8 +1,8 @@
using System.Collections.Generic;
namespace PckStudio.Classes.Extentions
namespace PckStudio.Extensions
{
internal static class EnumerableExtentions
internal static class EnumerableExtensions
{
public static IEnumerable<(int index, T type)>enumerate<T>(this IEnumerable<T> array)
{

View File

@@ -4,11 +4,14 @@ using System.Drawing;
using System.Diagnostics;
using System;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Media.Media3D;
using System.Web;
namespace PckStudio.Classes.Extentions
namespace PckStudio.Extensions
{
internal static class ImageExtentions
{
internal static class ImageExtensions
{
public enum ImageLayoutDirection
{
Horizontal,
@@ -31,15 +34,15 @@ namespace PckStudio.Classes.Extentions
}
}
private static Image GetTileImage(Image source, Rectangle area, Size size, GraphicsUnit unit = GraphicsUnit.Pixel)
public static Image GetArea(this Image source, Rectangle area, GraphicsUnit unit = GraphicsUnit.Pixel)
{
Image tileImage = new Bitmap(size.Width, size.Height);
Image tileImage = new Bitmap(area.Width, area.Height);
using (Graphics gfx = Graphics.FromImage(tileImage))
{
gfx.SmoothingMode = SmoothingMode.None;
gfx.InterpolationMode = InterpolationMode.NearestNeighbor;
gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
gfx.DrawImage(source, new Rectangle(Point.Empty, size), area, unit);
gfx.DrawImage(source, new Rectangle(Point.Empty, area.Size), area, unit);
}
return tileImage;
}
@@ -54,7 +57,7 @@ namespace PckStudio.Classes.Extentions
int row = i / img_row_count;
int column = i % img_row_count;
Rectangle tileArea = new Rectangle(new Point(column * size.Height, row * size.Width), size);
yield return GetTileImage(source, tileArea, size);
yield return source.GetArea(tileArea);
}
yield break;
}
@@ -70,7 +73,7 @@ namespace PckStudio.Classes.Extentions
{
ImageLayoutInfo locationInfo = new ImageLayoutInfo(source.Width, source.Height, i, layoutDirection);
Rectangle tileArea = new Rectangle(locationInfo.SectionPoint, locationInfo.SectionSize);
yield return GetTileImage(source, tileArea, locationInfo.SectionSize);
yield return source.GetArea(tileArea);
}
yield break;
}
@@ -112,8 +115,18 @@ namespace PckStudio.Classes.Extentions
public CompositingMode CompositingMode { get; set; }
public CompositingQuality CompositingQuality { get; set; }
public InterpolationMode InterpolationMode { get; set; }
public SmoothingMode SmoothingMode {get; set; }
public SmoothingMode SmoothingMode { get; set; }
public PixelOffsetMode PixelOffsetMode { get; set; }
public void Apply(Graphics graphics)
{
graphics.CompositingMode = CompositingMode;
graphics.CompositingQuality = CompositingQuality;
graphics.InterpolationMode = InterpolationMode;
graphics.SmoothingMode = SmoothingMode;
graphics.PixelOffsetMode = PixelOffsetMode;
}
}
public static Image ResizeImage(this Image image, int width, int height, GraphicsConfig graphicsConfig)
@@ -125,12 +138,7 @@ namespace PckStudio.Classes.Extentions
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = graphicsConfig.CompositingMode;
graphics.CompositingQuality = graphicsConfig.CompositingQuality;
graphics.InterpolationMode = graphicsConfig.InterpolationMode;
graphics.SmoothingMode = graphicsConfig.SmoothingMode;
graphics.PixelOffsetMode = graphicsConfig.PixelOffsetMode;
graphicsConfig.Apply(graphics);
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
@@ -139,5 +147,87 @@ namespace PckStudio.Classes.Extentions
}
return destImage;
}
public static Image Fill(this Image image, Color color)
{
using (var g = Graphics.FromImage(image))
{
using (SolidBrush brush = new SolidBrush(color))
{
g.FillRectangle(brush, new Rectangle(Point.Empty, image.Size));
}
}
return image;
}
public static Image Blend(this Image bg, Color foregroundColor, BlendMode mode)
{
Bitmap bitmap = new Bitmap(bg);
bitmap.Fill(foregroundColor);
return bg.Blend(bitmap, mode);
}
public static Image Blend(this Image image, Image overlay, BlendMode mode)
{
Stopwatch stopwatch = Stopwatch.StartNew();
if (image is not Bitmap baseImage || overlay is not Bitmap overlayImage)
return image;
BitmapData baseImageData = baseImage.LockBits(new Rectangle(Point.Empty, baseImage.Size),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
byte[] baseImageBuffer = new byte[baseImageData.Stride * baseImageData.Height];
Marshal.Copy(baseImageData.Scan0, baseImageBuffer, 0, baseImageBuffer.Length);
BitmapData overlayImageData = overlayImage.LockBits(new Rectangle(Point.Empty, overlayImage.Size),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] overlayImageBuffer = new byte[overlayImageData.Stride * overlayImageData.Height];
Marshal.Copy(overlayImageData.Scan0, overlayImageBuffer, 0, overlayImageBuffer.Length);
for (int k = 0; k < baseImageBuffer.Length && k < overlayImageBuffer.Length; k += 4)
{
baseImageBuffer[k + 0] = CalculateColorComponentBlendValue(baseImageBuffer[k + 0] / 255f, overlayImageBuffer[k + 0] / 255f, mode);
baseImageBuffer[k + 1] = CalculateColorComponentBlendValue(baseImageBuffer[k + 1] / 255f, overlayImageBuffer[k + 1] / 255f, mode);
baseImageBuffer[k + 2] = CalculateColorComponentBlendValue(baseImageBuffer[k + 2] / 255f, overlayImageBuffer[k + 2] / 255f, mode);
}
Bitmap bitmapResult = new Bitmap(baseImage.Width, baseImage.Height, PixelFormat.Format32bppArgb);
BitmapData resultImageData = bitmapResult.LockBits(new Rectangle(Point.Empty, bitmapResult.Size),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(baseImageBuffer, 0, resultImageData.Scan0, baseImageBuffer.Length);
bitmapResult.UnlockBits(resultImageData);
baseImage.UnlockBits(baseImageData);
overlayImage.UnlockBits(overlayImageData);
stopwatch.Stop();
Debug.WriteLine($"{nameof(ImageExtensions.Blend)} took {stopwatch.ElapsedMilliseconds}ms");
return bitmapResult;
}
private static T Clamp<T>(T value, T min, T max) where T : IComparable<T>
{
if (value.CompareTo(min) < 0) return min;
else if (value.CompareTo(max) > 0) return max;
else return value;
}
private static byte CalculateColorComponentBlendValue(float source, float overlay, BlendMode blendType)
{
source = Clamp(source, 0.0f, 1.0f);
overlay = Clamp(overlay, 0.0f, 1.0f);
float resultValue = blendType switch
{
BlendMode.Add => source + overlay,
BlendMode.Subtract => source - overlay,
BlendMode.Multiply => source * overlay,
BlendMode.Average => (source + overlay) / 2.0f,
BlendMode.AscendingOrder => source > overlay ? overlay : source,
BlendMode.DescendingOrder => source < overlay ? overlay : source,
_ => 0.0f
};
return (byte)Clamp(resultValue * 255, 0, 255);
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using PckStudio.Classes.Extentions;
using PckStudio.Extensions;
using System.Text;
@@ -140,7 +140,7 @@ namespace PckStudio.Forms.Editor
var textures = isClockOrCompass ? linearImages : frameTextures;
return ImageExtentions.ImageFromImageArray(textures.ToArray(), ImageExtentions.ImageLayoutDirection.Vertical);
return ImageExtensions.ImageFromImageArray(textures.ToArray(), ImageExtensions.ImageLayoutDirection.Vertical);
}
}
}

View File

@@ -3,15 +3,13 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using PckStudio.Classes.FileTypes;
using PckStudio.Forms.Additional_Popups.Animation;
using PckStudio.Forms.Utilities;
using PckStudio.Classes.Extentions;
using PckStudio.Extensions;
using OMI.Formats.Pck;
namespace PckStudio.Forms.Editor
@@ -51,7 +49,7 @@ namespace PckStudio.Forms.Editor
using MemoryStream textureMem = new MemoryStream(animationFile.Data);
var texture = new Bitmap(textureMem);
var frameTextures = texture.CreateImageList(ImageExtentions.ImageLayoutDirection.Horizontal);
var frameTextures = texture.CreateImageList(ImageExtensions.ImageLayoutDirection.Horizontal);
currentAnimation = animationFile.Properties.HasProperty("ANIM")
? new Animation(frameTextures, animationFile.Properties.GetPropertyValue("ANIM"))
@@ -296,7 +294,7 @@ namespace PckStudio.Forms.Editor
return;
}
using MemoryStream textureMem = new MemoryStream(File.ReadAllBytes(textureFile));
var textures = Image.FromStream(textureMem).CreateImageList(ImageExtentions.ImageLayoutDirection.Horizontal);
var textures = Image.FromStream(textureMem).CreateImageList(ImageExtensions.ImageLayoutDirection.Horizontal);
var new_animation = new Animation(textures);
try
{

View File

@@ -1,12 +1,9 @@
using Newtonsoft.Json.Linq;
using System.Drawing;
using System.Linq;
using System.IO;
using PckStudio.Properties;
using System.Drawing.Imaging;
using PckStudio.Classes.Extentions;
using OMI.Formats.Pck;
using PckStudio.Extensions;
namespace PckStudio.Forms.Utilities
{

View File

@@ -4,11 +4,9 @@ using System.Linq;
using System.IO;
using PckStudio.Properties;
using PckStudio.Classes.Extentions;
using PckStudio.Extensions;
using OMI.Formats.Behaviour;
using OMI.Workers.Behaviour;
using OMI.Formats.Pck;
using System;
namespace PckStudio.Forms.Utilities
{

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.IO;
using PckStudio.Properties;
using PckStudio.Classes.Extentions;
using PckStudio.Extensions;
using OMI.Formats.Pck;
using OMI.Formats.Material;
using OMI.Workers.Material;

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.IO;
using PckStudio.Properties;
using PckStudio.Classes.Extentions;
using PckStudio.Extensions;
using OMI.Formats.Model;
using OMI.Formats.Pck;
using OMI.Workers.Model;

View File

@@ -19,7 +19,7 @@ using PckStudio.Classes.FileTypes;
using PckStudio.Classes.IO.PCK;
using OMI.Formats.Pck;
using OMI.Workers.Pck;
using PckStudio.Classes.Extentions;
using PckStudio.Extensions;
namespace PckStudio.Forms
{
@@ -1027,7 +1027,7 @@ namespace PckStudio.Forms
{
var ms = new MemoryStream(skinTexture.Data);
Bitmap saveSkin = new Bitmap(Image.FromStream(ms));
var config = new ImageExtentions.GraphicsConfig()
var config = new ImageExtensions.GraphicsConfig()
{
CompositingMode = CompositingMode.SourceCopy,
CompositingQuality = CompositingQuality.HighQuality,

View File

@@ -170,7 +170,8 @@
<Compile Include="Classes\API\PCKCenter\PCKCollections.cs" />
<Compile Include="Classes\API\PCKCenter\PCKCollectionsLocal.cs" />
<Compile Include="Classes\API\PCKCenter\SaveLocalJSON.cs" />
<Compile Include="Classes\Extentions\EnumerableExtentions.cs" />
<Compile Include="Classes\Extensions\BlendMode.cs" />
<Compile Include="Classes\Extensions\EnumerableExtensions.cs" />
<Compile Include="Classes\FileTypes\CSMBFile.cs" />
<Compile Include="Classes\FileTypes\PCKAudioFile.cs" />
<Compile Include="Classes\FileTypes\Binka.cs" />
@@ -185,7 +186,7 @@
<Compile Include="Classes\Models\DefaultModels\Steve64x64Model.cs" />
<Compile Include="Classes\Utils\3DS\3DSUtil.cs" />
<Compile Include="Classes\Utils\ARC\ARCUtil.cs" />
<Compile Include="Classes\Extentions\ImageExtentions.cs" />
<Compile Include="Classes\Extensions\ImageExtensions.cs" />
<Compile Include="Classes\Utils\SkinANIM.cs" />
<Compile Include="Classes\Models\DefaultModels\Steve64x32Model.cs" />
<Compile Include="Classes\Models\DefaultModels\ModelBase.cs" />