Last active
December 26, 2023 00:34
-
-
Save studiosi/73aeb8442613a54eec6ef54f44641a4b to your computer and use it in GitHub Desktop.
Single file library to extend stb_image and convert images to monochrome with different standards
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SIL_INCLUDE_MONOCHROME_H | |
#define SIL_INCLUDE_MONOCHROME_H | |
// No need to include the implementation, or double include the definitions | |
#ifndef STBI_INCLUDE_STB_IMAGE_H | |
#include "stb_image.h" | |
#endif | |
// API definition | |
typedef enum T_SIL_MONOCHROME_CONVERSION_TYPE { | |
SIL_MONOCHROME_CONVERSION_AVERAGE = 0, | |
SIL_MONOCHROME_CONVERSION_CIE_1391 = 1, | |
SIL_MONOCHROME_CONVERSION_REC_601 = 2, | |
SIL_MONOCHROME_CONVERSION_ITU_R_BT_709 = 3, | |
SIL_MONOCHROME_CONVERSION_ITU_R_BT_2100 = 4, | |
SIL_MONOCHROME_CONVERSION_CHANNEL_RED = 5, | |
SIL_MONOCHROME_CONVERSION_CHANNEL_GREEN = 6, | |
SIL_MONOCHROME_CONVERSION_CHANNEL_BLUE = 7, | |
} SIL_MONOCHROME_CONVERSION_TYPE; | |
stbi_uc *sil_to_monochrome(SIL_MONOCHROME_CONVERSION_TYPE type, const stbi_uc *img_data, int size_x, int size_y, int n_channels); | |
// API implementation | |
#ifdef SIL_MONOCHROME_IMPLEMENTATION | |
static inline stbi_uc sil_monochrome_fn_average(const int r, const int g, const int b) { | |
double l = round(((double) r + (double) g + (double) b) / 3.0); | |
return (stbi_uc) l; | |
} | |
static inline stbi_uc sil_monochrome_fn_cie_1391(const int r, const int g, const int b) { | |
double l = round((0.2126 * (double) r) + (0.7152 * (double) g) + (0.0722 * (double) b)); | |
return (stbi_uc) l; | |
} | |
static inline stbi_uc sil_monochrome_fn_rec_601(const int r, const int g, const int b) { | |
double l = round((0.299 * (double) r) + (0.587 * (double) g) + (0.114 * (double) b)); | |
return (stbi_uc) l; | |
} | |
static inline stbi_uc sil_monochrome_fn_itu_r_bt_2100(const int r, const int g, const int b) { | |
double l = round((0.2627 * (double) r) + (0.678 * (double) g) + (0.0593 * (double) b)); | |
return (stbi_uc) l; | |
} | |
stbi_uc *sil_to_monochrome(const SIL_MONOCHROME_CONVERSION_TYPE type, const stbi_uc *img_data, const int size_x, const int size_y, const int n_channels) { | |
assert(n_channels == STBI_rgb || n_channels == STBI_rgb_alpha); | |
// 1 channel, 1BPP | |
stbi_uc *new_data = STBI_MALLOC(size_x * size_y * sizeof(stbi_uc)); | |
int idx_old = 0, idx_new = 0; | |
for(int y = 0; y < size_y; y++) | |
for(int x = 0; x < size_x; x++) { | |
int r = img_data[idx_old]; | |
int g = img_data[idx_old + 1]; | |
int b = img_data[idx_old + 2]; | |
// Luminance = according to type of conversion | |
switch(type) { | |
case SIL_MONOCHROME_CONVERSION_CHANNEL_RED: | |
new_data[idx_new] = r; | |
break; | |
case SIL_MONOCHROME_CONVERSION_CHANNEL_GREEN: | |
new_data[idx_new] = g; | |
break; | |
case SIL_MONOCHROME_CONVERSION_CHANNEL_BLUE: | |
new_data[idx_new] = b; | |
break; | |
case SIL_MONOCHROME_CONVERSION_ITU_R_BT_2100: | |
new_data[idx_new] = sil_monochrome_fn_itu_r_bt_2100(r, g, b); | |
break; | |
case SIL_MONOCHROME_CONVERSION_REC_601: | |
new_data[idx_new] = sil_monochrome_fn_rec_601(r, g, b); | |
break; | |
case SIL_MONOCHROME_CONVERSION_ITU_R_BT_709: | |
case SIL_MONOCHROME_CONVERSION_CIE_1391: | |
new_data[idx_new] = sil_monochrome_fn_cie_1391(r, g, b); | |
break; | |
case SIL_MONOCHROME_CONVERSION_AVERAGE: | |
default: | |
new_data[idx_new] = sil_monochrome_fn_average(r, g, b); | |
break; | |
} | |
idx_old += n_channels; | |
idx_new += 1; | |
} | |
return new_data; | |
} | |
#endif // SIL_MONOCHROME_IMPLEMENTATION | |
#endif // SIL_INCLUDE_MONOCHROME_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment