Thread: Loading an image as a matrix

  1. #1
    Registered User
    Join Date
    Dec 2019
    Posts
    7

    Loading an image as a matrix

    I want to load an image as a matrix, and perform sparse matrix arithmetic.
    The relevant libraries I found for this are:

    Image operations (load, resize):
    GitHub - nothings/stb: stb single-file public domain libraries for C/C++

    Sparse matrix arithmetic:
    GSL - GNU Scientific Library - GNU Project - Free Software Foundation

    Are there other libraries that can save the pain of adding a translation between these two libraries formats (the loaded image, and the matrix type)?

    thanks

  2. #2
    Registered User
    Join Date
    Dec 2019
    Posts
    7
    I ended up doing the below, I would be happy to get any tips for writing it in a more clean\ "right" way, I've been writing python for a few years and the transition is confusing for me.
    Code:
    #define STB_IMAGE_IMPLEMENTATION
    #include <stdio.h>
    #include <stdint.h>
    #include <stddef.h>
    #include <stdbool.h>
    #include <gsl/gsl_sf.h>
    #include "stb_image.h"
    #define STB_IMAGE_WRITE_IMPLEMENTATION
    #include "stb_image_write.h"
    
    void slice_image(unsigned char *from_image, unsigned char *to_image, int width,
                     int height, int original_channels, int target_channel);
    void image2matrix(gsl_matrix * matrix, unsigned char *image, int width,
                      int height);
    
    int main()
    {
      printf("Starting\n");
    
      // Load Image
      int width, height, channels;
    
      const char path[] =
          "/mnt/c/Users/alexf/Desktop/Projects/3D_Line_Dithering/test_images/sunflowers.jpg";
      unsigned char *image = stbi_load(path,
                                       &width,
                                       &height,
                                       &channels,
                                       STBI_rgb);
    
      if (image == NULL) {
        printf("Error in loading the image\n");
        exit(1);
      } else {
        printf("Loaded Image\n");
      }
    
    
      printf("Image Params:\n");
      printf("Height: %d ; Width: %d ; Channels: %d\n", width, height, channels);
      // Slice Image
      unsigned char *image_r = malloc(sizeof(int) * height * width);
      if (image_r == NULL) {
        printf("Error allocating space for the image slice\n");
        exit(1);
      }
      printf("Slice Image:\n");
    
      slice_image(image, image_r, width, height, channels, 0);
    
      printf("Allocate Matrix:\n");
      gsl_matrix *matrix = gsl_matrix_alloc(height, width);
      if (matrix == NULL) {
        printf("Error allocating space for the image slice\n");
        exit(1);
      }
      printf("Image to Matrix:\n");
      image2matrix(matrix, image_r, width, height);
    
      // FREE ALL
      printf("Free All:\n");
      gsl_matrix_free(matrix);
      free(image_r);
      stbi_image_free(image);
      printf("Finished\n");
    
      return 0;
    }
    
    void slice_image(unsigned char *from_image, unsigned char *to_image, int width,
                     int height, int original_channels, int target_channel)
    {
      unsigned char *p;
      for (int j = 0; j < height; j++) {
        for (int k = 0; k < width; k++) {
          p = &from_image[original_channels * (j * width + k)];
          to_image[(j * width + k)] = p[target_channel];
    
          printf("%u\n", p[target_channel]);
        }
        printf("\n");
      }
    };
    
    int print_matrix(FILE * f, const gsl_matrix * m)
    {
      int status, n = 0;
    
      for (size_t i = 0; i < m->size1; i++) {
        for (size_t j = 0; j < m->size2; j++) {
          if ((status = fprintf(f, "%g ", gsl_matrix_get(m, i, j))) < 0)
            return -1;
          n += status;
        }
    
        if ((status = fprintf(f, "\n")) < 0)
          return -1;
        n += status;
      }
    
      return n;
    
    }
    Last edited by Salem; 01-03-2020 at 04:16 AM. Reason: Removed crayola - please use copy/paste as text - not the eyebleed colour scheme of your IDE

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,169
    You didn't post image2matrix.

    > printf("Height: %d ; Width: %d ; Channels: %d\n", width, height, channels);
    What do you get printed for channels?

    3 maybe, one for each of R,G,B

    > unsigned char *image_r = malloc(sizeof(int) * height * width);
    I would think you would need channels, not sizeof(int) here.

    > p = &from_image[original_channels * (j * width + k)];
    original_channels is your limit value.
    If you're trying to extract say channel x out of a y-channel image, you need a different expression.
    It might be fine for your special case of channel 0 - I don't know.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Dec 2019
    Posts
    7
    my bad,
    Code:
    void image2matrix(gsl_matrix * matrix, unsigned char *image, int width,
                      int height)
    {
      for (int j = 0; j < height; j++) {
        for (int k = 0; k < width; k++) {
          matrix->data[j * matrix->tda + k] = image[j * width + k];
        }
      }
    
    };
    Last edited by Salem; 01-03-2020 at 05:31 AM. Reason: Removed crayola

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,169
    Please pay attention to posting code.
    Don't include all the HTML nonsense from your IDE.
    Use copy-as-text and/or paste-as-text.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Dec 2019
    Posts
    7
    copy that, I will remove HTML nonsense next time

    "
    What do you get printed for channels?
    3 maybe, one for each of R,G,B
    "
    Yea I get three

    "
    > unsigned char *image_r = malloc(sizeof(int) * height * width);
    I would think you would need channels, not sizeof(int) here.
    "
    I want to take a slice, meaning only one channel from the original image.

    "
    > p = &from_image[original_channels * (j * width + k)];
    original_channels is your limit value.
    If you're trying to extract say channel x out of a y-channel image, you need a different expression.
    It might be fine for your special case of channel 0 - I don't know.
    "
    The format that the image is loaded is an array, where the 3 first values are the RGB values of the first pixel.
    because I'm slicing one channel, I want to jump over the other channel values while iterating

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Loading image from Resource
    By parad0x13 in forum C++ Programming
    Replies: 1
    Last Post: 03-15-2009, 10:36 PM
  2. Loading & displaying an image
    By csonx_p in forum Windows Programming
    Replies: 1
    Last Post: 06-19-2008, 06:40 AM
  3. Loading an image into memory using OpenGL
    By Kaelin in forum C++ Programming
    Replies: 3
    Last Post: 02-08-2005, 12:03 PM
  4. Image class - loading image file
    By GaPe in forum Windows Programming
    Replies: 2
    Last Post: 07-11-2004, 01:35 PM
  5. Image Loading Troubles
    By frenchfry164 in forum C++ Programming
    Replies: 3
    Last Post: 11-02-2003, 01:07 PM

Tags for this Thread