aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bitmap.c69
-rw-r--r--src/bitmap.h11
-rw-r--r--src/color.c9
-rw-r--r--src/color.h6
-rw-r--r--src/dynalloc.c22
-rw-r--r--src/dynalloc.h12
-rw-r--r--src/main.c149
7 files changed, 141 insertions, 137 deletions
diff --git a/src/bitmap.c b/src/bitmap.c
index c64a4c0..6d72cb0 100644
--- a/src/bitmap.c
+++ b/src/bitmap.c
@@ -30,7 +30,7 @@ static uint32_t bitmap_flip_byte(unsigned char* _v, int _c)
int bitmap_read(char *_file, struct bitmap_image *_bitmap)
{
- if (!_bitmap )
+ if ( !_bitmap )
return 5;
struct bitmap_file_header header;
@@ -176,6 +176,7 @@ static struct bitmap_image bitmap_read_pixel_data(FILE *_file, struct bitmap_fil
}
int bitmap_copy ( struct bitmap_image *_input, struct bitmap_image *_output ) {
+ // TODO implement
return 1;
}
@@ -183,10 +184,7 @@ int bitmap_convert_monochrome ( struct bitmap_image *_input, struct bitmap_image
if ( !_input || !_output )
return 1;
- uint8_t **monochrome_bitmap = malloc( sizeof (*monochrome_bitmap) * _input->x );
- for ( int i = 0; i < _input->y; i++ ) {
- monochrome_bitmap[i] = malloc ( sizeof (**monochrome_bitmap) * _input->y );
- }
+ uint8_t **monochrome_bitmap = (uint8_t**) dynalloc_2d_array( _input->x, _input->y, sizeof(uint8_t));
for ( unsigned int x = 0; x < _input->x; x++ ) {
for ( unsigned int y = 0; y < _input->y; y++ ) {
@@ -198,16 +196,69 @@ int bitmap_convert_monochrome ( struct bitmap_image *_input, struct bitmap_image
}
_output->R = _output->G = _output->B = monochrome_bitmap;
+ _output->tags = BITMAP_MONOCHROME;
+ _output->x = _input->x;
+ _output->y = _input->y;
+ //TODO min/max brightness
return 0;
}
-int bitmap_transform ( struct bitmap_image *_input, struct bitmap_image *_output ) {
- return 1;
+int bitmap_shrink ( struct bitmap_image *_input, struct bitmap_image *_output, unsigned int _factor_x, unsigned int _factor_y ) {
+ if ( !_input || !_output )
+ return 1;
+
+ /* New Size */
+ _output->x = _input->x / _factor_x;
+ _output->y = _input->y / _factor_y;
+ _output->tags = _input->tags;
+
+ /* Allocate memory */
+ if ( _input->tags & BITMAP_MONOCHROME ) {
+ _output->R = _output->G = _output->B =
+ (uint8_t**) dynalloc_2d_array ( _output->x, _output->y, sizeof ( uint8_t) );
+ } else {
+ _output->R = (uint8_t**) dynalloc_2d_array ( _output->x, _output->y, sizeof ( uint8_t) );
+ _output->G = (uint8_t**) dynalloc_2d_array ( _output->x, _output->y, sizeof ( uint8_t) );
+ _output->B = (uint8_t**) dynalloc_2d_array ( _output->x, _output->y, sizeof ( uint8_t) );
+ }
+
+ for(unsigned int x = 0; x < _output->x; x++) {
+ for(unsigned int y = 0; y < _output->y; y++) {
+ // Unsafe for > 2^56 Pixels (Hopefully unrealistic)
+ uint64_t color_sum[3] = {0,0,0};
+ const uint64_t pixel_count = _factor_x * _factor_y;
+
+ // Average Pixel block
+ for(unsigned int row_c = 0; row_c < _factor_y; row_c++) {
+ unsigned int row = y * _factor_y + row_c; //Offset
+
+ for(unsigned int col_c = 0; col_c < _factor_x; col_c++) {
+ unsigned int col = x * _factor_x + col_c; //Offset
+
+ color_sum[0] += (uint64_t) _input->R[col][row];
+ color_sum[1] += (uint64_t) _input->G[col][row];
+ color_sum[2] += (uint64_t) _input->B[col][row];
+ }//for col_c
+ }//for row_c
+
+ _output->R[x][y] = (uint8_t) (color_sum[0] / pixel_count);
+ _output->G[x][y] = (uint8_t) (color_sum[1] / pixel_count);
+ _output->B[x][y] = (uint8_t) (color_sum[2] / pixel_count);
+ }//for y
+ }//for x
+
+ return 0;
}
-static uint8_t bitmap_rgb_luminance(uint8_t R, uint8_t G, uint8_t B)
-{
+int bitmap_fit_to_width ( struct bitmap_image *_input, struct bitmap_image *_output, unsigned int _width ) {
+ unsigned int factor_x = (unsigned int)((float)_input->x / (float) _width );
+ unsigned int factor_y = (unsigned int)(((float)_input->y / (float)_input->x ) * (float) factor_x * 2);
+
+ return bitmap_shrink ( _input, _output, factor_x, factor_y );
+}
+
+static uint8_t bitmap_rgb_luminance(uint8_t R, uint8_t G, uint8_t B) {
uint8_t ret;
ret = sqrt( 0.299*pow(R,2) + 0.587*pow(G,2) + 0.114*pow(B,2) ); //(char)(R+R+B+G+G+G)/6;
diff --git a/src/bitmap.h b/src/bitmap.h
index 3b942a7..48fd1ac 100644
--- a/src/bitmap.h
+++ b/src/bitmap.h
@@ -1,5 +1,4 @@
-/*
- * src/bitmap.h
+/* * src/bitmap.h
* (c) 2020 Jonas Gunz <himself@jonasgunz.de>
* License: MIT
*/
@@ -12,6 +11,8 @@
#include <stdlib.h>
#include <math.h>
+#include "dynalloc.h"
+
#define _HEADER_SIZE 54 //Fileheader + infoheader
#define IDENTIFIER 0x424d //BM BitMap identifier
@@ -65,6 +66,8 @@ struct bitmap_image
uint8_t **B;
uint8_t tags;
+ uint8_t monochrome_maximum_brightness;
+ uint8_t monochrome_minimum_brightness;
};
int bitmap_read ( char *_file, struct bitmap_image *_bitmap );
@@ -73,6 +76,8 @@ int bitmap_copy ( struct bitmap_image *_input, struct bitmap_image *_output );
int bitmap_convert_monochrome ( struct bitmap_image *_input, struct bitmap_image *_output );
-int bitmap_transform ( struct bitmap_image *_input, struct bitmap_image *_output );
+int bitmap_shrink ( struct bitmap_image *_input, struct bitmap_image *_output, unsigned int _factor_x, unsigned int _factor_y );
+
+int bitmap_fit_to_width ( struct bitmap_image *_input, struct bitmap_image *_output, unsigned int _width );
#endif /* end of include guard: _BITMAP_H_ */
diff --git a/src/color.c b/src/color.c
index d0fbe1b..d7b3cdf 100644
--- a/src/color.c
+++ b/src/color.c
@@ -64,12 +64,13 @@ char* calc_col(uint8_t R, uint8_t G, uint8_t B)
return colors[ nearest_num ].no;
}
//TODO consolidate
-char* calc_col_ansi(uint8_t R, uint8_t G, uint8_t B)
+char* calc_col_ansi(uint8_t R, uint8_t G, uint8_t B, uint8_t _mode)
{
+ int mode = _mode == COLOR_BG ? 4 : 3;
int num = 36 * (R/51) + 6 * (G/51) + (B/51);
- char *c = malloc(9);
- snprintf( c, 6, "38;5;" );
- snprintf( c + 5, 4, "%i", num + 16 );
+ char *c = malloc(12);
+ snprintf( c, 8, "\e[%i8;5;", mode );
+ snprintf( c + 7, 5, "%im", num + 16 );
return c;
}
diff --git a/src/color.h b/src/color.h
index 70a8b16..a2f82d3 100644
--- a/src/color.h
+++ b/src/color.h
@@ -8,7 +8,9 @@
#include "m.h"
-#define _COLORS_SIZE 16u
+#define _COLORS_SIZE 16u
+#define COLOR_FG 1
+#define COLOR_BG 2
struct console_color
{
@@ -28,7 +30,7 @@ uint8_t rgb_luminance(uint8_t R, uint8_t G, uint8_t B);
//Get nearest printable color in console
char *calc_col(uint8_t R, uint8_t G, uint8_t B);
-char *calc_col_ansi(uint8_t R, uint8_t G, uint8_t B);
+char *calc_col_ansi(uint8_t R, uint8_t G, uint8_t B, uint8_t _mode);
char *calc_bg_col_ansi(uint8_t R, uint8_t G, uint8_t B);
#endif //_COLOR_H_
diff --git a/src/dynalloc.c b/src/dynalloc.c
new file mode 100644
index 0000000..ecce3e7
--- /dev/null
+++ b/src/dynalloc.c
@@ -0,0 +1,22 @@
+/*
+ * src/dynalloc.c
+ * (c) 2020 Jonas Gunz <himself@jonasgunz.de>
+ * License: MIT
+*/
+#include "dynalloc.h"
+
+void** dynalloc_2d_array ( unsigned int _x, unsigned int _y, unsigned int _sizeof ) {
+ void** ret = NULL;
+
+ ret = malloc ( _x * sizeof ( void* ) );
+ for ( int i = 0; i < _x; i++ )
+ ret[i] = malloc ( _y * _sizeof );
+
+ return ret;
+}
+
+void dynalloc_2d_array_free ( unsigned int _x, unsigned int _y, void** _array ) {
+ for ( int i = 0; i < _x; i++ )
+ free ( _array[i] );
+ free(_array);
+}
diff --git a/src/dynalloc.h b/src/dynalloc.h
new file mode 100644
index 0000000..852f608
--- /dev/null
+++ b/src/dynalloc.h
@@ -0,0 +1,12 @@
+/*
+ * src/dynalloc.h
+ * (c) 2020 Jonas Gunz <himself@jonasgunz.de>
+ * License: MIT
+*/
+#pragma once
+
+#include <stdlib.h>
+
+void** dynalloc_2d_array ( unsigned int _x, unsigned int _y, unsigned int _sizeof );
+
+void dynalloc_2d_array_free ( unsigned int _x, unsigned int _y, void** _array );
diff --git a/src/main.c b/src/main.c
index e9e04e3..d73c58a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -15,8 +15,6 @@
#include "m.h"
#include "color.h"
-// #define CLEANUP 1
-
#ifdef _DEBUG
#warning "Compiling with DEBUG"
#define DEBUG_PRINTF(...) { printf(__VA_ARGS__); }
@@ -48,123 +46,51 @@ int main(int argc, char *argv[])
{
struct prog_param args = parse_args(argc, argv);
- //Stores a luminance array
- uint8_t **image_monochrome;
- //Stores a color array
- char* **col_buff;
+ struct bitmap_image bitmap;
+ struct bitmap_image shrunk_bitmap;
+ struct bitmap_image monochrome_bitmap;
- uint8_t brightness_max = 0x00;
- uint8_t brightness_min = 0xff;
+ uint8_t brightness_min = 0x00;
+ uint8_t brightness_max = 0xff;
+
+ int size_x, size_y;
- struct bitmap_image bitmap;
if ( bitmap_read(args.filename, &bitmap) ) {
printf("Error reading file\n");
return 1;
}
- // Character count in x and y in final ASCII image
- unsigned int size_x,size_y;
-
if(args.fit_width > 0) {
args.charsize_x = (unsigned int)((float)bitmap.x / (float)args.fit_width);
args.charsize_y = (unsigned int)(((float)bitmap.y / (float)bitmap.x) * (float)args.charsize_x * 2);
}
- size_x = bitmap.x / args.charsize_x;
- size_y = bitmap.y / args.charsize_y;
-
- DEBUG_PRINTF("Output size: %u x %u\n", size_x, size_y);
- //Allocate character sotrage
- image_monochrome = malloc(sizeof(*image_monochrome) * size_x);
- for (int i = 0; i < size_x; i++)
- image_monochrome[i] = malloc(sizeof(image_monochrome[i]) * size_y);
+ bitmap_shrink ( &bitmap, &shrunk_bitmap, args.charsize_x, args.charsize_y );
+ bitmap_convert_monochrome ( &shrunk_bitmap, &monochrome_bitmap );
- //Allocate color storage if color enabled
- if(args.color) {
- col_buff = malloc(sizeof(*col_buff) * size_x);
- for (int i = 0; i < size_x; i++)
- col_buff[i] = malloc(sizeof(col_buff[i]) * size_y);
+ if( args.dynamic_range ) {
+ brightness_min = monochrome_bitmap.monochrome_minimum_brightness;
+ brightness_max = monochrome_bitmap.monochrome_maximum_brightness;
+ DEBUG_PRINTF("Dynamic Range: Brightness Values: Min: %u Max: %u\n", brightness_min, brightness_max);
}
- //Nest thine Lööps
- //Very not optimal Variable names!!!!!!!!!!!!!
- //
- //For every size_x * size_y block: calculate average values of pixel blocks
- for(unsigned int x = 0; x < size_x; x++) {
- for(unsigned int y = 0; y < size_y; y++) {
- /* Luminance for every pixel */
- uint8_t brightness [ args.charsize_x ][ args.charsize_y ];
- /* Color for every Pixel */
- uint8_t color_list[ 3 ][ args.charsize_x * args.charsize_y ]; //RGB Values of Pixels, used for averaging
- unsigned int color_list_counter = 0;
-
- /* Iterate through pixel block, save brightness and color if set */
- for(unsigned int row_c = 0; row_c < args.charsize_y; row_c++) {
- unsigned int row = y * args.charsize_y + row_c; //Actual position in Bitmap
-
- for(unsigned int col_c = 0; col_c < args.charsize_x; col_c++) {
- unsigned int col = x * args.charsize_x + col_c; //Actual position in bitmap
-
- brightness[col_c][row_c] = rgb_luminance(
- bitmap.R[col][row],
- bitmap.G[col][row],
- bitmap.B[col][row]);
-
- if(args.color) {
- color_list[0][color_list_counter] = bitmap.R[col][row];
- color_list[1][color_list_counter] = bitmap.G[col][row];
- color_list[2][color_list_counter] = bitmap.B[col][row];
- color_list_counter++;
- }//if
- }//for col_c
- }//for row_c
-
- /* Calculate average brightness in pixel block */
- image_monochrome[x][y] = avg(args.charsize_x * args.charsize_y, *brightness);
-
- /* Calculate average color in pixel block */
- if(args.color) {
- if(args.use_whitespace)
- col_buff[x][y] = calc_bg_col_ansi(
- (uint8_t)avg(args.charsize_x * args.charsize_y, color_list[0]),
- (uint8_t)avg(args.charsize_x * args.charsize_y, color_list[1]),
- (uint8_t)avg(args.charsize_x * args.charsize_y, color_list[2]));
- else
- col_buff[x][y] = calc_col_ansi(
- (uint8_t)avg(args.charsize_x * args.charsize_y, color_list[0]),
- (uint8_t)avg(args.charsize_x * args.charsize_y, color_list[1]),
- (uint8_t)avg(args.charsize_x * args.charsize_y, color_list[2]));
- } // if args.color
-
- /* Save min and max brightness values for dynamic range */
- if((uint8_t)image_monochrome[x][y] < brightness_min)
- brightness_min = image_monochrome[x][y];
- if((uint8_t)image_monochrome[x][y] > brightness_max)
- brightness_max = image_monochrome[x][y];
- }//for y
- }//for x
-
-
/* Apply Default Colors */
if(args.color)
printf("\e[0m");
-
- if(! args.dynamic_range) {
- brightness_min = 0;
- brightness_max = 255;
- } else {
- DEBUG_PRINTF("Dynamic Range: Brightness Values: Min: %u Max: %u\n", brightness_min, brightness_max);
- }
/* Print the buffer */
- for(int y = 0; y<size_y; y++) {
- for(int x = 0; x < size_x; x++) {
+ uint8_t color_mode = args.use_whitespace ? COLOR_BG : COLOR_FG;
+ for(int y = 0; y < monochrome_bitmap.y; y++) {
+ for(int x = 0; x < monochrome_bitmap.x; x++) {
+ char c = args.use_whitespace ? ' ' : calc_char(monochrome_bitmap.R[x][y], brightness_min, brightness_max, args.character_map);
+
if(args.color)
- printf("\e[%sm", col_buff[x][y]);
- if(args.use_whitespace)
- printf(" ");
- else
- printf("%c", calc_char(image_monochrome[x][y], brightness_min, brightness_max, args.character_map));
+ printf("%s", calc_col_ansi(
+ shrunk_bitmap.R[x][y],
+ shrunk_bitmap.G[x][y],
+ shrunk_bitmap.B[x][y],
+ color_mode ) );
+ printf("%c", c);
}
printf("\e[0m\n");
}
@@ -175,27 +101,6 @@ int main(int argc, char *argv[])
DEBUG_PRINTF("Finished!\n");
-#ifdef CLEANUP
-#warning "Cleanup included"
- for(int i = 0; i < size_x; i++)
- free (image_monochrome[i]);
- free(image_monochrome);
-
- for(int i = 0; i < bitmap.x; i++) {
- free(bitmap.R[i]);
- free(bitmap.G[i]);
- free(bitmap.B[i]);
- }
- free(bitmap.R);
- free(bitmap.G);
- free(bitmap.B);
- if(args.color) {
- for(int i = 0; i < size_x; i++)
- free(col_buff[i]);
- free(col_buff);
- }
-#endif
-
return 0;
}//main
@@ -263,6 +168,12 @@ struct prog_param parse_args(int argc, char *argv[])
exit(1);
}
+ if(ret.use_whitespace && !ret.color) {
+ printf("use -w only with -c\n");
+ print_help();
+ exit(1);
+ }
+
if(!ret.charsize_y)
ret.charsize_y = 2 * ret.charsize_x;