- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
Possible Duplicate:
How to crop huge image
有一个问题询问如何裁剪图像 here
我已经阅读并使用了答案。但它们似乎都需要将图像加载到 Bitmap
或 Image
中。
这导致我出现内存问题。当我试图将 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/
我是 Java 新手,这是我的代码, if( a.name == b.name && a.displayname == b.displayname && a.linknam
在下面的场景中,我有一个 bool 值。根据结果,我调用完全相同的函数,唯一的区别是参数的数量。 var myBoolean = ... if (myBoolean) { retrieve
我是一名研究 C++ 的 C 开发人员: 我是否正确理解如果我抛出异常然后堆栈将展开直到找到第一个异常处理程序?是否可以在不展开的情况下在任何 throw 上打开调试器(即不离开声明它的范围或任何更高
在修复庞大代码库中的错误时,我观察到一个奇怪的情况,其中引用的动态类型从原始 Derived 类型更改为 Base 类型!我提供了最少的代码来解释问题: struct Base { // some
我正在尝试用 C# 扩展给定的代码,但由于缺乏编程经验,我有点陷入困境。 使用 Visual Studio 社区,我尝试通过控制台读出 CPU 核心温度。该代码使用开关/外壳来查找传感器的特定名称(即
这可能是一个哲学问题。 假设您正在向页面发出 AJAX 请求(这是使用 Prototype): new Ajax.Request('target.asp', { method:"post", pa
我有以下 HTML 代码,我无法在所有浏览器中正常工作: 我试图在移动到
我对 Swift 很陌生。我如何从 addPin 函数中检索注释并能够在我的 addLocation 操作 (buttonPressed) 中使用它。我正在尝试使用压力触摸在 map 上添加图钉,在两
我设置了一个详细 View ,我是否有几个 Nib 文件根据在 Root View Controller 的表中选择的项目来加载。 我发现,对于 Nibs 的类,永远不会调用 viewDidUnloa
我需要动态访问 json 文件并使用以下代码。在本例中,“bpicsel”和“temp”是变量。最终结果类似于“data[0].extit1” var title="data["+bpicsel+"]
我需要使用第三方 WCF 服务。我已经在我的证书存储中配置了所需的证书,但是在调用 WCF 服务时出现以下异常。 向 https://XXXX.com/AHSharedServices/Custome
在几个 SO 答案(1、2)中,建议如果存在冲突则不应触发 INSERT 触发器,ON CONFLICT DO NOTHING 在触发语句中。也许我理解错了,但在我的实验中似乎并非如此。 这是我的 S
如果进行修改,则会给出org.hibernate.NonUniqueObjectException。在我的 BidderBO 类(class)中 @Override @Transactional(pr
我使用 indexOf() 方法来精细地查找数组中的对象。 直到此刻我查了一些资料,发现代码应该无法正常工作。 我在reducer中尝试了上面的代码,它成功了 let tmp = state.find
假设我有以下表格: CREATE TABLE Game ( GameID INT UNSIGNED NOT NULL, GameType TINYINT UNSIGNED NOT NU
代码: Alamofire.request(URL(string: imageUrl)!).downloadProgress(closure: { (progress) in
我是一名优秀的程序员,十分优秀!