1

如何在 WinRT 中裁剪/剪辑图像。我在 Windows 8 窗口中完全填充了图像。我需要从中心剪辑/裁剪图像,并且需要将两个图像部分显示为两个单独的网格。我如何通过 Windows 8 做同样的事情。是否可以在不使用 WritableBitmapEx 的情况下实现这一点。如果不是,如何通过 WritableBitmapEx 执行相同的操作。

4

3 回答 3

3

实际上有很多方法可以做到这一点,每种方法都有一些优点和缺点。

  • WriteableBitmapEx似乎是一个流行的解决方案。我在WinRT XAML Toolkit. 两者本质上都是从完整的图像位图中复制像素块。这可能不是最快的方法,但如果您想要一个开箱即用的解决方案 - 它是一种易于使用的解决方案。您需要复制像素,因此您没有在操作时优化内存使用,因此可能会更快地在非常大的图像上耗尽内存。如果需要,您可以轻松地重新裁剪,但最终将结果保存到图像文件中。
  • Jan 推荐的BitmapDecoder解决方案是我经常使用的解决方案,因为它是平台的一部分,用本机代码编写并且可能经过高度优化,并且您不复制像素,但如果您想重新裁剪 - 您需要再次解码图像.
  • Xyroid 对Clip几何的建议是一种快速仅显示的解决方案。您实际上并没有修改内存中的位图 - 您只需在屏幕上显示它的一个区域。然后,您需要将整个图像保存在内存中,如果您想保存它 - 您仍然需要更新位图以保存它 - 通过使用前两种解决方案中的一种,或者RenderTargetBitmap.Render()如果屏幕分辨率对您来说足够,则可以使用。虽然更新屏幕上显示的裁剪区域以便快速预览,但应该非常快。
  • 另一种是用 aRectangle填充ImageBrush,您可以在其中应用 aTransform并指定Rectangle大小来控制裁剪。它与解决方案非常相似,Clip而不是剪切图像,在这种情况下,您实际上必须使用Tramsform(您也可以在Clip-上执行RectangleGeometry)。对于快速更新 - 使用 aTransform实际上可能比更新几何图形要快一些,并且还支持缩放和旋转。
于 2014-04-01T07:19:36.000 回答
1

您可以使用 Bitmapdecoder 和 BitmapTransform 类。这个例子非常适合裁剪。您还应该阅读本教程以进行剪辑。基本上,您实现了这样的功能(取自示例):

async public static Task<ImageSource> GetCroppedBitmapAsync(StorageFile originalImgFile, Point startPoint, Size corpSize, double scale) 
{ 


if (double.IsNaN(scale) || double.IsInfinity(scale)) 
{ 
    scale = 1; 
} 


// Convert start point and size to integer. 
uint startPointX = (uint)Math.Floor(startPoint.X * scale); 
uint startPointY = (uint)Math.Floor(startPoint.Y * scale); 
uint height = (uint)Math.Floor(corpSize.Height * scale); 
uint width = (uint)Math.Floor(corpSize.Width * scale); 


using (IRandomAccessStream stream = await originalImgFile.OpenReadAsync()) 
{ 


    // Create a decoder from the stream. With the decoder, we can get  
    // the properties of the image. 
    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream); 

    // The scaledSize of original image. 
    uint scaledWidth = (uint)Math.Floor(decoder.PixelWidth * scale); 
    uint scaledHeight = (uint)Math.Floor(decoder.PixelHeight * scale); 



    // Refine the start point and the size.  
    if (startPointX + width > scaledWidth) 
    { 
        startPointX = scaledWidth - width; 
    } 


    if (startPointY + height > scaledHeight) 
    { 
        startPointY = scaledHeight - height; 
    } 


    // Create cropping BitmapTransform and define the bounds. 
    BitmapTransform transform = new BitmapTransform(); 
    BitmapBounds bounds = new BitmapBounds(); 
    bounds.X = startPointX; 
    bounds.Y = startPointY; 
    bounds.Height = height; 
    bounds.Width = width; 
    transform.Bounds = bounds; 


    transform.ScaledWidth = scaledWidth; 
    transform.ScaledHeight = scaledHeight; 

    // Get the cropped pixels within the bounds of transform. 
    PixelDataProvider pix = await decoder.GetPixelDataAsync( 
        BitmapPixelFormat.Bgra8, 
        BitmapAlphaMode.Straight, 
        transform, 
        ExifOrientationMode.IgnoreExifOrientation, 
        ColorManagementMode.ColorManageToSRgb); 
    byte[] pixels = pix.DetachPixelData(); 


    // Stream the bytes into a WriteableBitmap 
    WriteableBitmap cropBmp = new WriteableBitmap((int)width, (int)height); 
    Stream pixStream = cropBmp.PixelBuffer.AsStream(); 
    pixStream.Write(pixels, 0, (int)(width * height * 4)); 


    return cropBmp; 
} 


} 
于 2014-04-01T06:59:54.407 回答
1

XAML 静态方式,如果我的屏幕尺寸是 1366x768 并且我想剪辑中心 400x300 图像,那么我会这样做。

<Image Source="Assets/img100.png" Stretch="Fill">
    <Image.Clip>
        <RectangleGeometry Rect="483,234,400,300" />
    </Image.Clip>
</Image>

动态方式。尽管高度和宽度是固定的,但它会对所有分辨率进行中心裁剪。

double _Height = 300, _Width = 400;
img.Clip = new RectangleGeometry 
{
    Rect = new Rect((Window.Current.Bounds.Width - _Width) / 2, (Window.Current.Bounds.Height - _Height) / 2, _Width, _Height)
};

别忘了结账...

如何在 C# WinRT/winmd 中调整图像大小?

用矩形裁剪图像

使用动态矩形坐标裁剪图像

文件选择器后的裁剪工具(例如拍照后的裁剪工具)

于 2014-04-01T07:00:42.857 回答