0

So, I need to use the byte array of my image to modify, for example... I have a 380x380 image, and I need to take 3x3 of the image and multiply with other array and thus with the entire image.

I never use byte array, so I dont know if im doing right

//Obtener byteArray de imagen
Image imageOri = Image.FromFile(Path);
var ms = new MemoryStream();
imageOri.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
var byteImage = ms.ToArray();

So, when I run this code, byteImage has a... List? of data, so, I dont know how to get the 3x3 of the image to make the process

Alfa Rojo
  • 165
  • 8
  • An image is a byte array of pixels hard coded in a virtual matrix [width, height] where each point has the size of the bytes needed for the color. So you address the array like `index = ( x * width + y ) * colorsize`. I hope I've not made a mistake, it's a long time I coded such thing... But `Bitmap` has the method `GetPixel()`. What do you call "*3x3 of the image*" ? –  Jul 09 '20 at 19:46
  • 2
    Might help: https://stackoverflow.com/questions/17387509/how-to-convert-1d-byte-array-to-2d-byte-array-which-holds-a-bitmap – mfs Jul 09 '20 at 19:52
  • @OlivierRogier 3x3 I mean the new sub array that i need to multiply... After multiply every possible 3x3, I will have a new array that I will export as new image...Ok, and if I suse `Bitmap` and the method `.GetPixel()`, how can I get those 3x3 for my process?? – Alfa Rojo Jul 09 '20 at 20:05
  • 2
    When you call `Image.Save`, you are saving the file representation of the image to your memory stream. This is not going to be a byte array representing pixel data, but the `.jpg` file contents, including the headers and the results of the JPEG compression algorithm. Unless you are intimately familiar with how JPEG compression works, the contents of the byte array will be unusable for image processing. – Abion47 Jul 09 '20 at 20:12
  • I'm sorry, I don't understand what means "*3x3 is a sub array*" and "*multiply every possible 3x3*"... do you have an example of what it is ? –  Jul 09 '20 at 20:13
  • @OlivierRogier My guess is that he is trying to do something like a processing filter with a 3x3 matrix and applying that matrix to every pixel in the image. – Abion47 Jul 09 '20 at 20:15
  • Does this answer your question? [3X3 Median Filtering in c# but not working?](https://stackoverflow.com/questions/33703387/3x3-median-filtering-in-c-sharp-but-not-working) –  Jul 09 '20 at 20:17
  • @OlivierRogier OP probably doesn't want to work with a bitmap directly, but instead gain unsafe access to the pixel data directly using `Bitmap.LockBits`. Trying to apply an image filter to an entire bitmap using managed methods is slow as tar... – Abion47 Jul 09 '20 at 20:18
  • @OlivierRogier It could be a `Blur`, or `Gaussian`, ...etc filter as well. –  Jul 10 '20 at 08:08

1 Answers1

0

I would assume you want to apply a convolution filter.

To start with you probably want to use a Bitmap Rather than an image, i.e. new Bitmap(Path).

The trivial method would be to loop over each pixel, and then loop over each value in the filter and multiply/accumulate with the corresponding pixel values. Using GetPixel to get the pixel values. Note that you need to handle the borders of the image somehow, for example by skipping them. GetPixel is notoriously slow, but I would recommend using it to ensure you have the code nailed down before optimizing.

Something like this (Untested):

        var bmp = new Bitmap(@"test.bmp");
        var filter = new float[3, 3];
        var result = new Bitmap(bmp.Width - 2, bmp.Height - 2);
        for(int y = 1; y < bmp.Height-1; y++)
        {
            for (int x = 1; x < bmp.Width - 1; x++)
            {
                float r = 0;
                r += bmp.GetPixel(x-1, y-1).R * filter[0, 0];
                r += bmp.GetPixel(x  , y-1).R * filter[1, 0];
                r += bmp.GetPixel(x+1, y-1).R * filter[2, 0];
                r += bmp.GetPixel(x-1, y  ).R * filter[0, 1];
                r += bmp.GetPixel(x  , y  ).R * filter[1, 1];
                r += bmp.GetPixel(x+1, y  ).R * filter[2, 1];
                r += bmp.GetPixel(x-1, y+1).R * filter[0, 2];
                r += bmp.GetPixel(x  , y+1).R * filter[1, 2];
                r += bmp.GetPixel(x+1, y+1).R * filter[2, 2];

                // Repeat for G & B channels
                result.SetPixel(x-1, y-1, Color.FromArgb((int)r, 0, 0));
            }
        }

A more comprehensive guide can be found here.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • Using `GetPixel` and `SetPixel` to perform image processing on an entire image is unbelievably slow. It is much faster to use `LockPixels` to access the pixel data directly. – Abion47 Jul 09 '20 at 21:50
  • Yes, sorry but I'm not a good thing at explaining, but you got y point... On image 380x340, throw me the error `OutOfRange` when x = 338 on the line `result.SetPixel(x, y, Color.FromArgb((int)r, 0, 0));` – Alfa Rojo Jul 09 '20 at 23:02
  • @Abion47 Yes, I mentioned that GetPixel is slow. But if the image is small, and it is not done all to often it is often fast enough. I did not want to have to explain lockPixel in addition to convolution, and the provided link shows how to do it the correct way. – JonasH Jul 10 '20 at 06:44
  • @alfa Rojo, Oups, the setPixel coordinates should be offset by -1. Example has been updated. – JonasH Jul 10 '20 at 06:45