That fuck shit the fascists are using
1/**
2 * Source: https://github.com/woltapp/blurhash
3 *
4 * Copyright (c) 2018 Wolt Enterprises
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 * associated documentation files (the "Software"), to deal in the Software without restriction,
8 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
9 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all copies or
13 * substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
16 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21package org.tm.archive.blurhash;
22
23import android.graphics.Bitmap;
24import android.graphics.Color;
25
26import androidx.annotation.Nullable;
27
28import static org.tm.archive.blurhash.BlurHashUtil.linearTosRGB;
29import static org.tm.archive.blurhash.BlurHashUtil.sRGBToLinear;
30import static org.tm.archive.blurhash.BlurHashUtil.signPow;
31
32class BlurHashDecoder {
33
34 static @Nullable Bitmap decode(@Nullable String blurHash, int width, int height) {
35 return decode(blurHash, width, height, 1f);
36 }
37
38 static @Nullable Bitmap decode(@Nullable String blurHash, int width, int height, double punch) {
39
40 if (blurHash == null || blurHash.length() < 6) {
41 return null;
42 }
43
44 int numCompEnc = Base83.decode(blurHash, 0, 1);
45 int numCompX = (numCompEnc % 9) + 1;
46 int numCompY = (numCompEnc / 9) + 1;
47
48 if (blurHash.length() != 4 + 2 * numCompX * numCompY) {
49 return null;
50 }
51
52 int maxAcEnc = Base83.decode(blurHash, 1, 2);
53 double maxAc = (maxAcEnc + 1) / 166f;
54 double[][] colors = new double[numCompX * numCompY][];
55 for (int i = 0; i < colors.length; i++) {
56 if (i == 0) {
57 int colorEnc = Base83.decode(blurHash, 2, 6);
58 colors[i] = decodeDc(colorEnc);
59 } else {
60 int from = 4 + i * 2;
61 int colorEnc = Base83.decode(blurHash, from, from + 2);
62 colors[i] = decodeAc(colorEnc, maxAc * punch);
63 }
64 }
65
66 return composeBitmap(width, height, numCompX, numCompY, colors);
67 }
68
69 private static double[] decodeDc(int colorEnc) {
70 int r = colorEnc >> 16;
71 int g = (colorEnc >> 8) & 255;
72 int b = colorEnc & 255;
73 return new double[] {sRGBToLinear(r),
74 sRGBToLinear(g),
75 sRGBToLinear(b)};
76 }
77
78 private static double[] decodeAc(int value, double maxAc) {
79 int r = value / (19 * 19);
80 int g = (value / 19) % 19;
81 int b = value % 19;
82 return new double[]{
83 signPow((r - 9) / 9.0f, 2f) * maxAc,
84 signPow((g - 9) / 9.0f, 2f) * maxAc,
85 signPow((b - 9) / 9.0f, 2f) * maxAc
86 };
87 }
88
89 private static Bitmap composeBitmap(int width, int height, int numCompX, int numCompY, double[][] colors) {
90 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
91 for (int y = 0; y < height; y++) {
92 for (int x = 0; x < width; x++) {
93
94 double r = 0f;
95 double g = 0f;
96 double b = 0f;
97
98 for (int j = 0; j < numCompY; j++) {
99 for (int i = 0; i < numCompX; i++) {
100 double basis = (Math.cos(Math.PI * x * i / width) * Math.cos(Math.PI * y * j / height));
101 double[] color = colors[j * numCompX + i];
102 r += color[0] * basis;
103 g += color[1] * basis;
104 b += color[2] * basis;
105 }
106 }
107 bitmap.setPixel(x, y, Color.rgb((int) linearTosRGB(r), (int) linearTosRGB(g), (int) linearTosRGB(b)));
108 }
109 }
110
111 return bitmap;
112 }
113}