2009-07-24 11 views
1

Ich habe erwogen, das Codebeispiel unter Shell Style Drag and Drop in .NET - Part 3 in einem WPF-Projekt zu verwenden. Das Beispielprojekt funktioniert gut, es ist ein großartiger Artikel, also schaut es euch an!WPF-Shell-Drag-Drop-Beispiel - Unsicherer Code

Wenn ich jedoch den Code in mein Projekt verschiebe, erhalte ich einen Fehler beim Kompilieren "Unsicherer Code erscheint möglicherweise nur beim Kompilieren mit/unsichere" Ich verstehe, dass ich nur die Kompilierungsoptionen ändern könnte Code drin. Der unsichere Code ist wie folgt.

Wie kann ich diesen Code sicher machen? Ich habe keine Erfahrung in diesem Bereich.

/// <summary> 
/// Replaces any pixel with a zero alpha value with the specified transparency key. 
/// </summary> 
/// <param name="bmpData">The bitmap data in which to perform the operation.</param> 
/// <param name="transKey">The transparency color. This color is rendered transparent 
/// by the DragDropHelper.</param> 
/// <remarks> 
/// This function only supports 32-bit pixel formats for now. 
/// </remarks> 
private static void ReplaceTransparentPixelsWithTransparentKey(BitmapData bmpData, DrawingColor transKey) 
{ 
    DrawingPixelFormat pxFormat = bmpData.PixelFormat; 

    if (DrawingPixelFormat.Format32bppArgb == pxFormat 
     || DrawingPixelFormat.Format32bppPArgb == pxFormat) 
    { 
     int transKeyArgb = transKey.ToArgb(); 

     // We will just iterate over the data... we don't care about pixel location, 
     // just that every pixel is checked. 
     unsafe 
     { 
      byte* pscan = (byte*)bmpData.Scan0.ToPointer(); 
      { 
       for (int y = 0; y < bmpData.Height; ++y, pscan += bmpData.Stride) 
       { 
        int* prgb = (int*)pscan; 
        for (int x = 0; x < bmpData.Width; ++x, ++prgb) 
        { 
         // If the alpha value is zero, replace this pixel's color 
         // with the transparency key. 
         if ((*prgb & 0xFF000000L) == 0L) 
          *prgb = transKeyArgb; 
        } 
       } 
      } 
     } 
    } 
    else 
    { 
     // If it is anything else, we aren't supporting it, but we 
     // won't throw, cause it isn't an error 
     System.Diagnostics.Trace.TraceWarning("Not converting transparent colors to transparency key."); 
     return; 
    } 
} 

Die Funktion dieser Code Aufruf ist wie folgt, vielleicht die ReplaceTransparentPixelsWithTransparentKey Funktion durch ein anderes Verfahren vollständig entfernt werden kann. Irgendwelche Ideen?

/// <summary> 
/// Gets a System.Drawing.Bitmap from a BitmapSource. 
/// </summary> 
/// <param name="source">The source image from which to create our Bitmap.</param> 
/// <param name="transparencyKey">The transparency key. This is used by the DragDropHelper 
/// in rendering transparent pixels.</param> 
/// <returns>An instance of Bitmap which is a copy of the BitmapSource's image.</returns> 
private static Bitmap GetBitmapFromBitmapSource(BitmapSource source, Color transparencyKey) 
{ 
    // Copy at full size 
    Int32Rect sourceRect = new Int32Rect(0, 0, source.PixelWidth, source.PixelHeight); 

    // Convert to our destination pixel format 
    DrawingPixelFormat pxFormat = ConvertPixelFormat(source.Format); 

    // Create the Bitmap, full size, full rez 
    Bitmap bmp = new Bitmap(sourceRect.Width, sourceRect.Height, pxFormat); 
    // If the format is an indexed format, copy the color palette 
    if ((pxFormat & DrawingPixelFormat.Indexed) == DrawingPixelFormat.Indexed) 
     ConvertColorPalette(bmp.Palette, source.Palette); 

    // Get the transparency key as a System.Drawing.Color 
    DrawingColor transKey = transparencyKey.ToDrawingColor(); 

    // Lock our Bitmap bits, we need to write to it 
    BitmapData bmpData = bmp.LockBits(
     sourceRect.ToDrawingRectangle(), 
     ImageLockMode.ReadWrite, 
     pxFormat); 
    { 
     // Copy the source bitmap data to our new Bitmap 
     source.CopyPixels(sourceRect, bmpData.Scan0, bmpData.Stride * sourceRect.Height, bmpData.Stride); 

     // The drag image seems to work in full 32-bit color, except when 
     // alpha equals zero. Then it renders those pixels at black. So 
     // we make a pass and set all those pixels to the transparency key 
     // color. This is only implemented for 32-bit pixel colors for now. 
     if ((pxFormat & DrawingPixelFormat.Alpha) == DrawingPixelFormat.Alpha) 
      ReplaceTransparentPixelsWithTransparentKey(bmpData, transKey); 
    } 
    // Done, unlock the bits 
    bmp.UnlockBits(bmpData); 

    return bmp; 
} 

Antwort

1

Wenn Sie keinen signifikanten Leistungseinbruch wünschen, dann haben Sie keine anderen Optionen.

Sie sollten wirklich nicht von unsafe Schlüsselwort und dem zugehörigen Compiler-Schalter Angst, entweder - ich oft sehen, wie Menschen versuchen, etwas Abhilfe zu finden, die noch unsicher (zB mit Marshal oder Win32 API) ist, aber doesn‘ t benötigen unsafe Schlüsselwort. Das hat keinen Sinn - wenn überhaupt, ist es schädlicher, weil unsafe herausragt. In diesem Fall könnten Sie natürlich den gesamten Zeigerarithmetikteil in eine C DLL oder C++/CLI-Assembly verschieben und diese direkt aus C# oder über P/Invoke aufrufen. Aber was wäre der Sinn?

1

Nichts über Drag & Drop ist unsicher, es ist die Zeigerbearbeitung im Bildverarbeitungscode. Anstatt dies selbst zu programmieren, warum nicht eine der vorhandenen Methoden im Framework verwenden?

  • Verwenden System.Drawing.Imaging SetRemapTable (example here) die Transparenz über eine Farbkarte zu ersetzen.

  • Sehen Sie, wenn Sie damit umgehen können mit pixel shaders, die in sicheren Code führen würde und würde wahrscheinlich eine viel bessere Leistung, weil es die GPU nutzen würde.

+0

Danke! Ich habe hier mit den BitmapData zu tun, also verstehe ich nicht ganz, wie ich die ColorMap verwenden würde, wenn die Funktion die Bitmap nicht zeichnet. – Luke

+0

Können Sie mehr Kontext von dem, was Sie tun, geben? Ziehen Sie Bilddateien in eine Anwendung und führen sie grafische Manipulationen durch? –

+0

Dies ist für Shell Drag & Drop (vollständiger Code innerhalb des obigen Artikels). Die obige Funktion ReplaceTransparentPixelsWithTransparentKey zum Auflösen: Das Drag-Image scheint in voller 32-Bit-Farbe zu arbeiten, außer wenn Alpha gleich Null ist. Dann rendert es diese Pixel in Schwarz. Also machen wir einen Durchgang und setzen alle diese Pixel auf die Transparenz-Schlüsselfarbe. Dies wird nur für 32-Bit-Pixelfarben vorerst implementiert. – Luke

Verwandte Themen