StretchBlt inversează ocazional imaginea atunci când nu ar trebui

Am o problemă folosind StretchBlt (sau BitBlt) pentru a copia o imagine dintr-o PictureBox într-o Bitmap pentru a fi utilizată în crearea unui fișier AVI. Fișierul AVI este un aspect lipsit de importanță. Cred că pot să afișez Bitmap-ul pe alt PictureBox și să văd problema.

Problema este că ocazional (nu de multe ori) o singură imagine este flipped (oglindită pe axa X, niciodată axa Y). Nu sunt sigur dacă este o problemă cunoscută cu StretchBlt Nu am găsit încă nici o mențiune sau dacă fac ceva greșit. Rețineți că acest lucru nu se datorează funcționalității dorite cu StretchBlt de "Dacă semnele de înălțime sau lățime de sursă și destinație sunt diferite, atunci se creează o imagine în oglindă".

UPDATE: Am schimbat lucrurile pentru a forța sursa/destinația să aibă aceeași dimensiune și folosesc BitBlt cu același comportament.

Am inclus un cod (c #), sper ca toate partile importante.

Trecând prin cod, pot vedea acest lucru pentru o singură imagine care are exact aceleași informații care sunt transmise la StretchBlt (altul decât hdc-ul pentru a copia) ca imaginea anterioară și următoarea imagine (și următoarea, următoare), toate acestea amenda. Nu se întâmplă adesea și nu văd nici un motiv atunci când o face. Sau o modalitate de a detecta sa întâmplat (așa că o pot întoarce). Am o muncă în jurul valorii de care nu utilizează StretchBlt, dar este mult mai lent și într-adevăr degrada performanța.

Un alt bit posibil: această imagine răsturnată este rară în utilizarea normală (mai puțin de 1 din 100 de cadre). Dar când alergați în IDE, trecând prin imagine prin imagine, se întâmplă foarte regulat (poate 1 din 10).

Orice idei ce ar putea cauza acest lucru sau ce aș putea face greșit? Sau alte metode FAST pentru a copia Bitmap-ul, inclusiv redimensionarea. NOTĂ: Bitmap-urile variază în funcție de dimensiune (nu se poate folosi BitBlt), dar nu de mult.

Mulțumesc!

Kate

// --- Import statement
[DllImport("GDI32.DLL", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    public static extern bool StretchBlt( 
IntPtr hdcDest, int nXDest, int nYDest, int nDestWidth, int nDestHeight,
IntPtr hdcSrc, int nXSrc, int nYSrc, int nSrcWidth, int nSrcHeight, Int32 dwRop );

// --- A small class for creating/storing Bitmap and Graphics objects, which get reused
public class CAviImageInfo
  {
    private Bitmap    mAviBitmap = null;
    private Graphics  mAviGraphics = null;

    public CAviImageInfo(int width, int height )
    {
      mAviBitmap = new Bitmap(width, height);
      mAviGraphics = Graphics.FromImage(mAviBitmap);
    }
    ~CAviImageInfo()
    {
      mAviGraphics.Dispose();
      mAviGraphics = null;
    }
    public Bitmap AviBitmap
    { get { return mAviBitmap; } }
    public Graphics AviGraphics
    { get { return mAviGraphics;  } }
}  

// --- Two PictureBoxs placed on form at design time (one is just to watch for these mirrored images):
PictureBox mMainPictureBox;//--- Displays the images to be copied
PictureBox DebugPictureBox;

//  --- The following done one time:
Graphics  mMainPictureBoxGraphics = mMainPictureBox.CreateGraphics();
IntPtr    mMainPictureBoxHdc      = mMainPictureBoxGraphics.GetHdc();

// --- Method that does the copying.  Called each time image on panel is updated.
Public void UpdateAviRecording()
{
 //--- Gets unused Bitmap and Graphics objects (these are reused)
  CAviImageInfo aviImageInfo = GetUnusedAviImageInfo();

  IntPtr destinationHdc = aviImageInfo.AviGraphics.GetHdc();

  StretchBlt(
    destinationHdc, 
    0, 0, aviImageInfo.AviBitmap.Width, aviImageInfo.AviBitmap.Height,
    mMainPictureBoxHdc, 
    0, 0, mMainPictureBox.Width, mMainPictureBox.Height, SRCCOPY);

 //--- Show the copied Bitmap on the debug PictureBox 
 //--- (normally would pass it to be written to avi file)
  DebugPictureBox.Image = aviImageInfo.AviBitmap;
  DebugPictureBox.Refresh();

  aviImageInfo.AviGraphics.ReleaseHdc(destinationHdc);      
}
0
Ați citit docs ? "StretchBlt creează o imagine oglindă a unui bitmap dacă semnele parametrilor nWidthSrc și nWidthDest sau nHeightSrc și nHeightDest < nWidthSrc și nWidthDest au semne diferite, funcția creează o imagine oglindă a bitmapului de-a lungul axei x. Dacă nHeightSrc și nHeightDest au semne diferite, funcția creează o imagine oglindă a bitmapului de-a lungul axei y. "
adăugat autor GSerg, sursa
Da - ar fi trebuit să adaug că sunt sigur că NU se datorează acelei funcționalități.
adăugat autor KateToo, sursa
Se întâmplă pe mai multe mașini.
adăugat autor KateToo, sursa
Este aceasta repetabilă pe alte mașini sau are loc doar pe mașina dvs.?
adăugat autor Dan Bryant, sursa
adăugat autor Hans Passant, sursa

1 răspunsuri

aceasta este doar o sugestie. Nu știu dacă va funcționa ..

Setați lățimea și înălțimea folosind Math.Abs ​​() a imaginii în apel la StretchBlt. Acest lucru ar putea împiedica posibila corupție a memoriei și inversarea semnelor (după cum a menționat GSerg). ..

StretchBlt(
    destinationHdc, 
    0, 0, Math.Abs(aviImageInfo.AviBitmap.Width), 
Math.Abs(aviImageInfo.AviBitmap.Height),
    mMainPictureBoxHdc, 
    0, 0, Math.Abs(mMainPictureBox.Width), 
Math.Abs(mMainPictureBox.Height), SRCCOPY);
0
adăugat