24 bit Image to 8 bit grayscale image

edited October 2013 in How To...

Hello everybody

For an assignment I have to transform an 24 bit image into a 8 bit one-channel grayscale image. I have not yet found a way to do this. If i change the pixels with color( ) it does produce a grayscale but it seems that it is done by just setting rgb to the same values. Is there methode how I can do this task?

I'm happy about every input.

Thanks in advance

Answers

  • check out the PImage.filter(). It has a greyscale filter.

  • edited October 2013

    I'm aware of the filter but as far as I know the image a stays three-channel grayscale with rgb set to the same values. If I'm mistaken please correct me. Thanks for the fast reply anyway

  • Ah, yes. I'm not sure about that. Look into dithering on the OpenProcessing site. I'll bet you can find some code there to move you towards what you want.

  • There's no way to do this using a PImage and here's why and what you should do:

    Pixels from PImages are integers. An integer has 4 bytes: the first byte (MSB) defines the opacity of the image, the second byte of that PImage defines the red color, the third byte defines the green color and the last byte defines the blue color (0xOORRGGBB). Even when you convert an image to grayscale with the filter function, tha image will stay with 4 channels, but the RGB component will have the same value.

    If you want to do that you have to create your own image type, which can be easily done by creating a byte matrix.

  • edited October 2013

    @TGPTIAlves

    why can't he just do it in following steps:

    0) load color image to PImage

    1) convert image pixels from RGB -> HSB (and store them in some array)

    2) reset in the HSB pixel array all "S" (saturation) values to 0 (now this HSB pixel array contains Grayscale data)

    3) convert HSB pixels array back into RGB pixels (and save it inside of same or new PImage).

    4) Now save resulting image to hard drive with PImage.save()

    PImage myColorImage = loadImage("lena.jpg");
    myColorImage.loadPixels();
    int[] hsb_pixel_values = convertRGBPixelsArrayToHSB(myColorImage.pixels);
    
    // now let's set saturation to 0, thus making each pixel Grayscale.
    for(int i = 0 ;i  < hsb_pixel_values.length; i++){
         // set saturation to 0
         hsb_pixel_values[i]  = hsb_pixel_values[i] & 0xffFF00FF; // we keep the highest byte untouched, then Hue untouched, reset Saturation to 00 and keep BB untouched.
    
    }
    
    // now copy hsb back to rgb. After this command myColorImage will contain
    // grayscale data
    copyHSBPixelsToRGBPixels(hsb_pixel_values, myColorImage.pixels);
    myColorImage.updatePixels();
    
    myColorImage.save("my_grayscale_lena.jpg");
    
    image(myColorImage, 0,0); // which is not color anymore but grayscale.
    
  • Oopps. This way image will still stay 3 channell RGB.. my bad :)

  • When you create a PImage using the createImage(), you can indicate the format as ARGB, RGB, or ALPHA ( which is greyscale alpha). I'm just guessing, but would the ALPHA format work?

  • Description of mask() method makes me believe that when you specify ALPHA, the data will be written to the Blue channel. But that's just a guess.

  • Thanks for all the answers! This really helped me to understand the subject. @TGPTIAlves Thank you. This makes completely sense and I wouldn't have thought of that without you.

  • A simpler way to do this is to use loadPixels(), iterate on pixels[], extract the brightness(), and write it in another PImage's pixels[] array.

  • size(800, 600);
    
    PImage colorful = loadImage("H:/Temp/Tree.jpg");
    PImage grey = createImage(colorful.width, colorful.height, RGB);
    colorful.loadPixels();
    grey.loadPixels();
    for (int i = 0; i < colorful.pixels.length; i++)
    {
      int b = int(brightness(colorful.pixels[i]));
      grey.pixels[i] = color(b, b, b);
    }
    grey.updatePixels();
    
    image(grey, 0, 0);
    

    Indeed, the image is still RGB, that's the way it is displayed on screen anyway, the concept of "8 bit one-channel grayscale image" applies more to a saving format, which isn't specified in your request.

  • You are completely right that this is more a saving problem. If I could use a Byte array for pixels and if I would know how to save that into an image file I might solve that problem, but I have not found any reference on that by now.

  • Looks like if you save your ALPHA image in "tga" format, Processing will automatically save it as 8-bit grayscale image.

    This can be seen in PImage source:

    https://github.com/processing/processing/blob/master/core/src/processing/core/PImage.java#L2963

    https://github.com/processing/processing/blob/master/core/src/processing/core/PImage.java#L2995

    So looks like your problem is solved:

    Just createImage() with ALPHA parameter and later on populate it's blue channel with brightness() values. Then just save it in TGA format myAlphaImage.save("myimage.tga")

    :)

  • Well, in this case, it is necessary to choose an image file format supporting this 8-bit format. Gif does this naturally, so if you save the result of my code to a Gif file, you are done. TGA might support it, as said, and PNG does support it too. Not Jpeg.

    Saving to this format might need to go out of Processing, into the Java realm...

    Probably out of the scope of this assignment. But your requirements are so vague, it is hard to give real advice.

Sign In or Register to comment.