1/* Part of SWISH 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@cs.vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (C): 2016, VU University Amsterdam 7 CWI Amsterdam 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(noble_avatar, 37 [ noble_avatar/2, % ?Gender, -File 38 noble_avatar/3, % ?Gender, -File, ?New 39 create_avatar/2, % +PNG, -File 40 41 existing_noble_avatar/2 % -Gender, -File 42 ]). 43:- use_module(library(apply)). 44:- use_module(library(lists)). 45:- use_module(library(random)). 46:- use_module(library(filesex)). 47:- use_module(library(process)).
76:- multifile 77 user:file_search_path/2. 78 79user:file_search_path(noble, icons(noble)). 80user:file_search_path(noble_avatar_components, noble(components)). 81user:file_search_path(noble_avatar, data(avatars)). 82 83:- dynamic 84 noble_dir/1, % Directory 85 noble/4. % Part, Gender, I, File
99noble_avatar(Gender, Image) :- 100 noble_avatar(Gender, Image, _). 101 102noble_avatar(Gender, Image, New) :- 103 var(New), !, 104 noble_index_components, 105 avatar_components(Gender, IDs, Components), 106 maplist(plus(0'a), IDs, Codes), 107 atom_codes(Base, Codes), 108 file_name_extension(Base, png, PNG), 109 with_mutex(noble_avatar, 110 create_avatar_sync(Components, 111 noble_avatar, PNG, Image, New)). 112noble_avatar(Gender, Image, true) :- !, 113 repeat, 114 noble_avatar(Gender, Image, New), 115 New == true, !.
121create_avatar(PNG, Image) :-
122 file_name_extension(Base, png, PNG),
123 atom_codes(Base, Codes),
124 maplist(plus(0'a), IDs, Codes),
125 noble_index_components,
126 avatar_components(_Gender, IDs, Components),
127 with_mutex(noble_avatar,
128 create_avatar_sync(Components,
129 noble_avatar, PNG, Image, _New)).
136existing_noble_avatar(Gender, Image) :- 137 absolute_file_name(noble_avatar(.), Dir, 138 [ file_type(directory), 139 solutions(all) 140 ]), 141 directory_files(Dir, Files), 142 member(Image, Files), 143 file_name_extension(Base, png, Image), 144 sub_atom(Base, 0, 1, _, First), 145 char_code(First, Code), 146 Index is Code-0'a, 147 gender_id(Gender, Index). 148 149 150create_avatar_sync(Components, DirAlias, File, Image, New) :- 151 Location =.. [DirAlias,File], 152 ( absolute_file_name(Location, Image, 153 [ access(read), 154 file_errors(fail) 155 ]) 156 -> New = false 157 ; absolute_file_name(Location, Image, 158 [ access(write), file_errors(fail) ]) 159 -> composite(Components, Image), 160 New = true 161 ; Dir =.. [DirAlias,.], 162 absolute_file_name(Dir, DirPath, [solutions(all)]), 163 file_directory_name(DirPath, Parent), 164 exists_directory(Parent), 165 \+ exists_directory(DirPath) 166 -> make_directory(DirPath), 167 absolute_file_name(Location, Image, [access(write)]), 168 composite(Components, Image) 169 ). 170 171composite(Components, Image) :- 172 noble_dir(Dir), 173 phrase(composite(Components, Dir), Argv, [file(Image)]), 174 process_create(path(convert), Argv, []). 175 176composite([], _) --> 177 [ '-background', 'none', '-flatten' ]. 178composite([File|T], Dir) --> 179 { directory_file_path(Dir, File, AbsFile) 180 }, 181 [ '-page', '+0+0', file(AbsFile) ], 182 composite(T, Dir). 183 184avatar_components(Gender, [GID|IDs], Files) :- 185 gender_id(Gender, GID), 186 parts(Parts), 187 files(Parts, Gender, IDs, Files). 188 189files([], _, [], []). 190files([P:H-Gender|T], Gender, [I|IDs], [File|Files]) :- 191 ( var(I), I \== 0 192 -> maybe(P) 193 ; true 194 ), 195 file(H, Gender, I, File), !, 196 files(T, Gender, IDs, Files). 197files([_|T], Gender, [0|IDs], Files) :- 198 files(T, Gender, IDs, Files). 199 200file(Part, Gender, I, File) :- 201 findall(I, noble(Part, Gender, I, _), IL), 202 random_member(I, IL), 203 noble(Part, Gender, I, File). 204 205gender_id(Var, ID) :- 206 var(Var), var(ID), 207 ID is 1+random(2), 208 gender_id(Var, ID), !. 209gender_id(male, 1). 210gender_id(female, 2).
Probability:Part-Gender
Part is included with Probability and only of Gender matches the target Gender.
223parts([ 0.5:pattern - _,
224 1.0:head - _,
225 1.0:mouth - _,
226 1.0:eye - _,
227 0.5:eyepatch - _,
228 0.3:glasses - _,
229 0.3:mustache - male,
230 0.5:beard - male,
231 0.8:hair - _,
232 0.2:accessory - _,
233 0.5:necklace - _,
234 0.3:boa - _,
235 0.2:scar - _,
236 0.1:sideburn - _
237 ]).
noble_avatar_components(.)
.244noble_index_components :- 245 noble_dir(_), !. 246noble_index_components :- 247 with_mutex(noble_avatar, noble_index_components_sync). 248 249noble_index_components_sync :- 250 noble_dir(_), !. 251noble_index_components_sync :- 252 retractall(noble_dir(_)), 253 retractall(noble(_,_,_,_)), 254 absolute_file_name(noble_avatar_components(.), Dir, 255 [ file_type(directory) 256 ]), 257 directory_files(Dir, Files), 258 maplist(noble_file, Files), 259 assertz(noble_dir(Dir)). 260 261noble_file(File) :- 262 file_name_extension(Base, png, File), 263 atomic_list_concat([avatar,Part,V], '_', Base), 264 ( atom_concat(f, NA, V), 265 atom_number(NA, N) 266 -> Gender = female 267 ; atom_concat(m, NA, V), 268 atom_number(NA, N) 269 -> Gender = male 270 ; atom_number(V, N) 271 ), !, 272 assert(noble(Part, Gender, N, File)). 273noble_file(_)
Noble Avatar generator
This library generates random avatar images from components. The file locations of the library are defined by file_search_path/2 rules for
noble_avatar_components
(the components) andnoble_avatar
for the generated avatars.The probalities for the various components are specified in part/1.
Credits and license
The component images can be downloaded from the address below. The images are licensed under CC-BY-3.0. If you use this library with these images, please include the following acknowledgements: