none
画像ファイルの縦・横の位置を指定し、その地点のRGB値を取得する RRS feed

  • 質問

  •  //https://qiita.com/Tachibana446/items/31cdda5cac78cf571a04
    
                //ファイルを開く
                FileOpenPicker fileOpenPicker = new FileOpenPicker();
                fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
                fileOpenPicker.FileTypeFilter.Add(".jpg");
                fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
                StorageFile inputFile = await fileOpenPicker.PickSingleFileAsync();
    
                //ビットマップを開く
                SoftwareBitmap softwareBitmap;
                using (IRandomAccessStream stream = await inputFile.OpenAsync(FileAccessMode.Read))
                {
                    // Create the decoder from the stream
                    //ストリームからデコーダーを作成します 
                    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
    
                    // Get the SoftwareBitmap representation of the file
                    //ファイルのSoftwareBitmap表現を取得します
                    softwareBitmap = await decoder.GetSoftwareBitmapAsync();
                }

    上記のコードで、SoftwareBitmapを読み込むことはできました。

    Q1:このsoftwareBitmapから、画像のXとYの位置を指定し、その位置におけるRGBの値を取得することはできますでしょうか?

    Q2:RGBの値を書き込んであるジャグ配列から、画像を作成してその画像を保存する、ということは可能でしょうか?

    上記の2個、もし可能ならばその方法をご教示ください。

    2021年3月24日 10:07

回答

  • こんな
    using System;
    using System.Runtime.InteropServices.WindowsRuntime;
    using Windows.Graphics.Imaging;
    using Windows.Storage;
    using Windows.Storage.Pickers;
    using Windows.Storage.Streams;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using System.Collections.Generic;
    
    namespace App10
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            private async void Button_Click(object sender, RoutedEventArgs e)
            {
                //ファイルを開く
                FileOpenPicker fileOpenPicker = new FileOpenPicker();
                fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
                fileOpenPicker.FileTypeFilter.Add(".jpg");
                fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
                StorageFile inputFile = await fileOpenPicker.PickSingleFileAsync();
    
                //ビットマップを開く
    
                Windows.UI.Xaml.Media.Imaging.WriteableBitmap bmp;
                uint w = 0;//画像の幅
                uint h = 0;//画像の高さ
                uint stride = 0;//1行のバイト数
    
                using (IRandomAccessStream stream = await inputFile.OpenAsync(FileAccessMode.Read))
                {
                    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
                    using (SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync())
                    {
                        using (var bmpbuffer = softwareBitmap.LockBuffer(BitmapBufferAccessMode.Read))
                        {
    
                            if (bmpbuffer.GetPlaneCount() > 0)
                            {
                                var desc = bmpbuffer.GetPlaneDescription(0);
                                w = (uint)desc.Width;
                                h = (uint)desc.Height;
                                stride = (uint)desc.Stride;
                            }
                        }
                        bmp = new Windows.UI.Xaml.Media.Imaging.WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight);
                        softwareBitmap.CopyToBuffer(bmp.PixelBuffer);
                    }
                }
    
                uint pixesBytsCount = stride / w;//1ピクセルのバイト数
                IBuffer buffer = bmp.PixelBuffer;
    
                if (pixesBytsCount == 4)
                {//ARGB
    
                    //バッファから読み取る
                    for (uint y = 0; y < h; y++)
                    {
                        for (uint x = 0; x < w; x++)
                        {
                            uint pos = y * stride + x * pixesBytsCount;
                            int b = buffer.GetByte((uint)(pos + 0));
                            int g = buffer.GetByte((uint)(pos + 1));
                            int r = buffer.GetByte((uint)(pos + 2));
                            int a = buffer.GetByte((uint)(pos + 3));
                        }
                    }
    
                    //バイト配列に取り出して調べる
                    var array = buffer.ToArray();
                    for (uint y = 0; y < h; y++)
                    {
                        for (uint x = 0; x < w; x++)
                        {
                            uint pos = y * stride + x * pixesBytsCount;
                            int b = array[pos + 0];
                            int g = array[pos + 1];
                            int r = array[pos + 2];
                            int a = array[pos + 3];
                        }
                    }
    
                    //バイト配列を編集してbitmapに書き戻す
                    for (uint x = 0; x < Math.Min(w, h); x++)
                    {
                        //赤線を描いてみる
                        uint pos = x * stride + x * pixesBytsCount;
                        array[pos + 0] = 0x00;
                        array[pos + 1] = 0x00;
                        array[pos + 2] = 0xFF;
                        array[pos + 3] = 0xFF;
                    }
                    array.CopyTo(bmp.PixelBuffer);
                }
    
                this.img.Source = bmp;//表示
    
                //ビットマップのバイト配列をjpegにエンコードして保存
                FileSavePicker picker = new FileSavePicker();
                picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
                picker.FileTypeChoices.Add("JPEG", new List<string>() { ".jpg" });
                var sf = await picker.PickSaveFileAsync();
                using (IRandomAccessStream stream = await sf.OpenAsync(FileAccessMode.ReadWrite))
                {
                    BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
                    encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, w, h, 96.0, 96.0, bmp.PixelBuffer.ToArray());
                    await encoder.FlushAsync();
                }
    
            }
        }
    }
    

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク ナノレス 2021年3月25日 4:18
    2021年3月24日 12:15