2009-07-24 7 views
1

WPFプロジェクト内でShell Style Drag and Drop in .NET - Part 3に示すコード例の使用を検討しています。サンプルプロジェクトはうまく動作します、それは素晴らしい記事ですので、それをチェックしてください!WPFシェルドラッグドロップサンプル - 安全でないコード

しかし、プロジェクトにコードを移動すると、「安全でないコードは/ unsafeでコンパイルした場合にのみ表示される」というコンパイル時にエラーが表示されます。コンパイルオプションを変更することはできますが、コードがそこにあります。安全でないコードは次のとおりです。

このコードを安全にするにはどうすればよいですか?私はこの分野での経験は本当にありません。

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

次のように、このコードを呼び出す関数であり、多分ReplaceTransparentPixelsWithTransparentKey機能は、他の方法で完全に除去することができます。何か案は?

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

答えて

1

重要なパフォーマンスヒットを望んでいない場合は、実際には他のオプションはありません。

あなたは本当にどちらか、unsafeキーワードと関連するコンパイラスイッチを怖がってはならない - 私は頻繁に人々が「(Marshal、またはのWin32 APIを使用して例えば)が、doesnのまだ危険なあるいくつかの回避策を見つけようとして見ますtはunsafeキーワードが必要です。 unsafeが目立っているので、それは意味がありません。もしあれば、より有害です。

この場合、たとえばポインタ演算部分全体をC DLLまたはC++/CLIアセンブリに移動し、C#から直接またはP/Invokeを使用して呼び出すことができます。しかし、何がポイントでしょうか?

1

ドラッグアンドドロップについては何も危険ですが、それは画像処理コード内のポインタ操作です。これを自分でコーディングするのではなく、フレームワーク内の既存のメソッドの1つを使用してみましょう。

  • 使用System.Drawing.Imaging SetRemapTable(example here)カラーマップを経由して透明性を交換します。

  • pixel shadersでこれを処理できるかどうかは、GPUを活用するため安全コードがより良くなる可能性が高いことを参照してください。

+0

ありがとうございます!ここではBitmapDataを扱っていますので、関数がビットマップを描画していないときにColorMapをどのように使用するのかよく分かりません。 – Luke

+0

あなたは何をやっているのより多くのコンテキストを与えることができますか?イメージファイルをアプリケーションにドロップして、それらのグラフィック操作をしていますか? –

+0

これは、シェルのドラッグアンドドロップ(上記の記事の中の完全なコード)です。上の関数ReplaceTransparentPixelsWithTransparentKeyを解決する:ドラッグイメージは、アルファがゼロに等しい場合を除いて、完全な32ビットカラーで動作するようです。次に、それらのピクセルを黒くレンダリングします。そこで、パスを作成し、すべてのピクセルを透過キーカラーに設定します。これは現在32ビットピクセルカラーに対してのみ実装されています。 – Luke

関連する問題