Gå til innhold

Anbefalte innlegg

Hei

 

Jeg har en frame av klassen BitMap. Denne framen skal sendes til en funksjon som tar i mot unsigned char* rgb24Buffer, hvor rgb24Buffer er definert som: "The format of rgb24Buffer is RGB24, here the buffer length must >= (width*24+31)/32*4*height"

 

Jeg skjønner ikke helt hvordan jeg skal få trykket BitMap framen inn i funkjonen (uten feilmelding så klart:P)

 

mvh

Martin

Lenke til kommentar
Videoannonse
Annonse

Du forteller ikke helt hva du skal her, men uansett;

Jeg regner med at dette er en C funksjon som du importerer med DllImport funksjonen.

 

Bytt om fra RGB24 i spesifikasjonen, til IntPtr, deretter kaller du Bitmap.Lock, og låser hele bildet, med Read & write.

 

Denne funksjonen gir tilbake en Bitmapdata struktur, som du må beholde, helt til du kaller Bitmap.Unlock

 

Bitmapdata.Scan0 inneholder pekeren til bildedata, så lenge dette bildet er 24bit rgb, så vil dette være en array av RBG24.

Lenke til kommentar

funksjonen jeg sender bildet til er i en importert dll fil ja.

 

Når skal jeg kalle Bitmap.Unlock?

 

Her er koden jeg har til nå:

Bitmap frame = camera.LastFrame;

 

BitmapData bmpdata = frame.LockBits(Rectangle.FromLTRB(0, 0, frame.Width, frame.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

 

camsdk.PlayBuffer(bmpdata.Scan0, frame.Width, frame.Height);

 

Jeg får da følgende feil:

Argument '1': cannot convert from 'System.IntPtr' to 'ref byte' (som da peker på PlayBuffer kallet)

 

Var det noe jeg misforstod i starten av det du skrev?

 

-Martin

Endret av martin82
Lenke til kommentar

ah, jeg har ikke tilgang til kildekoden til dll filen. camsdk.PlayBuffer() er en funksjon i dll filen, så jeg får ikke endret på den...

 

PlayBuffer() forventer å få en ref byte (i følge feilemldingen over). unsigned char* RGB24 som det står at den skal ta i mot. Alternativet mitt er å få convertert variabelen Bitmap frame til en unsigned char* (som jeg regner med er en peker til bildet?)

Lenke til kommentar

Det står noe slikt i CS filen der denne funksjonen er definert:

[DllImport("Camsdk.dll")]
public static void PlayBuffer(ref byte dst);

 

bytt denne til

[DllImport("Camsdk.dll")]
public static void PlayBuffer(IntPtr dst);

 

edit: Du kan eventuelt også beholde byte * men da må du skru på "allow unsafe code" samt å skrive

[DllImport("Camsdk.dll")]
public static unsafe void PlayBuffer(byte* dst);

Endret av GeirGrusom
Lenke til kommentar

DllImport står ingen steder. Dll filen er lagt til som en referanse til prosjektet. Et demo prosjekt har heller ikke DllImport i koden sin.

 

Her er et utdrag fra c++ kode som benytter PlayBuffer funksjonen:

LPBYTE buffer = new BYTE[320*240*3];
srand( (unsigned)time( NULL ) );
for (int i=0; i<320*240*3; i++) {
 buffer[i] = rand()%255;
}
m_pVCam->PlayBuffer(buffer, 320, 240);

 

Er en løsning da å opprette en tom byte med frame.width*frame.height*3 og putte inn verdiene for pixlene eller noe? Evt hvordan kan dette gjøres på kjappest/lurest mulig måte?

 

Takker for svar og hjelp så langt:)

Lenke til kommentar

Ah, skjønner.

 

hmmmm dette ser ut som et problem...

Du bruker en ActiveX dll hvis jeg ikke tar helt feil...

 

Dette er et interface, der char * har blitt med feiltagelse oversatt til ref byte, som ikke er riktig, det skal være byte * eller IntPtr, siden ref byte er en referanse til ett byte, og ikke en array.

Den kunne da i det minste skrevet byte[]....

 

jeg må bare tenke litt på dette, jeg vet ikke hvordan man får gjort om en byte * eller IntPtr til ref byte...

 

Dette kan sikkert endres, men jeg har ikke vært inne på COM+ DLL-er i .NET

Lenke til kommentar
funksjonen jeg sender bildet til er i en importert dll fil ja.

 

Når skal jeg kalle Bitmap.Unlock?

 

Her er koden jeg har til nå:

Bitmap frame = camera.LastFrame;

           

BitmapData bmpdata = frame.LockBits(Rectangle.FromLTRB(0, 0, frame.Width, frame.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

 

camsdk.PlayBuffer(bmpdata.Scan0, frame.Width, frame.Height);

 

Jeg får da følgende feil:

Argument '1': cannot convert from 'System.IntPtr' to 'ref byte' (som da peker på PlayBuffer kallet)

 

Var det noe jeg misforstod i starten av det du skrev?

 

-Martin

9317700[/snapback]

 

HER er noe som kan være nyttig på MSDN...

 

Her er en funksjon som gjør om Bitmap til et gråskala double 2D-array, som ser ut til å fungere for meg. Det burde være en smal sak for deg å gjøre det om slik at det returnerer en 1D-array...

 

private double[,] image2array(Bitmap bi)
       {
           Size s = bi.Size;
           double[,] arr = new double[s.Width, s.Height];

           BitmapData bitmapData1 = bi.LockBits(new Rectangle(0, 0,
                                    bi.Width, bi.Height),
                                    ImageLockMode.ReadOnly,
                                    PixelFormat.Format24bppRgb);
           int a = 0;
           unsafe
           {
               byte* imagePointer1 = (byte*)bitmapData1.Scan0;

               for (int i = 0; i < bitmapData1.Height; i++)
               {
                   for (int j = 0; j < bitmapData1.Width; j++)
                   {
                       // Convert to greyscale
                       a = (imagePointer1[0] + imagePointer1[1] +
                            imagePointer1[2]) / 3;
                       arr[i, j] = a;
                       //4 bytes per pixel
                       imagePointer1 += 3;
                   }//end for j
                   //4 bytes per pixel
                   imagePointer1 += bitmapData1.Stride -
                                   (bitmapData1.Width * 3);
               }//end for i
           }//end unsafe
           bi.UnlockBits(bitmapData1);
           return arr;
       }

Lenke til kommentar
Jojo, men problemet er ikke å hente bildedata, problemet er å prøve å kovertere byte * eller IntPtr til ref byte, så jeg tror han må endre på hvordan .NET interop saken gjør jobben sin.

9348947[/snapback]

ok, hm tenkte at jeg skulle svare på post #9...

 

Men uansett, dette virker vel garantert ikke...

            byte[] b = new byte[27];
           byte bptr = 0;
           IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(b, 0);
           bptr = (byte)ptr; 
           cam.PlayBuffer(ref bptr, 3, 3);

Lenke til kommentar

nei, fordi da lagrer den adressen i en byte, mens en IntPtr er enten 32-bit eller 64-bit, avhengig av prosessoren.

edit: litt bedre forklaring

 

Ref gir referansen til bytet, som inneholder en byte av pekeren til variabelen

 

oversatt til C-ish

byte * ptr = BitmapData.Scan0.ToPointer();

// address vil nå inneholde den første byten av pekeren
byte address = (byte)ptr;

// Gi adressen til et byte som inneholder et byte av pekeren
cam.PlayBuffer(&address,...) 

 

Tror man må gi en custom marshaler, og skrive et eget interface, men jeg har ikke lest noe om det.

 

edit2: kommet litt lenger, ser ut til at du må bruke verktøyet Tlbimp.exe som ligger i [Visual Studio]\SDK\v2.0\Bin\tlbimp.exe.

Det kan hende du må skru på /unsafe og bruke pekere, men det er ikke noe stress.

Endret av GeirGrusom
Lenke til kommentar
  • 2 uker senere...

Greit, da har de laget en ny funksjon som er definert slik:

 

HRESULT PlayBufferEx(in] VARIANT rgb24Buffer, in] unsigned long width, in] unsigned long height);

