Ancora meglio:
codice:
//Preleva una porzione da una bitmap su disco in base ai dati di origine x0,y0
//e le dimensioni dimx,dimy e restituisce una bitmap in memoria.
//La copia avviene per porzioni di riga e usa il Marshalling
public static Bitmap MarshalGetBmp(string path, int x0, int y0, int dimx, int dimy)
{
//Legge i dati di intestazione della base
Vector4 Data = GetData(path);
int Dim1 = (int)Data.X;
int Dim2 = (int)Data.Y;
int Bits = (int)Data.Z;
int Ofs = (int)Data.W;
Bitmap b = new Bitmap(dimx, dimy);
//Impostazioni forzate a !overedge
if (x0 < 0)
x0 = 0;
if (y0 < 0)
y0 = 0;
if (x0 + dimx > Dim1)
x0 -= dimx + x0 - Dim1;
if (y0 + dimy > Dim2)
y0 -= dimy + y0 - Dim2;
//bmdata modulato ai bit della base
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, dimx, dimy);
System.Drawing.Imaging.PixelFormat format;
if (Bits == 24)
format = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
else if (Bits == 32)
format = System.Drawing.Imaging.PixelFormat.Format32bppRgb;
else
{
MessageBox.Show("! Format ERROR !");
return b;
}
System.Drawing.Imaging.BitmapData bmdata = b.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, format);
// Puntatore ad inizio bitmap clip b2
IntPtr Ptr = bmdata.Scan0;
//Lunghezza fisica di row della base
int truewidth1 = (int)((Bits * Dim1 + 31) / 32) * 4; // = bmdata.Stride
//Lunghezza fisica di row della b2
int truewidth2 = (int)((Bits * dimx + 31) / 32) * 4;
//n. byte da copiare (= byte x row)
int bytes = (Bits/8) * dimx;
//array dei values pixel
byte[] a = new byte[bytes];
// Stream della base
FileStream f = File.Open(path, FileMode.OpenOrCreate);
int sp; //puntatore stream base
//ciclo dei pixel regione di sovrascrittura
for (int y = y0; y < y0 + dimy; y++)
{
//puntatore stream ad inizio row (x0,y0) su base
sp = Ofs + (Bits / 8) * x0 + truewidth1 * (Dim2 - y - 1);
//aggiorna puntatore stream
f.Seek(sp, SeekOrigin.Begin);
//preleva ibyte-pixel nello stream
f.Read(a, 0, bytes);
System.Runtime.InteropServices.Marshal.Copy(a, 0, Ptr, truewidth2);
//aggiorna il puntatore bmdata ai prossimi 3 byte
Ptr = new IntPtr((int)IntPtr.Add(Ptr, truewidth2));
}
// Chiusura
b.UnlockBits(bmdata);
f.Close();
return b;
}