2009-07-24 2 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를 사용) 일부 해결 방법을 찾기 위해 노력하고 볼 수 있지만, '아무튼 키워드가 unsafe 필요합니다. unsafe이 두드러지기 때문에 그다지 유해하지 않습니다.

예를 들어, 물론 포인터 연산 부분 전체를 C DLL 또는 C++/CLI 어셈블리로 옮기고 직접 C# 또는 P/Invoke를 통해 호출 할 수 있습니다. 그러나 요점은 무엇입니까?

1

드래그 앤 드롭에 관한 어떤 것도 안전하지 않습니다. 이미지 처리 코드에서 포인터 조작입니다. 직접 코딩하는 대신 프레임 워크에서 기존 방법 중 하나를 사용하는 것이 어떻습니까?

  • 사용 System.Drawing.Imaging SetRemapTable (example here)는 컬러지도를 통해 투명성을 대체한다.

  • pixel shaders으로 처리 할 수 ​​있는지 확인하면 GPU를 사용하기 때문에 안전 코드가 훨씬 향상 될 수 있습니다.

+0

고마워요! 여기서 BitmapData를 다루므로 함수가 비트 맵을 그리지 않을 때 ColorMap을 사용하는 방법을 잘 이해하지 못합니다. – Luke

+0

당신이하고있는 일에 대해 더 많은 맥락을 제시 할 수 있습니까? 이미지 파일을 응용 프로그램에 넣고 그래픽 조작을하고 있습니까? –

+0

이것은 쉘 드래그 앤 드롭 (위 기사의 전체 코드) 용입니다. 위의 함수 ReplaceTransparentPixelsWithTransparentKey를 통해 해결 : 드래그 이미지는 alpha가 0 일 때를 제외하고는 전체 32 비트 색상으로 작동합니다. 그런 다음 해당 픽셀을 검정색으로 렌더링합니다. 그래서 우리는 패스를 만들고 모든 픽셀을 투명성 키 색상으로 설정합니다. 이것은 현재 32 비트 픽셀 색상에만 구현됩니다. – Luke