-
Notifications
You must be signed in to change notification settings - Fork 0
/
imgTOascii.c
154 lines (141 loc) · 4.28 KB
/
imgTOascii.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
typedef struct {
unsigned char red;
unsigned char green;
unsigned char blue;
} Pixel;
Pixel pix_gscale(Pixel p) {
Pixel gray;
unsigned char avg = (p.red + p.green + p.blue) / 3;
gray.red = gray.blue = gray.green = avg;
return gray;
}
Pixel avgcol(int startr, int startc, int width, int height, int row, int col, Pixel pixels[row][col]) {
int count = width*height;
int red, green, blue;
red = green = blue = 0;
//In this rectangle summate the r g b values
for (int r=startr; r<startr+height; ++r) {
if (r >= row || r < 0) continue;
for (int c=startc; c<startc+width; ++c) {
if (c >= col || c < 0) continue;
Pixel p = pixels[r][c];
red += p.red;
green += p.green;
blue += p.blue;
}
}
Pixel color;
//Average r g b values gives avergae color;
color.red = red/count;
color.green = green/count;
color.blue = blue/count;
return color;
}
/**
* @brief Custom method to read in words from file stream.
* A word is considered a contionous characters until a space
*
* @param fill char* String to read bytes into (terminator char appended)
* @param cap int Hard limit on number of bytes to read in (including terminator char)
* @param file FILE* file stream from stdio.h
* @return char* Pointer to the filled out string
*/
char *fgetw(char *fill, int cap, FILE *file) {
char c;
//Read in 1st to (cap-1)th bytes
for (int i=0; i<cap-1; ++i) {
c = fgetc(file);
//If the current byte is a space
//set it to terminator & We return the word
if (isspace(c)) {
fill[i] = '\0';
return fill;
}
fill[i] = c;
}
//Reaches the (cap)th byte and terminate
fill[cap-1] = '\0';
//We need to get chars until we hit next space to finish current word
while (!isspace(c)) c = fgetc(file);
return fill;
}
/**
* @brief Assume p is in greyscale
*
* @param val
* @param colmin
* @param colmax
* @return char
*/
char col_ascii(int val, int colmin, int colmax) {
static const char *const light = "$#DR8mHXKAUbG0pV4d9h6PkqwSE2]ayjxY5Zoen[ult13If}C{iF|(7J)vTLs?z/*cr!+<>;=^,_:'-.`";
int i = (val-colmin)*80/(colmax-colmin);
return light[i];
}
int main(int argc, char *argv[]) {
//Get filename from argument
if (argc != 2) { printf("Usage: ./imgTOascii filname\n"); return 1; }
char *filename = argv[1];
//Open the file
FILE *file;
file = fopen(filename, "r");
if (!file) { printf("error opening file: %s\n", filename); return 1; }
//Use a temp string to copy into
char strin[64];
//Throw away first word being P6 file identifier
(void)fgetw(strin, 64, file);
//Read words containing file size
int cols = atoi(fgetw(strin, 64, file));
int rows = atoi(fgetw(strin, 64, file));
//Assume the color range 0-255 for rgb
(void)fgetw(strin, 64, file);
//Read in pixels in the following consecutive bytes
static Pixel glob_buffer[25000000];
if (rows*cols*sizeof(Pixel) > sizeof(glob_buffer)) { printf("Image File is too BIG!"); return 1; }
Pixel (*pixels)[cols] = (Pixel (*)[cols])glob_buffer;
for (int r=0; r<rows; ++r) {
for (int c=0; c<cols; ++c) {
Pixel *p = pixels[r]+c;
p->red = fgetc(file);
p->green = fgetc(file);
p->blue = fgetc(file);
}
}
//We are done reading the file so we can close it
fclose(file);
//Pixelate the image down
int scols = 100;
double blocksize = (double)cols / scols;
int srows = ceil(rows/blocksize);
//Goes through blocks and sets greyscale pixels in top-left corner
for (int r=0; r<srows; ++r) {
for (int c=0; c<scols; ++c) {
pixels[r][c] = pix_gscale(avgcol(
r*blocksize, c*blocksize, blocksize,
blocksize, rows, cols, pixels));
}
}
//We need to find the min color to make that black to give contrast
unsigned char colmin = 255;
unsigned char colmax = 0;
for (int r=0; r<srows; ++r) {
for (int c=0; c<scols; ++c) {
unsigned char col = pixels[r][c].red;
if (col < colmin) colmin = col;
if (col > colmax) colmax = col;
}
}
//Print the ascii rep of the pixels
for (int r=0; r<srows; ++r) {
for (int c=0; c<scols; ++c) {
char ascii = col_ascii(pixels[r][c].red, colmin, colmax);
printf("%c ", ascii);
}
printf("\n");
}
return 0;
}