Files
2026-07-13 12:26:32 +08:00

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);
}
}
}