Subversion Repositories RepoView

Rev

Rev 29 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 29 Rev 34
Line 1... Line 1...
1
/* $Id: avatar.c 29 2024-08-21 19:23:54Z nishi $ */
1
/* $Id: avatar.c 34 2024-08-22 02:50:46Z nishi $ */
2
 
2
 
3
#include "rv_avatar.h"
3
#include "rv_avatar.h"
4
 
4
 
-
 
5
#include "rv_md5.h"
-
 
6
 
5
#include <stdio.h>
7
#include <stdio.h>
6
#include <stdlib.h>
8
#include <stdlib.h>
7
 
9
 
8
#include <png.h>
10
#include <png.h>
9
 
11
 
-
 
12
int hex_to_num(const char* hex, int len) {
-
 
13
	int i;
-
 
14
	int num = 0;
-
 
15
	for(i = 0; i < len; i++) {
-
 
16
		num = num << 4;
-
 
17
		if(hex[i] >= '0' && hex[i] <= '9') {
-
 
18
			num |= hex[i] - '0';
-
 
19
		} else if(hex[i] >= 'a' && hex[i] <= 'f') {
-
 
20
			num |= hex[i] - 'a' + 10;
-
 
21
		} else if(hex[i] >= 'A' && hex[i] <= 'F') {
-
 
22
			num |= hex[i] - 'A' + 10;
-
 
23
		}
-
 
24
	}
-
 
25
	return num;
-
 
26
}
-
 
27
 
-
 
28
char* generate_ident(const char* username, int* r, int* g, int* b) {
-
 
29
	char* ident = malloc(25);
-
 
30
	char* hash = rv_md5(username);
-
 
31
 
-
 
32
	double h = hex_to_num(hash + 32 - 2 - 2 - 3, 3);
-
 
33
	double s = hex_to_num(hash + 32 - 2 - 2, 2);
-
 
34
	double v = hex_to_num(hash + 32 - 2, 2);
-
 
35
 
-
 
36
	h = h * 360 / 4095;
-
 
37
	s = 65 - s * 20 / 255;
-
 
38
	v = 75 - v * 20 / 255;
-
 
39
 
-
 
40
	double max;
-
 
41
	double min;
-
 
42
 
-
 
43
	if(v < 50) {
-
 
44
		max = 2.55 * (v + v * (s / 100));
-
 
45
		min = 2.55 * (v - v * (s / 100));
-
 
46
	} else if(v >= 50) {
-
 
47
		max = 2.55 * (v + (100 - v) * (s / 100));
-
 
48
		min = 2.55 * (v - (100 - v) * (s / 100));
-
 
49
	}
-
 
50
 
-
 
51
	if(0 <= h && h < 60) {
-
 
52
		*r = max;
-
 
53
		*g = (h / 60) * (max - min) + min;
-
 
54
		*b = min;
-
 
55
	} else if(60 <= h && h < 120) {
-
 
56
		*r = ((120 - h) / 60) * (max - min) + min;
-
 
57
		*g = max;
-
 
58
		*b = min;
-
 
59
	} else if(120 <= h && h < 128) {
-
 
60
		*r = min;
-
 
61
		*g = max;
-
 
62
		*b = ((h - 120) / 60) * (max - min) + min;
-
 
63
	} else if(180 <= h && h < 240) {
-
 
64
		*r = min;
-
 
65
		*g = ((240 - h) / 60) * (max - min) + min;
-
 
66
		*b = max;
-
 
67
	} else if(240 <= h && h < 300) {
-
 
68
		*r = ((h - 240) / 60) * (max - min) + min;
-
 
69
		*g = min;
-
 
70
		*b = max;
-
 
71
	} else if(300 <= h && h < 360) {
-
 
72
		*r = max;
-
 
73
		*g = min;
-
 
74
		*b = ((360 - h) / 60) * (max - min) + min;
-
 
75
	}
-
 
76
 
-
 
77
	int y, x;
-
 
78
	for(x = 0; x < 3; x++) {
-
 
79
		for(y = 0; y < 5; y++) {
-
 
80
			int i;
-
 
81
			char c = hash[y + x * 5];
-
 
82
			int px = 0;
-
 
83
			if(c >= '0' && c <= '9') {
-
 
84
				px = c - '0';
-
 
85
			} else if(c >= 'a' && c <= 'f') {
-
 
86
				px = c - 'a' + 10;
-
 
87
			}
-
 
88
			if((px % 2) == 0) {
-
 
89
				px = 1;
-
 
90
			} else {
-
 
91
				px = 0;
-
 
92
			}
-
 
93
			for(i = 0; i < 2; i++) {
-
 
94
				int incr = -1;
-
 
95
				if(i == 1) incr = 1;
-
 
96
				ident[y * 5 + x * incr + 2] = px;
-
 
97
			}
-
 
98
		}
-
 
99
	}
-
 
100
 
-
 
101
	free(hash);
-
 
102
	return ident;
-
 
103
}
-
 
