Skip to content

Instantly share code, notes, and snippets.

@Sir-Irk
Last active March 11, 2019 22:54
Show Gist options
  • Select an option

  • Save Sir-Irk/9fb80d264e4ec61523bc9524c040d544 to your computer and use it in GitHub Desktop.

Select an option

Save Sir-Irk/9fb80d264e4ec61523bc9524c040d544 to your computer and use it in GitHub Desktop.
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#define JM_MATH_IMPLEMENTATION
#define JM_MATH_USE_STDLIB
#include "jm_math.h"
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image.h"
#include "stb_image_write.h"
inline uint32_t get_blue(uint32_t color) { return (color >> 16) & 0xFF; }
inline uint32_t get_green(uint32_t color) { return (color >> 8) & 0xFF; }
inline uint32_t get_red(uint32_t color) { return (color >> 0) & 0xFF; }
//NOTE: Staight up comparison of pixel values
int pixel_compare(const void *a, const void *b)
{
uint32_t color0 = *(uint32_t *)a;
uint32_t color1 = *(uint32_t *)b;
if(color0 > color1) return 1;
if(color0 < color1) return -1;
return 0;
}
inline uint32_t averaged_color(uint32_t color)
{
uint32_t r = get_red(color);
uint32_t g = get_green(color);
uint32_t b = get_blue(color);
return (r + g + b) / 3;
}
//NOTE: Comparison is done using the average of each channel(no alpha). This can provide a slightly smoother
// appearance to the end result.
int pixel_compare_average(const void *a, const void *b)
{
uint32_t avg0 = averaged_color(*(uint32_t *)a);
uint32_t avg1 = averaged_color(*(uint32_t *)b);
if(avg0 > avg1) return 1;
if(avg0 < avg1) return -1;
return 0;
}
//NOTE: human eyes tend to be more sensitive to green light and much less
// sensitive to blue light and red light.
#define EYE_RED_COLOR_BIAS 0.2216f
#define EYE_GREEN_COLOR_BIAS 0.7152f
#define EYE_BLUE_COLOR_BIAS 0.0832f
inline float human_eye_color_intensity_bias(uint32_t color)
{
//NOTE: map channels from 0-255 to 0.0f-1.0f
float r = (float)get_red(color) / UCHAR_MAX;
float g = (float)get_green(color) / UCHAR_MAX;
float b = (float)get_blue(color) / UCHAR_MAX;
return jmClamp01(jmDot(V3(r, g, b), V3(EYE_RED_COLOR_BIAS, EYE_GREEN_COLOR_BIAS, EYE_BLUE_COLOR_BIAS)));
}
int pixel_compare_eye_bias(const void *a, const void *b)
{
float intensity0 = human_eye_color_intensity_bias(*(uint32_t *)a);
float intensity1 = human_eye_color_intensity_bias(*(uint32_t *)b);
if(intensity0 > intensity1) return 1;
if(intensity0 < intensity1) return -1;
return 0;
}
int main(void)
{
int w, h;
uint8_t *pixels = stbi_load("galaxy.jpg", &w, &h, 0, 4);
assert(pixels);
//NOTE: sort each row separately
for(int i = 0; i < h; ++i)
{
qsort(&((uint32_t *)pixels)[i * w], w, sizeof(uint32_t), pixel_compare_eye_bias);
}
stbi_write_png("galaxy_sorted_05.png", w, h, 4, pixels, 0);
STBI_FREE(pixels);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment