CPF/CPF.Windows/GDIPlus/GDIPlusBitmapLock.cs
2024-06-07 09:58:49 +08:00

169 lines
5.8 KiB
C#

//#if Net4
using System;
using System.Collections.Generic;
using System.Text;
using CPF.Drawing;
namespace CPF.GDIPlus
{
public class GDIPlusBitmapLock : IBitmapLockImpl
{
System.Drawing.Bitmap bmp;
System.Drawing.Imaging.BitmapData data;
int Stride;
public GDIPlusBitmapLock(GDIPlusBitmap bmp)
{
this.bmp = bmp.Bitmap;
data = this.bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
Stride = data.Stride;
}
public IntPtr DataPointer
{
get
{
return data.Scan0;
}
}
public PixelFormat PixelFormat => PixelFormat.PBgra;
public AlphaType AlphaType => AlphaType.Premul;
public void Dispose()
{
bmp.UnlockBits(data);
}
public unsafe void GetAlpha(in int x, in int y, out byte a)
{
byte* numPtr = (byte*)(((data.Scan0) + (y * Stride)) + (x * 4));
a = numPtr[3];
}
public unsafe void GetPixel(in int x, in int y, out byte a, out byte r, out byte g, out byte b)
{
byte* numPtr = (byte*)(((data.Scan0) + (y * Stride)) + (x * 4));
a = numPtr[3];
r = numPtr[2];
g = numPtr[1];
b = numPtr[0];
if (a > 0 && a < 255)
{
r = (byte)(r * 255 / a);
g = (byte)(g * 255 / a);
b = (byte)(b * 255 / a);
}
}
public unsafe void SetAlpha(in int x, in int y, in byte a)
{
byte* numPtr = (byte*)(((data.Scan0) + (y * Stride)) + (x * 4));
var oa = numPtr[3];
numPtr[3] = a;
if (oa == 0)
{
return;
}
numPtr[0] = (byte)(numPtr[0] * a / oa);
numPtr[1] = (byte)(numPtr[1] * a / oa);
numPtr[2] = (byte)(numPtr[2] * a / oa);
}
public unsafe void SetPixel(in int x, in int y, in byte a, in byte r, in byte g, in byte b)
{
byte* numPtr = (byte*)(((data.Scan0) + (y * Stride)) + (x * 4));
numPtr[0] = (byte)(b * a / 255);
numPtr[1] = (byte)(g * a / 255);
numPtr[2] = (byte)(r * a / 255);
numPtr[3] = a;
}
public unsafe void WritePixels(PixelRect rect, byte* sourceBuffer, PixelFormat sourcePixelFormat)
{
int offset = (bmp.Width - rect.Width) * 4;
var p = sourceBuffer + rect.Y * bmp.Width * 4 + rect.X * 4;
var target = (byte*)data.Scan0 + rect.Y * bmp.Width * 4 + rect.X * 4;
var rh = rect.Height;
var rw = rect.Width;
switch (sourcePixelFormat)
{
case PixelFormat.Undefined:
break;
case PixelFormat.PRgba:
for (int y = 0; y < rh; y++)
{
for (int x = 0; x < rw; x++)
{
//SetPixel(x + dirtyRect.X, y + dirtyRect.Y, p[3], p[2], p[1], p[0]);
target[0] = p[2];
target[1] = p[1];
target[2] = p[0];
target[3] = p[3];
target += 4;
p += 4;
} // x
p += offset;
target += offset;
} // y
break;
case PixelFormat.Rgba:
for (int y = 0; y < rh; y++)
{
for (int x = 0; x < rw; x++)
{
var a = p[3];
target[0] = (byte)(p[2] * a / 255);
target[1] = (byte)(p[1] * a / 255);
target[2] = (byte)(p[0] * a / 255);
target[3] = a;
target += 4;
p += 4;
} // x
p += offset;
target += offset;
} // y
break;
case PixelFormat.PBgra:
for (int y = 0; y < rh; y++)
{
for (int x = 0; x < rw; x++)
{
//SetPixel(x + dirtyRect.X, y + dirtyRect.Y, p[3], p[2], p[1], p[0]);
target[0] = p[0];
target[1] = p[1];
target[2] = p[2];
target[3] = p[3];
target += 4;
p += 4;
} // x
p += offset;
target += offset;
} // y
break;
case PixelFormat.Bgra:
for (int y = 0; y < rh; y++)
{
for (int x = 0; x < rw; x++)
{
var a = p[3];
target[0] = (byte)(p[0] * a / 255);
target[1] = (byte)(p[1] * a / 255);
target[2] = (byte)(p[2] * a / 255);
target[3] = a;
target += 4;
p += 4;
} // x
p += offset;
target += offset;
} // y
break;
default:
break;
}
}
}
}
//#endif