2016-12-20 2 views
2

SoftwareBitmap은 UWP에서 새로운 기능입니다. 먼저 다음과 같이 시작합니다.SoftwareBitmap의 크기를 조정하는 방법은 무엇입니까?

var softwareBitmap = EXTERNALVALUE; 

// do I even need a writeable bitmap? 
var writeableBitmap = new WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight); 
softwareBitmap.CopyToBuffer(writeableBitmap.PixelBuffer); 

// maybe use BitmapDecoder? 

나는 실종됐다. 고맙습니다.

참고로, 나는 BitmapImage을 의미하지 않습니다. 내 말은 SoftwareBitmap입니다.

+0

모든 언어가 될 수 있습니다. 이미지 크기 조정은 간단하지 않습니다. 몇 가지 C 언어 알고리즘이 있습니다 : https://github.com/MalcolmMcLean/babyxrc/tree/master/src –

+0

저는 과거에 이것을하기 위해 ImageMagick을 사용했습니다. 그것은 꽤 똑바로 앞으로 https://magick.codeplex.com/ –

+0

BitmapTransform에 ScaledHeight 및 ScaledWidth 메서드를 봐도 될까요? https://msdn.microsoft.com/library/windows/apps/br226254#methods 내 지역이 아니므로 Google과 비슷합니다. – JohnLBevan

답변

2

는 목발처럼 보이지만 그것은 당신의 문제를 해결할 수 있습니다 : 당신은 nuget에서 Win2D 패키지를 얻을 수 있습니다

private async Task<SoftwareBitmap> ResizeSoftwareBitmap(SoftwareBitmap softwareBitmap, double scaleFactor) 
    { 
     var resourceCreator = CanvasDevice.GetSharedDevice(); 
     var canvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(resourceCreator, softwareBitmap); 
     var canvasRenderTarget = new CanvasRenderTarget(resourceCreator, (int)(softwareBitmap.PixelWidth * scaleFactor), (int)(softwareBitmap.PixelHeight * scaleFactor), 96); 

     using (var cds = canvasRenderTarget.CreateDrawingSession()) 
     { 
      cds.DrawImage(canvasBitmap, canvasRenderTarget.Bounds); 
     } 

     var pixelBytes = canvasRenderTarget.GetPixelBytes(); 

     var writeableBitmap = new WriteableBitmap((int)(softwareBitmap.PixelWidth * scaleFactor), (int)(softwareBitmap.PixelHeight * scaleFactor)); 
     using (var stream = writeableBitmap.PixelBuffer.AsStream()) 
     { 
      await stream.WriteAsync(pixelBytes, 0, pixelBytes.Length); 
     } 

     var scaledSoftwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, (int)(softwareBitmap.PixelWidth * scaleFactor), (int)(softwareBitmap.PixelHeight * scaleFactor)); 
     scaledSoftwareBitmap.CopyFromBuffer(writeableBitmap.PixelBuffer); 

     return scaledSoftwareBitmap; 
    } 

합니다.

2

나는 ScaleEffect으로 몇 가지 시도를했으며 아래의 확장 방법으로 끝 냈습니다. 사실이 방법은 더 많은 작업이 필요하지만 어쨌든 더 멀리 움직이는 데 도움이됩니다. 여기

public static SoftwareBitmap Resize(this SoftwareBitmap softwareBitmap, float newWidth, float newHeight) 
{ 
    using (var resourceCreator = CanvasDevice.GetSharedDevice()) 
    using (var canvasBitmap = CanvasBitmap.CreateFromSoftwareBitmap(resourceCreator, softwareBitmap)) 
    using (var canvasRenderTarget = new CanvasRenderTarget(resourceCreator, newWidth, newHeight, canvasBitmap.Dpi)) 
    using (var drawingSession = canvasRenderTarget.CreateDrawingSession()) 
    using (var scaleEffect = new ScaleEffect()) 
    { 
     scaleEffect.Source = canvasBitmap; 
     scaleEffect.Scale = new System.Numerics.Vector2(newWidth/softwareBitmap.PixelWidth, newHeight/softwareBitmap.PixelHeight); 
     drawingSession.DrawImage(scaleEffect); 
     drawingSession.Flush(); 
     return SoftwareBitmap.CreateCopyFromBuffer(canvasRenderTarget.GetPixelBytes().AsBuffer(), BitmapPixelFormat.Bgra8, (int)newWidth, (int)newHeight, BitmapAlphaMode.Premultiplied); 
    } 
} 
1

나는 이미지 파일을하고 100 × 100 SoftwareBitmap로 축소하고 ImageSource로 돌아갑니다.

이미 SoftwareBitmap이 있으니 더욱 쉽게 작업 할 수 있다고 생각합니다. 그러나 이것이 당신에게 아이디어를 줄 수 있기를 바랍니다.

새로 조정 된 SoftwareBitmap 인스턴스를 초기화하는 동안 PixelBuffer의 경우에만 WritableBitmap이 필요합니다. 우리가 가지고있는 바이트 [] 픽셀 데이터 (픽셀 로컬 변수)에서 직접 IBuffer를 생성 할 수 있다면 직접 SoftwareBitmap.CreateCopyFromBuffer() 메소드에 제공 할 수 있습니다. 이 경우 WritableBitmap이 필요 없습니다.

private async Task<ImageSource> ProcessImageAsync(StorageFile ImageFile) 
    { 
     if (ImageFile == null) 
      throw new ArgumentNullException("ImageFile cannot be null."); 

     //The new size of processed image. 
     const int side = 100; 

     //Initialize bitmap transformations to be applied to the image. 
     var transform = new BitmapTransform() { ScaledWidth = side, ScaledHeight = side, InterpolationMode = BitmapInterpolationMode.Cubic }; 

     //Get image pixels. 
     var stream = await ImageFile.OpenStreamForReadAsync(); 
     var decoder = await BitmapDecoder.CreateAsync(stream.AsRandomAccessStream()); 
     var pixelData = await decoder.GetPixelDataAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb); 
     var pixels = pixelData.DetachPixelData(); 

     //Initialize writable bitmap. 
     var wBitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); 
     await wBitmap.SetSourceAsync(stream.AsRandomAccessStream()); 

     //Create a software bitmap from the writable bitmap's pixel buffer. 
     var sBitmap = SoftwareBitmap.CreateCopyFromBuffer(wBitmap.PixelBuffer, BitmapPixelFormat.Bgra8, side, side, BitmapAlphaMode.Premultiplied); 

     //Create software bitmap source. 
     var sBitmapSource = new SoftwareBitmapSource(); 
     await sBitmapSource.SetBitmapAsync(sBitmap); 

     return sBitmapSource; 
    } 

PS :

여기에 코드입니다. 이 문장은 대답의 일부가 아니지만, 저는 XAML/C#에 대해 많은 것을 배웠고 MVA 및 Channel9 비디오에서 Windows Store 응용 프로그램을 개발한다고 말해야합니다! :)

+0

비용이 많이 듭니까? –

+0

그다지 많지는 않지만 나중에 나름대로 똑바로 할 수 있다는 것을 깨달았습니다. SoftwareBitmap의 크기와 그레이 스케일링에 대한 다른 질문을했습니다. 이것 (https://stackoverflow.com/a/45393902/4062881) 대답을보십시오, 그것은 나보다 낫다, 성능 현명하다. –

+0

@ JerryNixon-MSFT Lumia Imaging SDK - https://msdn.microsoft.com/en-us/library/mt598502.aspx를 사용할 수도 있습니다. 그것은 굉장! –

관련 문제