Possible Duplicate:
How to crop huge image
There is a question asking how to crop an image here
Ive read it and used the answers. But they all seem to require loading the image into a Bitmap
or Image
.
This is causing memory issues for me. As Im trying to crop 5 images (8000 x 8000) into tiles. One at a time.
Correct me if im wrong, but thats 8000x8000x4 bytes = 244 MB. per image.
And randomly I get out of memory problem.
How can I get a 1000x1000 image from another image, with reduced memory consumption.
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.
C is an imperative procedural language supporting structured programming, lexical variable scope, and recursion, with a static type system. It was designed to be compiled to provide low-level access to memory and language constructs that map efficiently to machine instructions, all with minimal runtime support.
So, this is a decidedly non-trivial thing to do - basically, you'd have to re-implement the image decoder for a given image format. This is not simple.
For the "simple" Windows BMP format, there are these beasts to contend with:
That said, I had to give it a try over my lunch break...here's what I was able to come up with, in a nice LINQPad-ready script.
(NOTE: Windows BMP only!)
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With