0

I am just playing with images in WPF and i wrote a sample application which loads an image from hard disk and the should change the first 100 pixel in each line to red. But it doesn' do this and instead the generated iage has small redlined everywhere. I belive somewhere in the code, h and w are changed and hence the stride is not correct. But I can not find where is the problm. Any help appriciated.

The code is as follow:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestImageProcessing
{
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

class TransformImage
{
    public static BitmapSource Transform(BitmapImage input)
    {
        var red = new PixelColor() { Blue = 0, Green = 0, Red =255, Alpha =128 };
        var inputPixels = GetPixels(input);
        var outPixel = new PixelColor[inputPixels.GetLength(0), inputPixels.GetLength(1)];

        var output = new WriteableBitmap(input.PixelWidth, input.PixelHeight, input.DpiX, input.DpiY, input.Format, input.Palette);
        for (int h = 0; h < input.PixelHeight; h++)
        {
            for (int w = 0; w < input.PixelWidth; w++)
            {


               if (h < 100)
               {
                   outPixel[w, h] = red;
               }
               else
               {
                   outPixel[w, h] = inputPixels[w, h];
               }

            }
        }

        PutPixels(output, outPixel);
        return output;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct PixelColor
    {
        public byte Blue;
        public byte Green;
        public byte Red;
        public byte Alpha;
    }

    public static void PutPixels(WriteableBitmap bitmap, PixelColor[,] pixels)
    {
        int width = pixels.GetLength(0);
        int height = pixels.GetLength(1);
        bitmap.WritePixels(new Int32Rect(0, 0, width, height), pixels, width * 4, 0);
    }
    public static PixelColor[,] GetPixels(BitmapSource source)
    {
        if (source.Format != PixelFormats.Bgra32)
        {
            source = new FormatConvertedBitmap(source, PixelFormats.Bgra32, null, 0);
        }
       PixelColor[,] pixels = new PixelColor[source.PixelWidth, source.PixelHeight];

        int stride = source.PixelWidth * ((source.Format.BitsPerPixel + 7) / 8);
        GCHandle pinnedPixels = GCHandle.Alloc(pixels, GCHandleType.Pinned);
        source.CopyPixels(
          new Int32Rect(0, 0, source.PixelWidth, source.PixelHeight),
          pinnedPixels.AddrOfPinnedObject(),
          pixels.GetLength(0) * pixels.GetLength(1) * 4,
              stride);
        pinnedPixels.Free();
        return pixels;

    }
}
}

Part of he above code comes from this post: Finding specific pixel colors of a BitmapImage

MainWindow.xaml:

<Window x:Class="TestImageProcessing.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="550" Width="725">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition Height="30px"/>
    </Grid.RowDefinitions>

    <Image x:Name="InImage" Grid.Row="0" VerticalAlignment="Top" Stretch="Uniform" />
    <Image x:Name="OutImage" Grid.Row="1" VerticalAlignment="Top" Stretch="Uniform" />
    <Button x:Name="Process" Content="Button"  Grid.Row="2"   Width="75" Click="Process_Click"/>




</Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace TestImageProcessing
{


/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Process_Click(object sender, RoutedEventArgs e)
    {
        BitmapImage input= new BitmapImage(new Uri(@"C:\tmp\test.jpg"));
       InImage.Source=input;
        OutImage.Source = TransformImage.Transform(input);

    }
}
}
Community
  • 1
  • 1
mans
  • 17,104
  • 45
  • 172
  • 321

1 Answers1

0

The pixel format of the WriteableBitmap you create inside the Transform method should be PixelFormats.Bgra32, but you're using the pixel format of input parameter instead.


If you want to store pixels in a bidimensional matrix, the first dimension represents the number of lines and the second dimension is the number of columns, so you should declare a matrix of pixels in this way:
PixelColor[,] pixels = new PixelColor[Height, Width];

notice you need to swap width and height.


REMOVED (it was incorrect)
someone else
  • 321
  • 1
  • 3