many little optimizations removing overhead
This commit is contained in:
+29
@@ -0,0 +1,29 @@
|
||||
# ---
|
||||
# Checks: 'bugprone-*,modernize-*,performance-*,readability-*'
|
||||
# WarningsAsErrors: ''
|
||||
# ---
|
||||
|
||||
---
|
||||
# Enable a broad range of useful C checks
|
||||
Checks: >
|
||||
-*,
|
||||
bugprone-*,
|
||||
concurrency-*,
|
||||
misc-*,
|
||||
modernize-*,
|
||||
performance-*,
|
||||
readability-*,
|
||||
portability-*,
|
||||
-readability-braces-around-statements,
|
||||
-readability-implicit-bool-conversion
|
||||
|
||||
# Treat all enabled checks as errors (optional, shows up as Red in Neovim)
|
||||
WarningsAsErrors: ""
|
||||
|
||||
# Project-specific settings
|
||||
CheckOptions:
|
||||
- key: readability-identifier-naming.VariableCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.FunctionCase
|
||||
value: lower_case
|
||||
---
|
||||
+178
-181
@@ -3,147 +3,159 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define BYTE_A 0xFF000000
|
||||
#define BYTE_R 0x00FF0000
|
||||
#define BYTE_G 0x0000FF00
|
||||
#define BYTE_B 0x000000FF
|
||||
#define BYTE_RGB 0x00FFFFFF
|
||||
#define BYTE 0xFF
|
||||
|
||||
#define SHIFT_8 8
|
||||
#define SHIFT_16 16
|
||||
#define SHIFT_24 24
|
||||
|
||||
#define MAX 255
|
||||
#define HALF_MAX ((int)(MAX / 2) + 1)
|
||||
|
||||
#define decode_a(clr) (((clr) >> SHIFT_24) & BYTE)
|
||||
#define decode_r(clr) (((clr) >> SHIFT_16) & BYTE)
|
||||
#define decode_g(clr) (((clr) >> SHIFT_8) & BYTE)
|
||||
#define decode_b(clr) ((clr) & BYTE)
|
||||
|
||||
#define encode(r, g, b) \
|
||||
(((unsigned int)(MAX) << SHIFT_24) | ((unsigned int)(r) << SHIFT_16) | \
|
||||
((unsigned int)(g) << SHIFT_8) | (unsigned int)(b))
|
||||
|
||||
#define CLAMP_MAX(x) (((x) > MAX) ? MAX : (x))
|
||||
#define CLAMP_MIN(x) (((x) < 0) ? 0 : (x))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int width, height, len;
|
||||
char* name;
|
||||
char magic_number[3];
|
||||
const char* name;
|
||||
char fmt[3];
|
||||
} Image;
|
||||
|
||||
unsigned int
|
||||
encoder(unsigned char r, unsigned char g, unsigned char b)
|
||||
static inline unsigned int
|
||||
set_alpha(const unsigned int clr, const unsigned char alpha_value)
|
||||
{
|
||||
return (b << 0) | (g << 8) | (r << 16);
|
||||
return (clr & BYTE_RGB) | alpha_value << SHIFT_24;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
decoder(unsigned int clr, int byte)
|
||||
static inline unsigned int
|
||||
invert_rgb(const unsigned int clr)
|
||||
{
|
||||
if (byte == 1) return (clr & 0x000000FF) >> 0;
|
||||
else if (byte == 2) return (clr & 0x0000FF00) >> 8;
|
||||
else if (byte == 3) return (clr & 0x00FF0000) >> 16;
|
||||
else if (byte == 4) return (clr & 0xFF000000) >> 24;
|
||||
return 0;
|
||||
return ((~clr) & BYTE_RGB) | (clr & BYTE_A);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
set_alpha(unsigned int clr, unsigned char alpha_value)
|
||||
static inline unsigned int
|
||||
swap_rb(const unsigned int clr)
|
||||
{
|
||||
return (clr & 0x00FFFFFF) | alpha_value << 24;
|
||||
return (clr & 0xFF00FF00) | ((clr & BYTE_R) >> SHIFT_16) |
|
||||
((clr & BYTE_B) << SHIFT_16);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
invert_rgb(unsigned int clr)
|
||||
static inline unsigned int
|
||||
to_grayscale(const unsigned int clr)
|
||||
{
|
||||
return ((~clr) & 0x00FFFFFF) | (clr & 0xFF000000);
|
||||
unsigned int red = decode_r(clr);
|
||||
unsigned int green = decode_g(clr);
|
||||
unsigned int blue = decode_b(clr);
|
||||
unsigned int gray =
|
||||
((red * 77) + (green * 150) + (blue * 29)) >> SHIFT_8;
|
||||
|
||||
return (clr & BYTE_A) | (gray << SHIFT_16) | (gray << SHIFT_8) | gray;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
swap_rb(unsigned int clr)
|
||||
{
|
||||
return (((clr & 0xFF00FF00) | ((decoder(clr, 3)) << 0) |
|
||||
((decoder(clr, 1) >> 0) << 16)));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
to_grayscale(unsigned int clr)
|
||||
{
|
||||
int average =
|
||||
(decoder(clr, 3) + decoder(clr, 2) + decoder(clr, 1)) * .33333;
|
||||
unsigned int mask = encoder(average, average, average);
|
||||
mask = set_alpha(mask, decoder(clr, 4));
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
apply_threshold(unsigned int clr, unsigned char limit)
|
||||
static inline unsigned int
|
||||
apply_threshold(const unsigned int clr, const unsigned char limit)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
if (decoder(to_grayscale(clr), 1) < limit) mask = encoder(0, 0, 0);
|
||||
else mask = encoder(255, 255, 255);
|
||||
mask = set_alpha(mask, decoder(clr, 4));
|
||||
return mask;
|
||||
if (decode_b(to_grayscale(clr)) < limit) mask = encode(0, 0, 0);
|
||||
else mask = encode(MAX, MAX, MAX);
|
||||
return BYTE_A | mask;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
adjust_brightness(unsigned int clr, float factor)
|
||||
static inline unsigned int
|
||||
adjust_brightness(const unsigned int clr, const float factor)
|
||||
{
|
||||
unsigned int red = decoder(clr, 3) * factor;
|
||||
unsigned int green = decoder(clr, 2) * factor;
|
||||
unsigned int blue = decoder(clr, 1) * factor;
|
||||
if (red > 255) red = 255;
|
||||
if (green > 255) green = 255;
|
||||
if (blue > 255) blue = 255;
|
||||
unsigned int mask = encoder(red, green, blue);
|
||||
mask = set_alpha(mask, decoder(clr, 4));
|
||||
return mask;
|
||||
unsigned int alpha = (clr & BYTE_A);
|
||||
unsigned int red =
|
||||
CLAMP_MAX((unsigned int)((float)decode_r(clr) * factor));
|
||||
unsigned int green =
|
||||
CLAMP_MAX((unsigned int)((float)decode_g(clr) * factor));
|
||||
unsigned int blue =
|
||||
CLAMP_MAX((unsigned int)((float)decode_b(clr) * factor));
|
||||
return (clr & BYTE_A) | (red << SHIFT_16) | (green << SHIFT_8) | blue;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
apply_tint(unsigned int clr_a, unsigned int clr_b)
|
||||
static inline unsigned int
|
||||
apply_tint(const unsigned int clr_a, const unsigned int clr_b)
|
||||
{
|
||||
unsigned char blue = (decoder(clr_a, 1) + decoder(clr_b, 1)) / 2;
|
||||
unsigned char green = (decoder(clr_a, 2) + decoder(clr_b, 2)) / 2;
|
||||
unsigned char red = (decoder(clr_a, 3) + decoder(clr_b, 3)) / 2;
|
||||
unsigned char blue = (decode_b(clr_a) + decode_b(clr_b)) / 2;
|
||||
unsigned char green = (decode_g(clr_a) + decode_g(clr_b)) / 2;
|
||||
unsigned char red = (decode_r(clr_a) + decode_r(clr_b)) / 2;
|
||||
|
||||
return set_alpha(encoder(red, green, blue), decoder(clr_a, 4));
|
||||
return set_alpha(encode(red, green, blue), decode_a(clr_a));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
apply_opacity(unsigned clr_a, unsigned int clr_b, float ratio)
|
||||
static inline unsigned int
|
||||
apply_opacity(const unsigned clr_a, const unsigned int clr_b, const float ratio)
|
||||
{
|
||||
unsigned char blue =
|
||||
(decoder(clr_a, 1) * (1 - ratio) + (decoder(clr_b, 1) * ratio));
|
||||
unsigned char green =
|
||||
(decoder(clr_a, 2) * (1 - ratio) + (decoder(clr_b, 2) * ratio));
|
||||
unsigned char red =
|
||||
(decoder(clr_a, 3) * (1 - ratio) + (decoder(clr_b, 3) * ratio));
|
||||
return set_alpha(encoder(red, green, blue), decoder(clr_a, 4));
|
||||
unsigned char blue = (unsigned char)((decode_b(clr_a) * (1 - ratio)) +
|
||||
((decode_b(clr_b) * ratio)));
|
||||
unsigned char green = (unsigned char)((decode_g(clr_a) * (1 - ratio)) +
|
||||
((decode_g(clr_b) * ratio)));
|
||||
unsigned char red = (unsigned char)((decode_r(clr_a) * (1 - ratio)) +
|
||||
((decode_r(clr_b) * ratio)));
|
||||
return set_alpha(encode(red, green, blue), decode_a(clr_a));
|
||||
}
|
||||
|
||||
unsigned int*
|
||||
ppm_encode(char* file, Image* img)
|
||||
static inline unsigned int*
|
||||
ppm_encode(const char* file, Image* img)
|
||||
{
|
||||
unsigned char r, g, b;
|
||||
printf("Starting encode...\n");
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
char fmt[3];
|
||||
int max_val;
|
||||
FILE* fptr;
|
||||
fptr = fopen(file, "r");
|
||||
if (!fptr) return NULL;
|
||||
fscanf(fptr, "%s", img->magic_number);
|
||||
if (!fptr) return nullptr;
|
||||
fscanf(fptr, "%s", fmt);
|
||||
fscanf(fptr, "%d %d", &img->width, &img->height);
|
||||
img->len = img->width * img->height;
|
||||
fscanf(fptr, "%d", &max_val);
|
||||
fgetc(fptr);
|
||||
unsigned int* buf = malloc(img->len * sizeof(unsigned int));
|
||||
if (!buf) return NULL;
|
||||
if (img->magic_number[1] == '3')
|
||||
if (!buf) return nullptr;
|
||||
if (fmt[1] == '3')
|
||||
{
|
||||
for (int i = 0; i < img->len; i++)
|
||||
{
|
||||
fscanf(fptr, "%hhu %hhu %hhu", &r, &g, &b);
|
||||
unsigned int packed = encoder(r, g, b);
|
||||
buf[i] = set_alpha(packed, 255);
|
||||
fscanf(fptr, "%hhu %hhu %hhu", &red, &green, &blue);
|
||||
buf[i] = encode(red, green, blue);
|
||||
}
|
||||
}
|
||||
else if (img->magic_number[1] == '6')
|
||||
else if (fmt[1] == '6')
|
||||
{
|
||||
for (int i = 0; i < img->len; i++)
|
||||
{
|
||||
fread(&r, sizeof(unsigned char), 1, fptr);
|
||||
fread(&g, sizeof(unsigned char), 1, fptr);
|
||||
fread(&b, sizeof(unsigned char), 1, fptr);
|
||||
unsigned int packed = encoder(r, g, b);
|
||||
buf[i] = set_alpha(packed, 255);
|
||||
fread(&red, sizeof(unsigned char), 1, fptr);
|
||||
fread(&green, sizeof(unsigned char), 1, fptr);
|
||||
fread(&blue, sizeof(unsigned char), 1, fptr);
|
||||
buf[i] = encode(red, green, blue);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fptr);
|
||||
printf("Encoding done!\n");
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
ppm_apply_brightness(unsigned int* buf, Image img, float factor)
|
||||
static inline void
|
||||
ppm_apply_brightness(unsigned int* buf, const Image img, const float factor)
|
||||
{
|
||||
for (int i = 0; i < img.len; i++)
|
||||
{
|
||||
@@ -151,78 +163,89 @@ ppm_apply_brightness(unsigned int* buf, Image img, float factor)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ppm_decode(unsigned int* buf, Image img)
|
||||
static inline void
|
||||
ppm_decode(const unsigned int* buf, const Image img)
|
||||
{
|
||||
unsigned char red, green, blue;
|
||||
printf("Starting decode...\n");
|
||||
FILE* fptr;
|
||||
|
||||
if (img.magic_number[1] == '3') fptr = fopen(img.name, "w");
|
||||
if (img.magic_number[1] == '6') fptr = fopen(img.name, "wb");
|
||||
if (img.fmt[1] == '3') fptr = fopen(img.name, "w");
|
||||
if (img.fmt[1] == '6') fptr = fopen(img.name, "wb");
|
||||
if (!fptr) return;
|
||||
|
||||
fprintf(fptr, "%s\n%d %d\n255\n", img.magic_number, img.width,
|
||||
img.height);
|
||||
fprintf(fptr, "%s\n%d %d\n255\n", img.fmt, img.width, img.height);
|
||||
if (img.fmt[1] == '3')
|
||||
{
|
||||
for (int i = 0; i < img.len; i++)
|
||||
{
|
||||
red = decoder(buf[i], 3);
|
||||
green = decoder(buf[i], 2);
|
||||
blue = decoder(buf[i], 1);
|
||||
unsigned char red = decode_r(buf[i]);
|
||||
unsigned char green = decode_g(buf[i]);
|
||||
unsigned char blue = decode_b(buf[i]);
|
||||
fprintf(fptr, "%d %d %d ", red, green, blue);
|
||||
if (i % 7 == 0)
|
||||
{
|
||||
fprintf(fptr, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (img.fmt[1] == '6')
|
||||
{
|
||||
for (int i = 0; i < img.len; i++)
|
||||
{
|
||||
unsigned char red = decode_r(buf[i]);
|
||||
unsigned char green = decode_g(buf[i]);
|
||||
unsigned char blue = decode_b(buf[i]);
|
||||
fwrite(&red, 1, 1, fptr);
|
||||
fwrite(&green, 1, 1, fptr);
|
||||
fwrite(&blue, 1, 1, fptr);
|
||||
}
|
||||
}
|
||||
fclose(fptr);
|
||||
printf("Decode Done!\n");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
channel_mask(unsigned int clr, char keep)
|
||||
static inline unsigned int
|
||||
channel_mask(const unsigned int clr, const char keep)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
switch (keep)
|
||||
{
|
||||
case 'r':
|
||||
mask = encoder(decoder(clr, 3), 0, 0);
|
||||
return clr & (BYTE_A | BYTE_R);
|
||||
break;
|
||||
case 'g':
|
||||
mask = encoder(0, decoder(clr, 2), 0);
|
||||
return clr & (BYTE_A | BYTE_G);
|
||||
break;
|
||||
case 'b':
|
||||
mask = encoder(0, 0, decoder(clr, 1));
|
||||
return clr & (BYTE_A | BYTE_B);
|
||||
break;
|
||||
}
|
||||
mask = set_alpha(mask, decoder(clr, 4));
|
||||
return mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
chromatic_circular_shift(unsigned int clr, int n)
|
||||
static inline unsigned int
|
||||
chromatic_circular_shift(const unsigned int clr, const int n)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
unsigned char r, g, b;
|
||||
r = decoder(clr, 3);
|
||||
g = decoder(clr, 2);
|
||||
b = decoder(clr, 1);
|
||||
unsigned int red = decode_r(clr);
|
||||
unsigned int green = decode_g(clr);
|
||||
unsigned int blue = decode_b(clr);
|
||||
|
||||
r = (r << n) | (r >> (8 - n));
|
||||
g = (g << n) | (g >> (8 - n));
|
||||
b = (b << n) | (b >> (8 - n));
|
||||
mask = encoder(r, g, b);
|
||||
mask = set_alpha(mask, decoder(clr, 4));
|
||||
return mask;
|
||||
red = ((red << n) | (red >> (SHIFT_8 - n))) & BYTE;
|
||||
green = ((green << n) | (green >> (SHIFT_8 - n))) & BYTE;
|
||||
blue = ((blue << n) | (blue >> (SHIFT_8 - n))) & BYTE;
|
||||
return encode(red, green, blue);
|
||||
}
|
||||
|
||||
unsigned int*
|
||||
horizontal_flip(unsigned int* buf, Image img)
|
||||
static inline unsigned int*
|
||||
horizontal_flip(unsigned int* buf, const Image img)
|
||||
{
|
||||
unsigned int* flip = malloc(img.len * sizeof(unsigned int));
|
||||
if (!flip) return NULL;
|
||||
if (!flip) return nullptr;
|
||||
int idx = 0;
|
||||
for (int i = 0; i < img.height; i++)
|
||||
{
|
||||
for (int k = img.width - 1; k >= 0; k--)
|
||||
{
|
||||
flip[idx] = buf[i * img.width + k];
|
||||
flip[idx] = buf[(i * img.width) + k];
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
@@ -231,18 +254,18 @@ horizontal_flip(unsigned int* buf, Image img)
|
||||
return flip;
|
||||
}
|
||||
|
||||
unsigned int*
|
||||
static inline unsigned int*
|
||||
vertical_flip(unsigned int* buf, Image img)
|
||||
{
|
||||
unsigned int* flip = malloc(img.len * sizeof(unsigned int));
|
||||
if (!flip) return NULL;
|
||||
if (!flip) return nullptr;
|
||||
|
||||
int idx = 0;
|
||||
for (int i = img.height - 1; i >= 0; i--)
|
||||
{
|
||||
for (int k = 0; k < img.width; k++)
|
||||
{
|
||||
flip[idx] = buf[i * img.width + k];
|
||||
flip[idx] = buf[(i * img.width) + k];
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
@@ -251,39 +274,34 @@ vertical_flip(unsigned int* buf, Image img)
|
||||
return flip;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
static inline unsigned int
|
||||
constrast_adjustment(unsigned int clr, float factor)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
int r = factor * (decoder(clr, 3) - 128) + 128;
|
||||
int g = factor * (decoder(clr, 2) - 128) + 128;
|
||||
int b = factor * (decoder(clr, 1) - 128) + 128;
|
||||
if (r > 255) r = 255;
|
||||
if (g > 255) g = 255;
|
||||
if (b > 255) b = 255;
|
||||
if (r < 0) r = 0;
|
||||
if (g < 0) g = 0;
|
||||
if (b < 0) b = 0;
|
||||
mask = encoder(r, g, b);
|
||||
mask = set_alpha(mask, decoder(clr, 4));
|
||||
return mask;
|
||||
int red = CLAMP_MIN(CLAMP_MAX(
|
||||
(int)(factor * (float)(int)(decode_r(clr) - HALF_MAX)) + HALF_MAX));
|
||||
int green = CLAMP_MIN(CLAMP_MAX(
|
||||
(int)(factor * (float)(int)(decode_g(clr) - HALF_MAX)) + HALF_MAX));
|
||||
int blue = CLAMP_MIN(CLAMP_MAX(
|
||||
(int)(factor * (float)(int)(decode_b(clr) - HALF_MAX)) + HALF_MAX));
|
||||
return BYTE_A | (red << SHIFT_16) | (green << SHIFT_8) | blue;
|
||||
}
|
||||
|
||||
unsigned int*
|
||||
static inline unsigned int*
|
||||
rotate(unsigned int* buf, Image* img, int len)
|
||||
{
|
||||
unsigned int* mask = malloc(len * sizeof(unsigned int));
|
||||
int old_width = img->width;
|
||||
int old_height = img->height;
|
||||
for (int y = 0; y < old_height; y++)
|
||||
for (int row = 0; row < old_height; row++)
|
||||
{
|
||||
for (int x = 0; x < old_width; x++)
|
||||
for (int col = 0; col < old_width; col++)
|
||||
{
|
||||
int new_height = x;
|
||||
int new_width = (old_height - 1 - y);
|
||||
int new_height = col;
|
||||
int new_width = (old_height - 1 - row);
|
||||
|
||||
mask[new_height * old_height + new_width] =
|
||||
buf[y * old_width + x];
|
||||
mask[(new_height * old_height) + new_width] =
|
||||
buf[(row * old_width) + col];
|
||||
}
|
||||
}
|
||||
img->width = old_height;
|
||||
@@ -292,52 +310,31 @@ rotate(unsigned int* buf, Image* img, int len)
|
||||
return mask;
|
||||
}
|
||||
|
||||
Image
|
||||
create_image(int w, int h, char* name, char* fmt)
|
||||
{
|
||||
Image image = {
|
||||
.width = w,
|
||||
.height = h,
|
||||
.len = w * h,
|
||||
.name = name,
|
||||
};
|
||||
image.magic_number[0] = fmt[0];
|
||||
image.magic_number[1] = fmt[1];
|
||||
image.magic_number[2] = '\0';
|
||||
return image;
|
||||
}
|
||||
|
||||
void
|
||||
print_bits_int(unsigned int n)
|
||||
{
|
||||
for (int i = 31; i >= 0; i--)
|
||||
{
|
||||
if (i == 7 || i == 15 || i == 23) write(1, " ", 1);
|
||||
char bit = (n & (1 << i)) ? '1' : '0';
|
||||
write(1, &bit, 1);
|
||||
}
|
||||
write(1, "\n", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
Image image = create_image(3, 2, "../color.ppm", "P6");
|
||||
Image img = { .width = 3,
|
||||
.height = 2,
|
||||
.name = "../color.ppm",
|
||||
.fmt = "P3",
|
||||
.len = 0 };
|
||||
|
||||
unsigned int* buf = ppm_encode("../assets/4ktest.ppm", &image);
|
||||
unsigned int* buf = ppm_encode("../assets/8ktest.ppm", &img);
|
||||
if (buf)
|
||||
{
|
||||
// ppm_apply_brightness(buf, image, 2);
|
||||
//
|
||||
for (int i = 0; i < image.len; i++)
|
||||
ppm_apply_brightness(buf, img, 2);
|
||||
|
||||
for (int i = 0; i < img.len; i++)
|
||||
{
|
||||
// buf[i] = channel_mask(buf[i], 'b');
|
||||
// buf[i] = chromatic_circular_shift(buf[i], (rand() % 10));
|
||||
// buf[i] = constrast_adjustment(buf[i], 2);
|
||||
buf[i] = to_grayscale(buf[i]);
|
||||
buf[i] = channel_mask(buf[i], 'r');
|
||||
// buf[i] = chromatic_circular_shift(buf[i], (rand() %
|
||||
// 5)); buf[i] = constrast_adjustment(buf[i], .1f);
|
||||
// buf[i] = adjust_brightness(buf[i], 1.5f);
|
||||
// buf[i] = swap_rb(buf[i]);
|
||||
// buf[i] = to_grayscale(buf[i]);
|
||||
}
|
||||
// buf = rotate(buf, &image, image.len);
|
||||
ppm_decode(buf, image);
|
||||
ppm_decode(buf, img);
|
||||
free(buf);
|
||||
}
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user