2010-05-14 6 views
2

캔버스 배경이 lineargradientbrush로 설정되어 있습니다 .... 어떻게 특정 마우스 포인트 (x, y)에서이 배경 색상을 추출 할 수 있습니까?캔버스 배경색 검색을위한 배경

나는 BitmappedImage이 할 수있는 좋은 ...이 ...하지만 캔버스에 대해 확실하지 픽셀로

크게 미리

감사합니다,

U.

답변

0

WPF는 V입니다 : 마이크로 소프트 지원, 마우스 커서의 픽셀의 색을 찾는 것에 대해이 문서가 ector를 기반으로하므로 비트 맵 데이터 구조 내에서를 제외하고는 "픽셀"개념을 실제로 갖고 있지 않습니다. 그러나 1x1 직사각형 영역 (일반적으로 물리적 화면에서 단일 픽셀로 표시됨)을 포함하여 직사각형 영역의 평균 색상을 결정할 수 있습니다. 이 코드가 작동

Color pixelColor = GetPixelColor(canvas, x, y); 

방법은 다음과 같습니다 :

  1. 그것은 1x1 크기의 사각형을 채 웁니다

    다음
    public Color GetPixelColor(Visual visual, int x, int y) 
    { 
        return GetAverageColor(visual, new Rect(x,y,1,1)); 
    } 
    
    public Color GetAverageColor(Visual visual, Rect area) 
    { 
        var bitmap = new RenderTargetBitmap(1,1,96,96,PixelFormats.Pbgra32); 
        bitmap.Render(
        new Rectangle 
        { 
         Width = 1, Height = 1, 
         Fill = new VisualBrush { Visual = visual, Viewbox = area } 
        }); 
        var bytes = new byte[4]; 
        bitmap.CopyPixels(bytes, 1, 0); 
        return Color.FromArgb(bytes[0], bytes[1], bytes[2], bytes[3]); 
    } 
    

    당신이 그것을 사용하는 것이 방법입니다

    다음은이 작업을 수행하는 방법 캔버스의 선택된 영역을 보여주는 VisualBrush 사용하기

  2. 1 픽셀 비트 맵
  3. 그것은 렌더링 된 비트 맵
+6

코드를 사용해 보았지만 System.ArgumentOutOfRangeException이 발생했습니다. Sth like : "매개 변수 값은 bitmap.CopyPixels (바이트, 1, 0)에서 4보다 작을 수 없습니다." 내 매개 변수는 x = 57, y = 78입니다. bitmap.CopyPixels (bytes, 4, 0)을 사용하면 "바이트"는 항상 "0"을 유지하므로 투명 검정색을 나타냅니다. – Torsten

0

레이 번스에 의해 게시 코드는 나를 위해 작동하지 않았다하지만 올바른 경로를 날 실망 이어질 않은에서 픽셀의 색상을 얻을에 사각형입니다. 몇 가지 연구와 실험을 마친 후 문제점을 bitmap.Render (...) 구현과 사용하는 Viewbox로 지정했습니다.

참고 : .Net 3.5와 WPF를 사용하고 있으므로 다른 버전의 .Net에서 작동 할 수도 있습니다.

코드를 설명하기 위해 의도적으로 의견을 남겼습니다.

원본 크기의 Visual Height와 Width를 기준으로 Viewbox를 표준화해야합니다.

DrawingVisual은 렌더링되기 전에 DrawingContext를 사용하여 그려야합니다.

RenderTargetBitmap 메서드에서 PixelFormats.Default와 PixelFormats.Pbgra32를 모두 시도했습니다. 내 테스트 결과는 두 사람 모두 동일했습니다.

다음은 코드입니다. 당신이 getScreenDPI (에 관심이 있다면

public static Color GetPixelColor(Visual visual, Point pt) 
    { 
     Point ptDpi = getScreenDPI(visual); 

     Size srcSize = VisualTreeHelper.GetDescendantBounds(visual).Size; 

     //Viewbox uses values between 0 & 1 so normalize the Rect with respect to the visual's Height & Width 
     Rect percentSrcRec = new Rect(pt.X/srcSize.Width, pt.Y/srcSize.Height, 
             1/srcSize.Width, 1/srcSize.Height); 

     //var bmpOut = new RenderTargetBitmap(1, 1, 96d, 96d, PixelFormats.Pbgra32); //assumes 96 dpi 
     var bmpOut = new RenderTargetBitmap((int)(ptDpi.X/96d), 
              (int)(ptDpi.Y/96d), 
              ptDpi.X, ptDpi.Y, PixelFormats.Default); //generalized for monitors with different dpi 

     DrawingVisual dv = new DrawingVisual(); 
     using (DrawingContext dc = dv.RenderOpen()) 
     { 
      dc.DrawRectangle(new VisualBrush { Visual = visual, Viewbox = percentSrcRec }, 
          null, //no Pen 
          new Rect(0, 0, 1d, 1d)); 
     } 
     bmpOut.Render(dv); 

     var bytes = new byte[4]; 
     int iStride = 4; // = 4 * bmpOut.Width (for 32 bit graphics with 4 bytes per pixel -- 4 * 8 bits per byte = 32) 
     bmpOut.CopyPixels(bytes, iStride, 0); 

     return Color.FromArgb(bytes[0], bytes[1], bytes[2], bytes[3]); 
    } 

)는 코드가 작동 :

public static Point getScreenDPI(Visual v) 
    { 
     //System.Windows.SystemParameters 
     PresentationSource source = PresentationSource.FromVisual(v); 
     Point ptDpi; 
     if (source != null) 
     { 
      ptDpi = new Point(96.0 * source.CompositionTarget.TransformToDevice.M11, 
           96.0 * source.CompositionTarget.TransformToDevice.M22 ); 
     } 
     else 
      ptDpi = new Point(96d, 96d); //default value. 

     return ptDpi; 
    } 

그리고 사용은 레이의 유사합니다. 캔버스에있는 MouseDown에 대해 여기에 표시합니다.

private void cvsTest_MouseDown(object sender, MouseButtonEventArgs e) 
    { 
     Point ptClicked = e.GetPosition(cvsTest); 

     if (e.LeftButton.Equals(MouseButtonState.Pressed)) 
     { 
      Color pxlColor = ImagingTools.GetPixelColor(cvsTest, ptClicked); 
      MessageBox.Show("Color String = " + pxlColor.ToString()); 
     } 
    } 

FYI, ImagingTools는 이미징과 관련된 정적 메소드를 유지하는 클래스입니다.