您应该能够使用 Marshal 替换代码,并通过 BinaryReader 之类的工具显式读取底层流。这可能会比较慢,因为您必须将流完全读入托管内存或查找它,而不是依赖于非托管内存中已经存在的副本来快速访问,但这从根本上来说是您唯一的选择。
即使仅执行读取操作,您也无法从中等信任上下文深入探索非托管内存。
查看链接的代码后,您会发现不允许执行此类操作是有原因的。首先,他忽略了 IntPtr 的 64/32 位方面!
他使用的底层 BitMapData 类完全基于对任意内存进行不受限制的读取访问,这在中等信任度下永远不会发生。
需要对其基本功能进行重大重写,才能直接使用 BitMap(使用缓慢的 GetPixel 调用)或直接通过传统流 api 读取数据,将其放入数组中,然后自己解析出来。这些都可能不会令人愉快。前者会慢得多(由于每个像素读取的高开销,我预计会是一个数量级),后者慢一些(尽管仍然更慢),但在重写图像数据的低级解析方面有更多的相关工作。
以下是根据当前代码需要更改的粗略指南:
来自 Quantizer.cs
public Bitmap Quantize(Image source)
{
// Get the size of the source image
int height = source.Height;
int width = source.Width;
// And construct a rectangle from these dimensions
Rectangle bounds = new Rectangle(0, 0, width, height);
// First off take a 32bpp copy of the image
Bitmap copy = new Bitmap(width, height, PixelFormat.Format32bppArgb);
// And construct an 8bpp version
Bitmap output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
// Now lock the bitmap into memory
using (Graphics g = Graphics.FromImage(copy))
{
g.PageUnit = GraphicsUnit.Pixel;
// Draw the source image onto the copy bitmap,
// which will effect a widening as appropriate.
g.DrawImage(source, bounds);
}
//!! BEGIN CHANGES - no locking here
//!! simply use copy not a pointer to it
//!! you could also simply write directly to a buffer then make the final immage in one go but I don't bother here
// Call the FirstPass function if not a single pass algorithm.
// For something like an octree quantizer, this will run through
// all image pixels, build a data structure, and create a palette.
if (!_singlePass)
FirstPass(copy, width, height);
// Then set the color palette on the output bitmap. I'm passing in the current palette
// as there's no way to construct a new, empty palette.
output.Palette = GetPalette(output.Palette);
// Then call the second pass which actually does the conversion
SecondPass(copy, output, width, height, bounds);
//!! END CHANGES
// Last but not least, return the output bitmap
return output;
}
//!! Completely changed, note that I assume all the code is changed to just use Color rather than Color32
protected virtual void FirstPass(Bitmap source, int width, int height)
{
// Loop through each row
for (int row = 0; row < height; row++)
{
// And loop through each column
for (int col = 0; col < width; col++)
{
InitialQuantizePixel(source.GetPixel(col, row));
} // Now I have the pixel, call the FirstPassQuantize function...
}
}
您需要在其他功能中执行大致相同的操作。
这消除了对 Color32 的任何需要,Bitmap 类将为您处理所有这些。
Bitmap.SetPixel()
将处理第二遍。请注意,这是最简单的移植方法,但绝对不是在中等信任环境中最快的方法。