gpt4 book ai didi

C#如何在不使用大量内存的情况下裁剪图像?

转载 作者:IT王子 更新时间:2023-10-28 23:38:02 27 4
gpt4 key购买 nike

Possible Duplicate:
How to crop huge image

有一个问题询问如何裁剪图像 here

我已经阅读并使用了答案。但它们似乎都需要将图像加载到 BitmapImage 中。

这导致我出现内存问题。当我试图将 5 张图像 (8000 x 8000) 裁剪成图 block 时。一次一个。

如果我错了,请纠正我,但那是 8000x8000x4 字节 = 244 MB。每张图片。

我随机出现内存不足的问题。

如何从另一个图像中获取 1000x1000 的图像,同时减少内存消耗。

最佳答案

因此,这绝对是一件非常重要的事情 - 基本上,您必须为给定的图像格式重新实现图像解码器。这不简单

对于“简单”的 Windows BMP 格式,有这些野兽要与之抗衡:

也就是说,我必须在午休时试一试...这是我能够想出的,在一个不错的 LINQPad 就绪脚本中。

(注意:仅限 Windows BMP!)

void Main()
{
// Carve out a 100x100 chunk
var top = 100;
var left = 100;
var bottom = 300;
var right = 300;

// For BMP only - open input
var fs = File.OpenRead(@"c:\temp\testbmp.bmp");

// Open output
if(File.Exists(@"c:\temp\testbmp.cropped.bmp")) File.Delete(@"c:\temp\testbmp.cropped.bmp");
var output = File.Open(@"c:\temp\testbmp.cropped.bmp", FileMode.CreateNew);
var bw = new BinaryWriter(output);

// Read out the BMP header fields
var br = new BinaryReader(fs);
var headerField = br.ReadInt16();
var bmpSize = br.ReadInt32();
var reserved1 = br.ReadInt16();
var reserved2 = br.ReadInt16();
var startOfData = br.ReadInt32();

// Read out the BMP DIB header
var header = new BITMAPV5Header();
var headerBlob = br.ReadBytes(Marshal.SizeOf(header));
var tempMemory = Marshal.AllocHGlobal(Marshal.SizeOf(header));
Marshal.Copy(headerBlob, 0, tempMemory, headerBlob.Length);
header = (BITMAPV5Header)Marshal.PtrToStructure(tempMemory, typeof(BITMAPV5Header));
Marshal.FreeHGlobal(tempMemory);

// This file is a 24bpp rgb bmp,
var format = PixelFormats.Bgr24;
var bytesPerPixel = (int)(format.BitsPerPixel / 8);
Console.WriteLine("Bytes/pixel:{0}", bytesPerPixel);

// And now I know its dimensions
var imageWidth = header.ImageWidth;
var imageHeight = header.ImageHeight;
Console.WriteLine("Input image is:{0}x{1}", imageWidth, imageHeight);

var fromX = left;
var toX = right;
var fromY = imageHeight - top;
var toY = imageHeight - bottom;

// How "long" a horizontal line is
var strideInBytes = imageWidth * bytesPerPixel;
Console.WriteLine("Stride size is:0x{0:x}", strideInBytes);

// new size
var newWidth = Math.Abs(toX - fromX);
var newHeight = Math.Abs(toY - fromY);
Console.WriteLine("New slice dimensions:{0}x{1}", newWidth, newHeight);

// Write out headers to output file
{
// header = "BM" = "Windows Bitmap"
bw.Write(Encoding.ASCII.GetBytes("BM"));
var newSize = 14 + Marshal.SizeOf(header) + (newWidth * newHeight * bytesPerPixel);
Console.WriteLine("New File size: 0x{0:x} bytes", newSize);
bw.Write((uint)newSize);
// 2 reserved shorts
bw.Write((ushort)0);
bw.Write((ushort)0);
// offset to "data"
bw.Write(header.HeaderSize + 14);

// Tweak size in header to cropped size
header.ImageWidth = newWidth;
header.ImageHeight = newHeight;

// Write updated DIB header to output
tempMemory = Marshal.AllocHGlobal(Marshal.SizeOf(header));
Marshal.StructureToPtr(header, tempMemory, true);
byte[] asBytes = new byte[Marshal.SizeOf(header)];
Marshal.Copy(tempMemory, asBytes, 0, asBytes.Length);
Marshal.FreeHGlobal(tempMemory);
bw.Write(asBytes);
asBytes.Dump();
}

// Jump to where the pixel data is located (on input side)
Console.WriteLine("seeking to position: 0x{0:x}", startOfData);
fs.Seek(startOfData, SeekOrigin.Begin);

var sY = Math.Min(fromY, toY);
var eY = Math.Max(fromY, toY);
for(int currY = sY; currY < eY; currY++)
{
long offset = startOfData + ((currY * strideInBytes) + (fromX * bytesPerPixel));
fs.Seek(offset, SeekOrigin.Begin);

// Blast in each horizontal line of our chunk
var lineBuffer = new byte[newWidth * bytesPerPixel];
int bytesRead = fs.Read(lineBuffer, 0, lineBuffer.Length);
output.Write(lineBuffer, 0, lineBuffer.Length);
}

fs.Close();
output.Close();
}

[StructLayout(LayoutKind.Sequential, Pack=0)]
public struct BITMAPV5Header
{
public uint HeaderSize;
public int ImageWidth;
public int ImageHeight;
public ushort Planes;
public ushort BitCount;

[MarshalAs(UnmanagedType.ByValArray, SizeConst=36)]
public byte[] DontCare;
}

关于C#如何在不使用大量内存的情况下裁剪图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13729368/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com