diff --git a/src/main/scala/gitbucket/core/controller/AccountController.scala b/src/main/scala/gitbucket/core/controller/AccountController.scala index 714ae96..6af8ab6 100644 --- a/src/main/scala/gitbucket/core/controller/AccountController.scala +++ b/src/main/scala/gitbucket/core/controller/AccountController.scala @@ -21,13 +21,13 @@ class AccountController extends AccountControllerBase with AccountService with RepositoryService with ActivityService with WikiService with LabelsService with SshKeyService with OneselfAuthenticator with UsersAuthenticator with GroupManagerAuthenticator with ReadableUsersAuthenticator - with AccessTokenService with WebHookService with RepositoryCreationService + with AccessTokenService with WebHookService with RepositoryCreationService with TextAvatarService trait AccountControllerBase extends AccountManagementControllerBase { self: AccountService with RepositoryService with ActivityService with WikiService with LabelsService with SshKeyService with OneselfAuthenticator with UsersAuthenticator with GroupManagerAuthenticator with ReadableUsersAuthenticator - with AccessTokenService with WebHookService with RepositoryCreationService => + with AccessTokenService with WebHookService with RepositoryCreationService with TextAvatarService => case class AccountNewForm(userName: String, password: String, fullName: String, mailAddress: String, description: Option[String], url: Option[String], fileId: Option[String]) @@ -150,17 +150,17 @@ get("/:userName/_avatar"){ val userName = params("userName") - (for { - account <- getAccountByUserName(userName) - image <- account.image - } yield (account, image)) match { - case Some((account, image)) => + getAccountByUserName(userName).map{ account => + account.image.map{ image => response.setDateHeader("Last-Modified", account.updatedDate.getTime) RawData(FileUtil.getMimeType(image), new java.io.File(getUserUploadDir(userName), image)) - case None => + }.getOrElse{ contentType = "image/png" - response.setDateHeader("Last-Modified", (new Date(0)).getTime) - Thread.currentThread.getContextClassLoader.getResourceAsStream("noimage.png") + response.setDateHeader("Last-Modified", new Date(0).getTime()) + textAvatar(account.fullName) + } + }.getOrElse{ + NotFound() } } diff --git a/src/main/scala/gitbucket/core/service/TextAvatarService.scala b/src/main/scala/gitbucket/core/service/TextAvatarService.scala new file mode 100644 index 0000000..58d5870 --- /dev/null +++ b/src/main/scala/gitbucket/core/service/TextAvatarService.scala @@ -0,0 +1,49 @@ +package gitbucket.core.service + +import java.io.ByteArrayOutputStream +import java.awt.image.BufferedImage +import javax.imageio.ImageIO +import java.awt.{Color, Font, RenderingHints} +import java.awt.font.{FontRenderContext, TextLayout} +import gitbucket.core.util.StringUtil + +trait TextAvatarService { + def textAvatar(nameText: String): Array[Byte] = { + val drawText = nameText.substring(0, 1) + val md5 = StringUtil.md5(nameText) + val hashedInt = Integer.parseInt(md5.substring(0, 2), 16) + + val h = hashedInt / 256f + val bgColor = Color.getHSBColor(h, 1f, 1f) + val fgColor = Color.getHSBColor(h + 0.5f, 1f, 0.8f) + + val size = (200, 200) + val canvas = new BufferedImage(size._1, size._2, BufferedImage.TYPE_INT_ARGB) + val g = canvas.createGraphics() + + g.setColor(new Color(0, 0, 0, 0)) + g.fillRect(0, 0, canvas.getWidth, canvas.getHeight) + g.setColor(bgColor) + g.fillRoundRect(0, 0, canvas.getWidth, canvas.getHeight, 60, 60) + + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON) + + g.setColor(fgColor) + val font = new Font("SansSerif", Font.PLAIN, 180) + val context = g.getFontRenderContext + val txt = new TextLayout(drawText, font, context) + val bounds = txt.getBounds + + val x: Int = ((size._1 - bounds.getWidth) / 2 - bounds.getX).toInt + val y: Int = ((size._2 - bounds.getHeight) / 2 - bounds.getY).toInt + + g.setFont(font) + g.drawString(drawText, x, y) + + g.dispose() + + val stream = new ByteArrayOutputStream + ImageIO.write(canvas, "png", stream) + stream.toByteArray + } +}