bsw@211: local alphabet = { bsw@211: "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", bsw@211: "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", bsw@211: "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", bsw@211: "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", bsw@211: "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/" bsw@211: } bsw@211: bsw@211: local function encode_base64(str) bsw@211: local parts = {} bsw@211: local pos = 1 bsw@211: local block_count = 0 bsw@211: while pos <= #str do bsw@211: local s = string.sub(str, pos, pos + 2) bsw@211: local n = 0 bsw@211: for i = 1, 3 do bsw@211: n = n * 256 bsw@211: if i <= #s then bsw@211: n = n + string.byte(string.sub(s, i, i)) bsw@211: end bsw@211: end bsw@211: parts[#parts+1] = alphabet[math.floor(n / 262144) + 1] bsw@211: parts[#parts+1] = alphabet[math.floor(n / 4096) % 64 + 1] bsw@211: if #s > 1 then bsw@211: parts[#parts+1] = alphabet[math.floor(n / 64) % 64 + 1] bsw@211: else bsw@211: parts[#parts+1] = "=" bsw@211: end bsw@211: if #s > 2 then bsw@211: parts[#parts+1] = alphabet[n % 64 + 1] bsw@211: else bsw@211: parts[#parts+1] = "=" bsw@211: end bsw@211: block_count = block_count + 1 bsw@211: if block_count == 19 then bsw@211: --parts[#parts+1] = "\r\n" bsw@211: block_count = 0 bsw@211: end bsw@211: pos = pos + #s bsw@211: end bsw@211: if block_count > 0 then bsw@211: --parts[#parts+1] = "\r\n" bsw@211: end bsw@211: return table.concat(parts) bsw@211: end bsw@211: bsw@211: function ui.avatar(member, size) bsw@211: local base64_string bsw@211: bsw@211: if member.avatar_base64 then bsw@211: base64_string = member.avatar_base64 bsw@211: else bsw@211: local member_image = MemberImage:by_pk(member.id, "avatar", true) bsw@211: if member_image then bsw@211: base64_string = encode_base64(member_image.data) bsw@211: else bsw@211: base64_string = "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAAwADABAREA/8QAGQABAAMBAQAAAAAAAAAAAAAAAAMGBwQC/8QAIxAAAgICAgEEAwAAAAAAAAAAAQIAAwQRBTEGEiEyYTVRcf/aAAgBAQAAPwDf4kN2TRjjd1ip/TFOTRkDdNiv/DJoiR3WCml7D0o3M55DOtzsp7HYkb9h+hHH51uDlJYjEDfuP2Jo1NgupSwdMNySJzcgC3H3gd+gzNCNMR9wBtgPuaXx4K8fQD36BOmJ5ZQ6FT0RozNeQrWrPuRegx1HH1rbn0o3RYbmlKoRAo6A0J6kGXlV4eM99vxXuVrK8uJBXHp19tKxZY1trWN8mOzFdjVWrYvyU7Es+L5cQAuRTv7WWXEyq8zGS+r4t1ODyP8AC3SgRES/+OfhaZ//2Q==" bsw@211: end bsw@211: member.avatar_base64 = base64_string bsw@211: member:save() bsw@211: end bsw@211: bsw@216: ui.tag{ tag = "img", attr = { class = "avatar_image", src = "data:image/jpeg;base64," .. base64_string } } bsw@211: bsw@211: end bsw@211: