PREMESSO CHE:
Una bitmap MxN esiste come una matrice di pixel ad N righe, ed ogni riga è costituita da 3*M byte colore + un certo numero di byte riservati di valore ininfluente tanti quanti occorrono per portare la riga ad avere un numero di byte che sia multiplo di 4. Es. una bitmap 5x4 avrà 4 righe ognuna di 3*5 + 1 byte perchè 3*5 fa 15 e 15 non è multiplo di 4, serve un altro byte per arrivare a 16.
PREMESSO CHE:
La mappatura dei byte su filestream e quella in memoria sono uguali, cambia solo una cosa: nello stream si comincia dalla riga in basso e si procede da sx a dx salendo verso l'alto, nella memoria si segue invece ilo normale flusso dei pixel (dall'alto verso il basso e da sx a dx).
Detto questo
OGGETTO: ho la necessità di copiare in memoria una sotto-bitmap b2 (regione rettangolare) da una bitmap base b1 fuori memoria (su stream).
In precedenza ho presentato un codice che fa esattamente l'operazione inversa cioè copia una bitmap b2 in memoria in una bitmap base b1 fuori memoria e funziona, ma non c'è verso di fare funzionare il codice che ho scritto per l'operazione inversa come da oggetto.
Mi dite cosa ho sbagliato?
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 b1 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 b2 = new Bitmap(dimx, dimy); //bmdata contiene tutti i byte della clip System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, dimx, dimy); System.Drawing.Imaging.BitmapData bmdata = b2.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, b2.PixelFormat); // Puntatore ad inizio bitmap clip b2 IntPtr Ptr = bmdata.Scan0; //Lunghezza fisica di row della base int truewidth1 = (int)((Bits * Dim1 + 31) / 32) * 4; //Lunghezza fisica di row della b2 int truewidth2 = (int)((Bits * dimx + 31) / 32) * 4; //n. byte da copiare (= byte x row) int bytes = 3 * dimx; //array dei byte colore pixel di b2 byte[] a = new byte[bytes]; // Stream della base FileStream f = File.Open(path, FileMode.OpenOrCreate); int sp; //puntatore stream base //ciclo dei pixel nella regione di sovrascrittura for (int y = y0; y < y0 + dimy; y++) { //puntatore stream ad inizio row (x0,y) su base sp = Ofs + (Bits / 8) * x0 + truewidth1 * (Dim2 - y - 1); //aggiorna puntatore stream f.Seek(sp, SeekOrigin.Begin); //legge i byte-pixel nello stream f.Read(a, 0, bytes); //copia byte array nella memoria b2 System.Runtime.InteropServices.Marshal.Copy(a, 0, Ptr, bytes); //aggiorna il puntatore bmdata alla prossima riga di b2 Ptr = new IntPtr((int)IntPtr.Add(Ptr, truewidth2)); } // Chiusura b2.UnlockBits(bmdata); f.Close(); return b2; }codice://Legge in un file bitmap e restituisce Dim1, Dim2, bits e offset public static Vector4 GetData(string path) { long len; byte[] b = new byte[30]; using (FileStream x = File.Open(path, FileMode.OpenOrCreate)) { x.Seek(0, SeekOrigin.Begin); //Ptr a Width (4 byte) x.Read(b, 0, b.Length); len = x.Length; x.Close(); } int Ofs = Convert.ToInt32(b[10]); int Dim1 = Convert.ToInt32(b[18]) + Convert.ToInt32(b[19]) * 256; int Dim2 = Convert.ToInt32(b[22]) + Convert.ToInt32(b[23]) * 256; int Bits = Convert.ToInt32(b[28]); long bmpbytes = len - Ofs; if (bmpbytes < Dim1 * Dim2) { Dim1 = Convert.ToInt32(b[18]) * 256 + Convert.ToInt32(b[19]); Dim2 = Convert.ToInt32(b[22]) * 256 + Convert.ToInt32(b[23]); } if (Ofs == 0) Ofs = 54; if (Bits == 0) Bits = 24; return new Vector4(Dim1, Dim2, Bits, Ofs); }

Rispondi quotando

