blurhash_decoder 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68941f08272cb7b00dab2261afc755cd8833f67e3407f75d1eca45a4c765938b
4
- data.tar.gz: 7d641afcd4a5ee0366112268f3c7a4d3d8a078c90f478118116a0dc1f9360595
3
+ metadata.gz: b0221d3511057d149926cc067e2a8e2eb51ff0c724476666e618df955160626e
4
+ data.tar.gz: a271106fec9b1e3872b0ab1a8ec7753e8b4e68a055887ba0dee57e9bd3964d1e
5
5
  SHA512:
6
- metadata.gz: b8476b070ae0f36d0f7369998fe8cd672ec92a80f5347c48cf03db2073c12ddad3f6a2f1d5e4df328bb6c79b942a1d604c5f6a68e37bf070973d649680f4be66
7
- data.tar.gz: '0813bb02a43ca11415eb9bc087446a5f6bc8a4b5be13d29cb03c6cd248ddd042e322132210dc29f000cce1dd809091af733c3074c32ac2bdf58c9a28a8afead5'
6
+ metadata.gz: dbbb92c47bcb19a4445e58c1a22ec038642fce18d01209a9b528b70707c42905385164aaf48b9b0b9f2165f7d7a1118ccef7533b2e58e56e37ca862fba8d98a2
7
+ data.tar.gz: 125ef0207f696e1bf40055e8ffdbd14419b47ce83e0e7efb9bc7dfb79dbe55b685efa04c4d894a55d17a4cd00c010b7e437b2187167a4d6234df454c4c58ea12
@@ -3,7 +3,7 @@
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'blurhash_decoder'
6
- s.version = '0.0.10'
6
+ s.version = '0.0.11'
7
7
  s.summary = "A blurhash decoder gem!"
8
8
  s.description = "A simple blurhash decoder gem using c."
9
9
  s.authors = ["Rabin Poudyal"]
