2010-04-08 4 views
2

이 질문은 1042830이지만 MonoTouch에만 해당합니다. IntPtr을 할당하는 것보다 CGBitmapContext를 사용하여 드로잉을하고 적절한 오프셋에서 바이트를 읽는 것보다 더 안전한 방법이 있습니까? 당신의 자신의 질문에 대답 정결 있는지 모르겠어요UIImage (MonoTouch)에 대한 픽셀 알파 값 검색

답변

5

:하지만,

protected CGBitmapContext CreateARGBBitmapContext(CGImage inImage) 
    { 
     var pixelsWide = inImage.Width; 
     var pixelsHigh = inImage.Height; 
     var bitmapBytesPerRow = pixelsWide * 4; 
     var bitmapByteCount = bitmapBytesPerRow * pixelsHigh; 
     //Note implicit colorSpace.Dispose() 
     using(var colorSpace = CGColorSpace.CreateDeviceRGB()) 
     { 
      //Allocate the bitmap and create context 
      var bitmapData = Marshal.AllocHGlobal(bitmapByteCount); 
      //I think this is unnecessary, as I believe Marshal.AllocHGlobal will throw OutOfMemoryException 
      if(bitmapData == IntPtr.Zero) 
      { 
       throw new Exception("Memory not allocated."); 
      } 

      var context = new CGBitmapContext(bitmapData, pixelsWide, pixelsHigh, 8, 
               bitmapBytesPerRow, colorSpace, CGImageAlphaInfo.PremultipliedFirst); 
      if(context == null) 
      { 
       throw new Exception("Context not created"); 
      } 
      return context; 
     } 
    } 

    //Store pixel data as an ARGB Bitmap 
    protected IntPtr RequestImagePixelData(UIImage inImage) 
    { 
     imageSize = inImage.Size; 
     CGBitmapContext ctxt = CreateARGBBitmapContext(inImage.CGImage); 
     var rect = new RectangleF(0.0f, 0.0f, imageSize.Width, imageSize.Height); 
     ctxt.DrawImage(rect, inImage.CGImage); 
     var data = ctxt.Data; 
     return data; 
    } 

    //Note: Unsafe code 
    unsafe byte GetByte(int offset, IntPtr buffer) 
    { 
     byte* bufferAsBytes = (byte*) buffer; 
     return bufferAsBytes[offset]; 
    } 

    //Example of using it... 
    public override bool PointInside (PointF point, UIEvent uievent) 
    { 
     //Lazy initialize 
     if(bitmapData == IntPtr.Zero) 
     { 
      bitmapData = RequestImagePixelData(Image); 
     } 

     //Check for out of bounds 
     if(point.Y < 0 || point.X < 0 || point.Y > Image.Size.Height || point.X > Image.Size.Width) 
     { 
      return false; 
     } 
     var startByte = (int) ((point.Y * this.Image.Size.Width + point.X) * 4); 

     byte alpha = GetByte(startByte, this.bitmapData); 
     Console.WriteLine("Alpha value of {0}, {1} is {2}", point.X, point.Y, alpha); 
        ...etc...