jweinst1
10/4/2018 - 5:03 AM

rgb data processing in C, for visual data

rgb data processing in C, for visual data

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// RGB Data Generator prototype.
// Works with 24-bit aligned unsigned data
// Targeted for images.

// rgb_t is considered to be 24-bit aligned unsigned data.
// Thus, unsigned char is suitable.
typedef unsigned char rgb_t;

// Enum used in rule type to signify whether,
// The rule sets the current, previous, 
enum rgb_pos_t {
  RGB_POS_PREV,
  RGB_POS_CUR,
  RGB_POS_NEXT
};

// Data structure to encapsulate a rule to apply to color.
// Note, the set_<> fields represent what to set the directed
// color value to, the regular fields indicate the condition.
struct rgb_rule_t {
  enum rgb_pos_t place;
  rgb_t red;
  rgb_t green;
  rgb_t blue;
  rgb_t set_red;
  rgb_t set_green;
  rgb_t set_blue;
};

#define RGBC_WIDTH (sizeof(unsigned char) * 3)

// Macro aligns the idea of memory size with 24-bit integer
// data.
#define RGBC_SIZE(space) (sizeof(unsigned char) * 3 * space) 

// Macros to evaluate to the red, green, and blue channels
#define RGBC_RED(r) (r[0])
#define RGBC_GREEN(r) (r[1])
#define RGBC_BLUE(r) (r[2])

// Pointer movement macros
#define RGBC_NEXT(r) (r + RGBC_WIDTH)
#define RGBC_PREV(r) (r - RGBC_WIDTH)
#define RGBC_OFFSET(r, change) (r + RGBC_SIZE(change))

// Color comparison macros
#define RGBC_EQ(r, red, green, blue) (RGBC_RED(r) == (red) && RGBC_GREEN(r) == (green) && RGBC_BLUE(r) == (blue))

#define RGBC_NEQ(r, red, green, blue) (!RGBC_EQ(r, red, green, blue))

// color specific compare
#define RGBC_EQ_RED(r, red) (RGBC_RED(r) == red)
#define RGBC_EQ_GREEN(r, green) (RGBC_GREEN(r) == green)
#define RGBC_EQ_BLUE(r, blue) (RGBC_BLUE(r) == blue)

// Setting macros

#define RGBC_SET_RED(r, n) (RGBC_RED(r) = n)
#define RGBC_SET_GREEN(r, n) (RGBC_GREEN(r) = n)
#define RGBC_SET_BLUE(r, n) (RGBC_BLUE(r) = n)
#define RGBC_SET_ALL(r, red, green, blue) do { \
                           RGBC_RED(r) = red; \
                           RGBC_GREEN(r) = green; \
                           RGBC_BLUE(r) = blue ; \
} while(0)

// Conditional macros

#define RGBC_IF_EQ(r, red, green, blue, action) if(RGBC_EQ(r, red, green, blue)){action;}
#define RGBC_IF_NEQ(r, red, green, blue, action)if(RGBC_NEQ(r, red, green, blue)){action;}

// conditional set macros 
#define RGBC_IF_EQ_SET(r, red, green, blue, r_set, g_set, b_set) RGBC_IF_EQ(r, red, green, blue, RGBC_SET_ALL(r, r_set, g_set, b_set))
#define RGBC_IF_EQ_SET_NEXT(r, red, green, blue, r_set, g_set, b_set) RGBC_IF_EQ_SET(RGBC_NEXT(r), red, green, blue, r_set, g_set, b_set)
#define RGBC_IF_EQ_SET_PREV(r, red, green, blue, r_set, g_set, b_set) RGBC_IF_EQ_SET(RGBC_PREV(r), red, green, blue, r_set, g_set, b_set)


static rgb_t COLOR_DATA[RGBC_SIZE(1000)] = {0};

static void rgb_init_rule(struct rgb_rule_t* rule,
                          enum rgb_pos_t posi,
                          rgb_t red,
                          rgb_t green,
                          rgb_t blue,
                          rgb_t set_red,
                          rgb_t set_green,
                          rgb_t set_blue) {
    rule->place = posi;
    rule->red = red;
    rule->green = green;
    rule->blue = blue;
    rule->set_red = set_red;
    rule->set_green = set_green;
    rule->set_blue = set_blue;
}

static void rgb_apply_rule(rgb_t* data, struct rgb_rule_t* rule) {
	switch(rule->place) {
		case RGB_POS_PREV:
		         RGBC_IF_EQ_SET_PREV(data, rule->red, rule->green, rule->blue, rule->set_red, rule->set_green, rule->set_blue);
		         return;
		case RGB_POS_CUR:
		         RGBC_IF_EQ_SET(data, rule->red, rule->green, rule->blue, rule->set_red, rule->set_green, rule->set_blue);
		         return;
		case RGB_POS_NEXT:
		         RGBC_IF_EQ_SET_NEXT(data, rule->red, rule->green, rule->blue, rule->set_red, rule->set_green, rule->set_blue);
		         return;
	}
}

static void rgb_print_pixels(rgb_t* begin, rgb_t* end) {
	while(begin != end) {
		printf("rgb(%u, %u, %u)\n", RGBC_RED(begin), RGBC_GREEN(begin), RGBC_BLUE(begin));
		begin += RGBC_WIDTH;
	}
}

static int 
rgb_to_file(rgb_t* color, size_t color_len, const char* path) {
	FILE* fp;
	fp = fopen(path, "wb");
	if(fp == NULL) {
		fprintf(stderr, "IO Error: Cannot open file at %s, exiting.\n", path);
		exit(1);
	}
	fwrite(color, sizeof(unsigned char), color_len, fp);
	fclose(fp);
	return 1;
}

int main(void) {
  rgb_t* color_ptr = COLOR_DATA;
  struct rgb_rule_t rule1;
  rgb_init_rule(&rule1, RGB_POS_NEXT, 0, 0, 0, 10, 40, 200);
  rgb_apply_rule(color_ptr, &rule1);
  rgb_print_pixels(color_ptr, color_ptr + RGBC_SIZE(20));
  return 0;
}