@@ -0,0 +1,52 @@
1
+ #include "encode.h"
2
+
3
+ #define STB_IMAGE_IMPLEMENTATION
4
+ #include "stb_image.h"
5
+
6
+ #include <stdio.h>
7
+ #include <ruby.h>
8
+ #include<string.h>
9
+
10
+
11
+ VALUE ENCODER = Qnil; /* Ruby Module */
12
+
13
+ const char *blurHashForFile(int xComponents, int yComponents,const char *filename);
14
+
15
+ VALUE method_encode(VALUE self, VALUE x, VALUE y) {
16
+ int xComponents = NUM2INT(x);
17
+ int yComponents = NUM2INT(y);
18
+
19
+ const char * input_file = "tmp/in.png";
20
+
21
+ if(xComponents < 1 || xComponents > 8 || yComponents < 1 || yComponents > 8) {
22
+ fprintf(stderr, "Component counts must be between 1 and 8.\n");
23
+ return 1;
24
+ }
25
+
26
+ const char *hash = blurHashForFile(xComponents, yComponents, input_file);
27
+ if(!hash) {
28
+ fprintf(stderr, "Failed to load image file \"%s\".\n", input_file);
29
+ return 1;
30
+ }
31
+
32
+ return rb_str_new(hash, strlen(hash));
33
+ }
34
+
35
+ const char *blurHashForFile(int xComponents, int yComponents,const char *filename) {
36
+ int width, height, channels;
37
+ unsigned char *data = stbi_load(filename, &width, &height, &channels, 3);
38
+ if(!data) return NULL;
39
+
40
+ const char *hash = blurHashForPixels(xComponents, yComponents, width, height, data, width * 3);
41
+
42
+ stbi_image_free(data);
43
+
44
+ return hash;
45
+ }
46
+
47
+ void
48
+ Init_blurhash_encoder(void) {
49
+ ENCODER = rb_define_module("ENCODER");
50
+ rb_define_method(ENCODER, "encode", method_encode, 2);
51
+ }
52
+
@@ -0,0 +1,26 @@
1
+ #ifndef __BLURHASH_COMMON_H__
2
+ #define __BLURHASH_COMMON_H__
3
+
4
+ #include<math.h>
5
+
6
+ #ifndef M_PI
7
+ #define M_PI 3.14159265358979323846
8
+ #endif
9
+
10
+ static inline int linearTosRGB(float value) {
11
+ float v = fmaxf(0, fminf(1, value));
12
+ if(v <= 0.0031308) return v * 12.92 * 255 + 0.5;
13
+ else return (1.055 * powf(v, 1 / 2.4) - 0.055) * 255 + 0.5;
14
+ }
15
+
16
+ static inline float sRGBToLinear(int value) {
17
+ float v = (float)value / 255;
18
+ if(v <= 0.04045) return v / 12.92;
19
+ else return powf((v + 0.055) / 1.055, 2.4);
20
+ }
21
+
22
+ static inline float signPow(float value, float exp) {
23
+ return copysignf(powf(fabsf(value), exp), value);
24
+ }
25
+
26
+ #endif
@@ -0,0 +1,116 @@
1
+ #include "encode.h"
2
+ #include "common.h"
3
+
4
+ #include <string.h>
5
+
6
+ static float *multiplyBasisFunction(int xComponent, int yComponent, int width, int height, uint8_t *rgb, size_t bytesPerRow);
7
+ static char *encode_int(int value, int length, char *destination);
8
+
9
+ static int encodeDC(float r, float g, float b);
10
+ static int encodeAC(float r, float g, float b, float maximumValue);
11
+
12
+ const char *blurHashForPixels(int xComponents, int yComponents, int width, int height, uint8_t *rgb, size_t bytesPerRow) {
13
+ static char buffer[2 + 4 + (9 * 9 - 1) * 2 + 1];
14
+
15
+ if(xComponents < 1 || xComponents > 9) return NULL;
16
+ if(yComponents < 1 || yComponents > 9) return NULL;
17
+
18
+ float factors[yComponents][xComponents][3];
19
+ memset(factors, 0, sizeof(factors));
20
+
21
+ for(int y = 0; y < yComponents; y++) {
22
+ for(int x = 0; x < xComponents; x++) {
23
+ float *factor = multiplyBasisFunction(x, y, width, height, rgb, bytesPerRow);
24
+ factors[y][x][0] = factor[0];
25
+ factors[y][x][1] = factor[1];
26
+ factors[y][x][2] = factor[2];
27
+ }
28
+ }
29
+
30
+ float *dc = factors[0][0];
31
+ float *ac = dc + 3;
32
+ int acCount = xComponents * yComponents - 1;
33
+ char *ptr = buffer;
34
+
35
+ int sizeFlag = (xComponents - 1) + (yComponents - 1) * 9;
36
+ ptr = encode_int(sizeFlag, 1, ptr);
37
+
38
+ float maximumValue;
39
+ if(acCount > 0) {
40
+ float actualMaximumValue = 0;
41
+ for(int i = 0; i < acCount * 3; i++) {
42
+ actualMaximumValue = fmaxf(fabsf(ac[i]), actualMaximumValue);
43
+ }
44
+
45
+ int quantisedMaximumValue = fmaxf(0, fminf(82, floorf(actualMaximumValue * 166 - 0.5)));
46
+ maximumValue = ((float)quantisedMaximumValue + 1) / 166;
47
+ ptr = encode_int(quantisedMaximumValue, 1, ptr);
48
+ } else {
49
+ maximumValue = 1;
50
+ ptr = encode_int(0, 1, ptr);
51
+ }
52
+
53
+ ptr = encode_int(encodeDC(dc[0], dc[1], dc[2]), 4, ptr);
54
+
55
+ for(int i = 0; i < acCount; i++) {
56
+ ptr = encode_int(encodeAC(ac[i * 3 + 0], ac[i * 3 + 1], ac[i * 3 + 2], maximumValue), 2, ptr);
57
+ }
58
+
59
+ *ptr = 0;
60
+
61
+ return buffer;
62
+ }
63
+
64
+ static float *multiplyBasisFunction(int xComponent, int yComponent, int width, int height, uint8_t *rgb, size_t bytesPerRow) {
65
+ float r = 0, g = 0, b = 0;
66
+ float normalisation = (xComponent == 0 && yComponent == 0) ? 1 : 2;
67
+
68
+ for(int y = 0; y < height; y++) {
69
+ for(int x = 0; x < width; x++) {
70
+ float basis = cosf(M_PI * xComponent * x / width) * cosf(M_PI * yComponent * y / height);
71
+ r += basis * sRGBToLinear(rgb[3 * x + 0 + y * bytesPerRow]);
72
+ g += basis * sRGBToLinear(rgb[3 * x + 1 + y * bytesPerRow]);
73
+ b += basis * sRGBToLinear(rgb[3 * x + 2 + y * bytesPerRow]);
74
+ }
75
+ }
76
+
77
+ float scale = normalisation / (width * height);
78
+
79
+ static float result[3];
80
+ result[0] = r * scale;
81
+ result[1] = g * scale;
82
+ result[2] = b * scale;
83
+
84
+ return result;
85
+ }
86
+
87
+
88
+
89
+ static int encodeDC(float r, float g, float b) {
90
+ int roundedR = linearTosRGB(r);
91
+ int roundedG = linearTosRGB(g);
92
+ int roundedB = linearTosRGB(b);
93
+ return (roundedR << 16) + (roundedG << 8) + roundedB;
94
+ }
95
+
96
+ static int encodeAC(float r, float g, float b, float maximumValue) {
97
+ int quantR = fmaxf(0, fminf(18, floorf(signPow(r / maximumValue, 0.5) * 9 + 9.5)));
98
+ int quantG = fmaxf(0, fminf(18, floorf(signPow(g / maximumValue, 0.5) * 9 + 9.5)));
99
+ int quantB = fmaxf(0, fminf(18, floorf(signPow(b / maximumValue, 0.5) * 9 + 9.5)));
100
+
101
+ return quantR * 19 * 19 + quantG * 19 + quantB;
102
+ }
103
+
104
+ static char characters[83]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~";
105
+
106
+ static char *encode_int(int value, int length, char *destination) {
107
+ int divisor = 1;
108
+ for(int i = 0; i < length - 1; i++) divisor *= 83;
109
+
110
+ for(int i = 0; i < length; i++) {
111
+ int digit = (value / divisor) % 83;
112
+ divisor /= 83;
113
+ *destination++ = characters[digit];
114
+ }
115
+ return destination;
116
+ }
@@ -0,0 +1,9 @@
1
+ #ifndef __BLURHASH_ENCODE_H__
2
+ #define __BLURHASH_ENCODE_H__
3
+
4
+ #include <stdint.h>
5
+ #include <stdlib.h>
6
+
7
+ const char *blurHashForPixels(int xComponents, int yComponents, int width, int height, uint8_t *rgb, size_t bytesPerRow);
8
+
9
+ #endif