Home > Blockchain >  incrementing unsigned char *image
incrementing unsigned char *image

Time:11-12

void draw(unsigned char *image)
    {
        for (int y = 0; y < HEIGHT; y  )
        {
            for (int x = 0; x < WIDTH; x  )
            {
                if (someCondition)
                {
                    int red = x * 256 / WIDTH;
                    int green = 255;
                    int blue = y * 256 / HEIGHT;

                    image[0] = (unsigned char)blue;
                    image[1] = (unsigned char)green;
                    image[2] = (unsigned char)red;
                }
                else
                {
                    image[0] = 0;
                    image[1] = 0;
                    image[2] = 0;
                }
                image  = 3;
            }
        }
    }

What does incrementing image =3; actually do here. I'm trying to convert the same c code to C#, but unable to achieve this. I'm using byte[] image in C#, now how should I do image =3 in C#. Is it scaling the image?

CodePudding user response:

From the code it is evident that the pointer points to an element of an array of unsigned char:

[ ][ ][ ][ ] ........... [ ]

 ^
 |
 image

Next consider that image[i] is equivalent (really equivalent, that is how it is defined) to *(image i), ie it increments the pointer by i and dereferences it. You can write image[0] to get the element image points to. You can type image[1] to get the next element in the array.

Lets call the actual array x then you can access its elements via incrementing image like this:

x[0]      x[1]     x[2]      x[3]          x[4]          x[5]
image[0]  image[1] image[2]
                             (image 3)[0]  (image 3)[1]  (image 3)[2]

In other words, the author could have used some offset in the outer loop which increments by 3 in each iteration and then instead of image[ i ] they would have used image[ i offset ]. Instead they choose to increment image which has the same effect.

CodePudding user response:

Here is your code in C# with comments which hopefully help understand what is done.
I highly recommend reading this article about image strides.

I read in the comments that each pixel has 3-byte which is why it is incremented by 3... while this might be true for some images, it is overall wrong. The bytes per pixel are depended on the pixel format of the image. you image can have 1-byte per pixel, 2-byte per pixel, 3-byte per pixel, 4-byte per pixel. The byte per pixel are also known as Color depth.

using System;
using System.Linq;
using System.Drawing;
using System.Drawing.Imaging;

namespace something 
{
    
    void draw(Bitmap bmp) 
    {
        BitmapData data = null;
        try {
            // Returns an object of type BitmapData.
            // BitmapData object grants you access 
            // to the address of the first pixel.
            data = bmp.UnlockBits(
                new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.ReadWrite,
                bmp.PixelFormat);
                
            unsafe {
                // Byte per pixel.
                // This is really import!
                // By checking how many bytes a pixel consumes
                // you know how to increment your raw pixel data.
                int bpp = Bitmap.GetPixelFormatSize(data.PixelFormat) / 8;
                // Pointer to the first pixel.
                byte* ptFirst = (byte*)data.Scan0;
                // Using a parallel loop here 
                // drastically improves performance.
                Parallel.For(0, data.Height, y => 
                {
                    // Get the pointer of the first pixel
                    // in the current stride.
                    // If you imagine your image as a table with 
                    // rows and columns, then this is the 'index'
                    // of the row.
                    // Images are built from multiple strides (rows).
                    byte* pixel = ptFirst   (y * data.Stride);
                    // IMPORTANT: Incrementing by byte-per-pixel 
                    // is crucial here as you need to skip n-bytes 
                    // to get to the next pixel.
                    // The pixel count per stride is the
                    // width multiplied by byte-per-pixel.
                    for (int x=0; x<data.Stride; x =bpp) 
                    {
                        if (someCondition) {
                            // Calc some colour values.
                            byte r = (byte)(x*256/data.Width);
                            byte g = byte.MaxValue;
                            byte b = (byte)(y*256/data.Height);
                            // Assign colour.
                            pixel[x 2]=r;   
                            pixel[x 1]=g;
                            pixel[x 0]=b;
                        }
                        else {
                            // Set pixel to black.
                            pixel[x 2]=0;   
                            pixel[x 1]=0;
                            pixel[x 0]=0;
                        }
                    }
                }
            }
        }
        finally {
            if (null != data) {
                bmp.UnlockBits(data);
            }
        }   
    }
}
  • Related