use same algo for avatar placeholder

This commit is contained in:
tobiaskaminsky 2017-10-13 08:23:30 +02:00 committed by AndyScherzinger
parent 620f9db9b5
commit c7ee4f1a60
No known key found for this signature in database
GPG key ID: 6CADC7E3523C308B
2 changed files with 98 additions and 16 deletions

View file

@ -113,10 +113,10 @@ public class TextDrawable extends Drawable {
@NonNull
public static TextDrawable createNamedAvatar(String name, float radiusInDp) throws
UnsupportedEncodingException, NoSuchAlgorithmException {
int[] rgb = BitmapUtils.calculateRGB(name);
TextDrawable avatar = new TextDrawable(
name.substring(0, 1).toUpperCase(), rgb[0], rgb[1], rgb[2], radiusInDp);
return avatar;
int[] hsl = BitmapUtils.calculateHSL(name);
int[] rgb = BitmapUtils.HSLtoRGB(hsl[0], hsl[1], hsl[2], 1);
return new TextDrawable(name.substring(0, 1).toUpperCase(), rgb[0], rgb[1], rgb[2], radiusInDp);
}
/**

View file

@ -29,16 +29,17 @@ import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
import com.owncloud.android.lib.common.utils.Log_OC;
import org.apache.commons.codec.binary.Hex;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Locale;
/**
* Utility class with methods for decoding Bitmaps.
*/
public class BitmapUtils {
public static final String TAG = BitmapUtils.class.getSimpleName();
/**
@ -188,7 +189,7 @@ public class BitmapUtils {
*
* @param h Hue is specified as degrees in the range 0 - 360.
* @param s Saturation is specified as a percentage in the range 1 - 100.
* @param l Lumanance is specified as a percentage in the range 1 - 100.
* @param l Luminance is specified as a percentage in the range 1 - 100.
* @param alpha the alpha value between 0 - 1
* adapted from https://svn.codehaus.org/griffon/builders/gfxbuilder/tags/GFXBUILDER_0.2/
* gfxbuilder-core/src/main/com/camick/awt/HSLColor.java
@ -267,17 +268,98 @@ public class BitmapUtils {
* @throws UnsupportedEncodingException if the charset is not supported
* @throws NoSuchAlgorithmException if the specified algorithm is not available
*/
public static int[] calculateRGB(String name) throws UnsupportedEncodingException, NoSuchAlgorithmException {
// using adapted algorithm from /core/js/placeholder.js:50
byte[] seed = name.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
Integer seedMd5Int = String.format(Locale.ROOT, "%032x",
new BigInteger(1, md.digest(seed))).hashCode();
public static int[] calculateHSL(String name) throws UnsupportedEncodingException, NoSuchAlgorithmException {
// using adapted algorithm from https://github.com/nextcloud/server/blob/master/core/js/placeholder.js#L126
double maxRange = Integer.MAX_VALUE;
float hue = (float) (seedMd5Int / maxRange * 360);
String[] result = new String[]{"0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"};
double[] rgb = new double[]{0, 0, 0};
int sat = 70;
int lum = 68;
int modulo = 16;
return BitmapUtils.HSLtoRGB(hue, 90.0f, 65.0f, 1.0f);
String hash = name.toLowerCase().replaceAll("[^0-9a-f]", "");
if (!hash.matches("^[0-9a-f]{32}")) {
hash = md5(hash);
}
// Splitting evenly the string
for (int i = 0; i < hash.length(); i++) {
result[i % modulo] = result[i % modulo] + String.valueOf(Integer.parseInt(hash.substring(i, i + 1), 16));
}
// Converting our data into a usable rgb format
// Start at 1 because 16%3=1 but 15%3=0 and makes the repartition even
for (int count = 1; count < modulo; count++) {
rgb[count % 3] += (Integer.parseInt(result[count]));
}
// Reduce values bigger than rgb requirements
rgb[0] = rgb[0] % 255;
rgb[1] = rgb[1] % 255;
rgb[2] = rgb[2] % 255;
double[] hsl = rgbToHsl(rgb[0], rgb[1], rgb[2]);
// Classic formula to check the brightness for our eye
// If too bright, lower the sat
double bright = Math.sqrt(0.299 * Math.pow(rgb[0], 2) + 0.587 * Math.pow(rgb[1], 2) + 0.114
* Math.pow(rgb[2], 2));
if (bright >= 200) {
sat = 60;
}
return new int[]{(int) (hsl[0] * 360), sat, lum};
}
private static double[] rgbToHsl(double r, double g, double b) {
r /= 255;
g /= 255;
b /= 255;
double max = Math.max(r, Math.max(g, b));
double min = Math.min(r, Math.min(g, b));
double h = (max + min) / 2;
double s;
double l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
double d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
if (max == r) {
h = (g - b) / d + (g < b ? 6 : 0);
} else if (max == g) {
h = (b - r) / d + 2;
} else if (max == b) {
h = (r - g) / d + 4;
}
h /= 6;
}
double[] hsl = new double[]{0.0, 0.0, 0.0};
hsl[0] = h;
hsl[1] = s;
hsl[2] = l;
return hsl;
}
public static String md5(String string) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(string.getBytes());
return new String(Hex.encodeHex(md5.digest()));
} catch (Exception e) {
Log_OC.e(TAG, e.getMessage());
}
return "";
}
/**