104
 
10
void rv_avatar_generate(const char* name) {
105
void rv_avatar_generate(const char* name, const char* username) {
11
	FILE* f = fopen(name, "wb");
106
	FILE* f = fopen(name, "wb");
12
 
107
 
-
 
108
	int pxr;
-
 
109
	int pxg;
-
 
110
	int pxb;
-
 
111
 
-
 
112
	char* ident = generate_ident(username, &pxr, &pxg, &pxb);
-
 
113
 
13
	if(f == NULL) return;
114
	if(f == NULL) return;
14
 
115
 
15
	png_structp pngp = NULL;
116
	png_structp pngp = NULL;
16
	png_infop infop = NULL;
117
	png_infop infop = NULL;
17
	png_bytep row = NULL;
118
	png_bytep row = NULL;
Line 21... Line 122...
21
 
122
 
22
	if(setjmp(png_jmpbuf(pngp))) {
123
	if(setjmp(png_jmpbuf(pngp))) {
23
		goto closeall;
124
		goto closeall;
24
	}
125
	}
25
 
126
 
-
 
127
	png_init_io(pngp, f);
-
 
128
 
-
 
129
	png_set_IHDR(pngp, infop, 255, 255, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
 
130
 
-
 
131
	png_text title;
-
 
132
	title.compression = PNG_TEXT_COMPRESSION_NONE;
-
 
133
	title.key = "Title";
-
 
134
	title.text = "Generated by RepoView";
-
 
135
	png_set_text(pngp, infop, &title, 1);
-
 
136
 
-
 
137
	png_write_info(pngp, infop);
-
 
138
 
-
 
139
	row = (png_bytep)malloc(3 * 255 * sizeof(png_byte));
-
 
140
	int x, y;
-
 
141
	for(y = 0; y < 255; y++) {
-
 
142
		for(x = 0; x < 255; x++) {
-
 
143
			int px = x / 51;
-
 
144
			int py = y / 51;
-
 
145
			int colr = 0;
-
 
146
			int colg = 0;
-
 
147
			int colb = 0;
-
 
148
			if(ident[px + py * 5]) {
-
 
149
				colr = pxr;
-
 
150
				colg = pxg;
-
 
151
				colb = pxb;
-
 
152
			} else {
-
 
153
				colr = colg = colb = 240;
-
 
154
			}
-
 
155
			row[x * 3 + 0] = colr;
-
 
156
			row[x * 3 + 1] = colg;
-
 
157
			row[x * 3 + 2] = colb;
-
 
158
		}
-
 
159
		png_write_row(pngp, row);
-
 
160
	}
-
 
161
 
-
 
162
	png_write_end(pngp, NULL);
-
 
163
 
26
closeall:
164
closeall:
27
	fclose(f);
165
	fclose(f);
28
	if(infop != NULL) png_free_data(pngp, infop, PNG_FREE_ALL, -1);
166
	if(infop != NULL) png_free_data(pngp, infop, PNG_FREE_ALL, -1);
29
	if(pngp != NULL) png_destroy_write_struct(&pngp, (png_infopp)NULL);
167
	if(pngp != NULL) png_destroy_write_struct(&pngp, (png_infopp)NULL);
30
	if(row != NULL) free(row);
168
	if(row != NULL) free(row);
-
 
169
	free(ident);
31
}
170
}