Gå til innhold

Anbefalte innlegg

Skrevet

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

Videoannonse
Annonse
Skrevet

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.

Skrevet (endret)

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
Skrevet (endret)

Litt, der du har skrevet "ref byte" i DllImport funksjonen, bytter du ut med IntPtr.

 

edit: Pass på at du kaller Lock før du tegner bildet til Graphics objekt.

Endret av GeirGrusom
Skrevet

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?)

Skrevet (endret)

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
Skrevet

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:)

Skrevet

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

Skrevet

Setter pris på hjelpen:)

De som har laget SDK'en henviser bare til å søke på nettet etter konvertering fra Bitmap til RGB24. Og har ikke funnet noe fornuftig som hjelper...

Skrevet
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;
       }

Skrevet

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.

Skrevet
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);

Skrevet (endret)

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
  • 2 uker senere...
Skrevet

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

  • 2 måneder senere...
Skrevet

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?

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...