Just like PlayBuffer, but support automation, you should use this in C#/VB/Delphi instead of PlayBuffer, rgb24Buffer is a BYTE array, whose size must >= (width*24+31)/32*4*height.

 

Her er et eksempel i C#:

private void btnPlayBuffer_Click(object sender, System.EventArgs e)
 {
 	btnStop_Click(sender, e);

 	byte[] buffer = new byte [320*240*3];
 	Random rdm = new Random();
 	for (int i=0; i<320*240*3; i++) 
 	{
   buffer[i] = (byte)rdm.Next(255);
 	}
 	vcam.PlayBufferEx(buffer, 320, 240);
 }

 

Jeg er ingen reser i C# (enda), men regner med at det ikke er så vanskelig å få slengt en Bitmap om til en 1 dim variabel og ikke 3 dim som den er nå (hvis jeg har forstått det riktig nå da) ?

 

-Martin

Lenke til kommentar
  • 2 måneder senere...

Da er jeg tilbake etter en liten pause fra prosjektet :)

 

Jeg tok utgangspunkt i post 11 men da får jeg denne feilmeldingen:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt. (AccessViolationException)

 

Det skjer på denne linjen:

camsdk.PlayBufferEx(arr, (uint)s.Width, (uint)s.Height);

 

Endringene jeg gjorde i koden fra post 11 er å gjøre arr om til en-dim byte[høyde*bredde] og caste om a til byte. Arr variabelen inneholder alle pixlene i en en-dim array og burde være ok slik jeg ser det.

 

tips til hva det kan være?

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...