-1

I haven't programmed in c for about 9 years, and I've never been that good (with any language) either. Now, I'm trying to brute-force my way back in, converting some Matlab code into c, and some stuff is still very rusty.

I'm trying to read an 8bit-bmp into a c file. Then I'd like to change the saturation level (0-255) of each specific bit.

I did find the stb_image library, but I'm not sure what am I actually loading through:

 #include <stdio.h>  
 #include <stdlib.h>  
   
 #define STB_IMAGE_IMPLEMENTATION  
 #define STBI_ONLY_BMP  
 #define STB_IMAGE_WRITE_IMPLEMENTATION  
 #include "stb_image/stb_image.h"  
 #include "stb_image/stb_image_write.h"  
 
 
 int main(void) {    
      int width, height, channels;    
      int i,j;    
      unsigned char *img = stbi_load("filename", &width, &height, &channels, 1);

But if it's an unsigned char, it's a 8bit value. And if it's a 8bit .bmp, and I'm loading 1 channel, it's gotta be the saturation in binary. Which then led me to the question: how can I access inside each byte and change the values? Is it through something like this?

for (i=1;i<=1440;i++){  
    for (j=1;j<=1080;j++){  
        if(*(*(img + i) + j)<100){  
            *(*(img + i) + j) = 0;  
        }  
        else{  
            *(*(img + i) + j) = 255;  
        }  
    }  
 }  

Well, of course it isn't. Silly me.

../srctt/tryout.c:17:28: error: invalid type argument of unary ''(have 'int')
17 | if(
(*(img + i) +j)<100){

So... I have to loop through all of the unsigned char array and convert it 1 by 1 to an int array with the same size? I feel that I'm missing something here. There's either a better library to read images, or some kind of easy conversion that I should be doing.

Then, afterwards, I'd also like to save the array into a bmp (like below), but does that mean I have to run another loop to convert every int into an unsigned char back?

stbi_write_bmp("filename", 1440, 1080, 0, img);  
stbi_image_free(img);

Thanks in advance. I know, reaaaaaaally rusty shenanigans here.

  • Those 8-bit pixel values are indexes into a colour table. That's what needs to be edited. – Weather Vane Feb 10 '23 at 12:37
  • @WeatherVane Are you sure? I’m reading through the stb_image.h documentation right now to find out... – Dúthomhas Feb 10 '23 at 12:51
  • @Dúthomhas you may be right. I am talking about a bitmap file. Perhaps the library converts to and from a 24/32 bit array of actual colour values. – Weather Vane Feb 10 '23 at 12:52
  • So, I’m a little confused at what you are doing. **Grayscale** and **saturation** are two different things, even if they have similar consequence. I can go on, but maybe you can provide more information about your exact input and exact desired output. (For example, I have an input BMP file that loads to display a 3-channel, 8-bit-per-channel RGB image. I want to lower the saturation N% and write it back to disk as an RGB BMP image.) – Dúthomhas Feb 10 '23 at 13:12
  • Since C arrays start at 0, loops should be `(i=0; i – stark Feb 10 '23 at 13:59

1 Answers1

1

You're not really interested in scanlines, so just do:

for (k=0; k<width*height; k++)
    img[k] = ...

If you are, then:

for (y=0; y<height; y++)
    for (x=0; x<width; x++)
        img[y*width+x] = ...
teapot418
  • 1,239
  • 1
  • 3
  • 9
  • You've ignored the *stride* of a bitmap image, which is always a multiple of `4`. – Weather Vane Feb 10 '23 at 12:40
  • @WeatherVane STB image libraries remove the stride from the image data. – Dúthomhas Feb 10 '23 at 12:46
  • If stbi_load loads an unsigned char array, then how am I going to then make an asigment to an int i.e. img[y*width+x] = 255; I'm not sure if it's for that reason or not, but my output bmp says it's corrupted. – ATSlooking4things Feb 10 '23 at 13:04
  • @ATSlooking4things `img` is `unsigned char *` ("array of chars"), what int do you mean? – teapot418 Feb 10 '23 at 13:08
  • @teapot418 forget what I said before. But still, `img` is `unsigned char*`, right? So, that means that the address of the first pixel of the image is inside the variable `img`. And. if it's a `*img`, i should be able to do `img++`, which would increase the address that's inside `img`, and `img` would start to point to the second pixel. Right? If that's correct, the question that remains is: The addresses increase 1 by 1 along each row, or along each column? – ATSlooking4things Feb 12 '23 at 20:30
  • @ATSlooking4things https://github.com/nothings/stb/blob/master/stb_image.h#L137 +1 should move you to the next pixel to the right, and if you are at the right edge, all the way to the left, one line down – teapot418 Feb 12 '23 at 20:38
  • @teapot418 Thank you for the answer. So, in theory, my thought process of the comment above is correct, right? Then, can you explain me exactly what I'll end up having in each memory cell pointed by `*img`? Is it a 8bit binary char? Is it 8bit binary? How can I make it an integer? Because, assuming that each memory cell contains the grayscale value of each pixel, it should be a value from 0-255. And I'd like to compare it with a specific value. For example, `if(*img<100){`. But, `*img` isn't an `int`, I assume. – ATSlooking4things Feb 12 '23 at 21:13
  • @ATSlooking4things you asked stbi_load for 1 component, so you are getting 0..255 greyscale I assume. You can treat `unsigned char` as an int that takes values 0..255, no problem there. If you try to assign something larger to it, only the least significant 8 bits of the value will be used. – teapot418 Feb 12 '23 at 21:23
  • @ATSlooking4things the problem with your `*(*(img + i) + j)` is that img is a one-star pointer. You need either `*(img +k)` (k in 0..w*h-1) or `*(img+j*width+i)` – teapot418 Feb 12 '23 at 21:26
  • @teapot418 Ok, so if I make comparisons like `*img<100` or assignments like `*img=255`, there should be no problem right? Sry for the "what if" questions, but right now I have no images and can't even run the program to test lol. And yes, `*(img+j*width+i)` should be the way to go. I needed a bit to interiorize what pointers meant – ATSlooking4things Feb 12 '23 at 21:29
  • @ATSlooking4things correct. But you will still have to test all that at some point. – teapot418 Feb 12 '23 at 21:31
  • @teapot418 in 9 and half hours when I get to work! But thanks a lot for the help so far. Hopefully, it will be enough – ATSlooking4things Feb 12 '23 at 21:33
  • @ATSlooking4things btw a useful shortcut for `*(p+x)` is `p[x]` (or x[p] if you want to be weird about it) -- the array semantics may be more intuitive than juggling pointers – teapot418 Feb 12 '23 at 21:38