104 lines
3.3 KiB
C#
104 lines
3.3 KiB
C#
// Copyright 2025 Takuto Nakamura
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
using System.Drawing.Imaging;
|
|
|
|
namespace RunCat365
|
|
{
|
|
internal readonly ref struct BitmapLock
|
|
{
|
|
private readonly Bitmap bitmap;
|
|
internal BitmapData Data { get; }
|
|
|
|
internal BitmapLock(Bitmap bitmap, ImageLockMode mode)
|
|
{
|
|
this.bitmap = bitmap;
|
|
Data = bitmap.LockBits(
|
|
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
|
mode,
|
|
PixelFormat.Format32bppArgb
|
|
);
|
|
}
|
|
|
|
internal void Dispose()
|
|
{
|
|
bitmap.UnlockBits(Data);
|
|
}
|
|
}
|
|
|
|
internal static class BitmapExtension
|
|
{
|
|
internal static Bitmap Recolor(this Bitmap bitmap, Color color)
|
|
{
|
|
var newBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb);
|
|
|
|
using var srcLock = new BitmapLock(bitmap, ImageLockMode.ReadOnly);
|
|
using var dstLock = new BitmapLock(newBitmap, ImageLockMode.WriteOnly);
|
|
|
|
unsafe
|
|
{
|
|
byte* srcPtr = (byte*)srcLock.Data.Scan0;
|
|
byte* dstPtr = (byte*)dstLock.Data.Scan0;
|
|
|
|
for (int y = 0; y < bitmap.Height; y++)
|
|
{
|
|
byte* srcRow = srcPtr + (y * srcLock.Data.Stride);
|
|
byte* dstRow = dstPtr + (y * dstLock.Data.Stride);
|
|
|
|
for (int x = 0; x < bitmap.Width; x++)
|
|
{
|
|
byte* srcPixel = srcRow + (x * 4);
|
|
byte* dstPixel = dstRow + (x * 4);
|
|
|
|
dstPixel[0] = color.B;
|
|
dstPixel[1] = color.G;
|
|
dstPixel[2] = color.R;
|
|
dstPixel[3] = srcPixel[3];
|
|
}
|
|
}
|
|
}
|
|
|
|
return newBitmap;
|
|
}
|
|
|
|
internal static Icon ToIcon(this Bitmap bitmap)
|
|
{
|
|
using var pngStream = new MemoryStream();
|
|
bitmap.Save(pngStream, ImageFormat.Png);
|
|
var pngData = pngStream.ToArray();
|
|
|
|
using var icoStream = new MemoryStream();
|
|
using var bw = new BinaryWriter(icoStream);
|
|
|
|
bw.Write((short)0);
|
|
bw.Write((short)1);
|
|
bw.Write((short)1);
|
|
|
|
bw.Write((byte)(bitmap.Width >= 256 ? 0 : bitmap.Width));
|
|
bw.Write((byte)(bitmap.Height >= 256 ? 0 : bitmap.Height));
|
|
bw.Write((byte)0);
|
|
bw.Write((byte)0);
|
|
bw.Write((short)1);
|
|
bw.Write((short)32);
|
|
bw.Write(pngData.Length);
|
|
bw.Write(22);
|
|
|
|
bw.Write(pngData);
|
|
|
|
icoStream.Position = 0;
|
|
return new Icon(icoStream);
|
|
}
|
|
}
|
|
}
|