Skip to content

Commit

Permalink
Made changes to indentation and declared common functions in common.h
Browse files Browse the repository at this point in the history
  • Loading branch information
Narasimha1997 committed Nov 28, 2020
1 parent cbe93d4 commit 8deeac3
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 202 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*.perspectivev3
!default.perspectivev3
xcuserdata/
C/blurhash
C/blurhash_encoder
C/blurhash_decoder
Ruby/.*
Ruby/Makefile
Expand Down
10 changes: 5 additions & 5 deletions C/Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
PROGRAM=blurhash
PROGRAM=blurhash_encoder
DECODER=blurhash_decoder
$(PROGRAM): blurhash_stb.c encode.c encode.h stb_image.h
$(CC) -o $@ blurhash_stb.c encode.c -lm
$(PROGRAM): encode_stb.c encode.c encode.h stb_image.h common.h
$(CC) -o $@ encode_stb.c encode.c -lm

$(DECODER): decoder/decode_main.c decoder/decode.c decoder/decode.h decoder/stb_writer.h
$(CC) -o $(DECODER) decoder/decode_main.c decoder/decode.c -Idecoder/ -lm
$(DECODER): decode_stb.c decode.c decode.h stb_writer.h common.h
$(CC) -o $(DECODER) decode_stb.c decode.c -lm

.PHONY: clean
clean:
Expand Down
10 changes: 7 additions & 3 deletions C/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ It will be overwritten on the next call into the function, so be careful!

## Usage as a command-line tool

You can also build a command-line version to test the encoder. However, note that it uses `stb_image` to load images,
You can also build a command-line version to test the encoder and decoder. However, note that it uses `stb_image` to load images,
which is not really security-hardened, so it is **not** recommended to use this version in production on untrusted data!
Use one of the integrations instead, which use more robust image loading libraries.

Nevertheless, if you want to try it out quickly, simply run:

$ make
$ ./blurhash 4 3 ../Swift/BlurHashTest/pic1.png
$ make blurhash_encoder
$ ./blurhash_encoder 4 3 ../Swift/BlurHashTest/pic1.png
LaJHjmVu8_~po#smR+a~xaoLWCRj

If you want to try out the decoder, simply run:
$ make blurhash_decoder
$ ./blurhash_decoder "LaJHjmVu8_~po#smR+a~xaoLWCRj" 32 32 decoded_output.png
26 changes: 26 additions & 0 deletions C/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef __BLURHASH_COMMON_H__
#define __BLURHASH_COMMON_H__

#include<math.h>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

static inline int linearTosRGB(float value) {
float v = fmaxf(0, fminf(1, value));
if(v <= 0.0031308) return v * 12.92 * 255 + 0.5;
else return (1.055 * powf(v, 1 / 2.4) - 0.055) * 255 + 0.5;
}

static inline float sRGBToLinear(int value) {
float v = (float)value / 255;
if(v <= 0.04045) return v / 12.92;
else return powf((v + 0.055) / 1.055, 2.4);
}

static inline float signPow(float value, float exp) {
return copysignf(powf(fabsf(value), exp), value);
}

#endif
75 changes: 5 additions & 70 deletions C/decoder/decode.c → C/decode.c
Original file line number Diff line number Diff line change
@@ -1,86 +1,34 @@
#include "decode.h"

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#include "common.h"

static char chars[83] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~";

/*
Image processing functions start
*/

static float sRGBToLinear(int value) {
float v = (float)value / 255;
if(v <= 0.04045) return v / 12.92;
else return powf((v + 0.055) / 1.055, 2.4);
}

static float signPow(float value, float exp) {
return copysignf(powf(fabsf(value), exp), value);
}

static int linearTosRGB(float value) {
float v = fmaxf(0, fminf(1, value));
if(v <= 0.0031308) return v * 12.92 * 255 + 0.5;
else return (1.055 * powf(v, 1 / 2.4) - 0.055) * 255 + 0.5;
}

/*
Image processing functions end
*/

/*
decoder helper functions start
*/

static inline uint8_t clampToUByte(int * src) {
if( *src >= 0 && *src <= 255 )
return *src;
return (*src < 0) ? 0 : 255;
}


static inline uint8_t * createByteArray(int size) {
return (uint8_t *)malloc(size * sizeof(uint8_t));
}

/*
decoder helper functions end
*/


/*
Base-83 decoder start
*/

int decodeToInt(const char * string, int start, int end) {
int value = 0, iter1 = 0, iter2 = 0;
for( iter1 = start; iter1 < end; iter1 ++) {

int index = -1;
for(iter2 = 0; iter2 < 83; iter2 ++) {
if (chars[iter2] == string[iter1]) {
index = iter2;
break;
}
}

if (index == -1) return -1;
value = value * 83 + index;
}

return value;
}

/*
Base-83 decoder end
*/

/*
Blurhash functions start
*/

bool isValidBlurhash(const char * blurhash) {

const int hashLength = strlen(blurhash);
Expand All @@ -92,39 +40,29 @@ bool isValidBlurhash(const char * blurhash) {
int numX = (sizeFlag % 9) + 1;

if (hashLength != 4 + 2 * numX * numY) return false;

return true;
}

void decodeDC(int value, float * r, float * g, float * b) {
*r = sRGBToLinear(value >> 16); // R-component

*g = sRGBToLinear((value >> 8) & 255); // G-Component

*b = sRGBToLinear(value & 255); // B-Component

}


void decodeAC(int value, float maximumValue, float * r, float * g, float * b) {

int quantR = (int)floorf(value / (19 * 19));
int quantR = (int)floorf(value / (19 * 19));
int quantG = (int)floorf(value / 19) % 19;
int quantB = (int)value % 19;


*r = signPow(((float)quantR - 9) / 9, 2.0) * maximumValue;

*g = signPow(((float)quantG - 9) / 9, 2.0) * maximumValue;

*b = signPow(((float)quantB - 9) / 9, 2.0) * maximumValue;
}


int decodeToArray(const char * blurhash, int width, int height, int punch, int nChannels, uint8_t * pixelArray) {

if (! isValidBlurhash(blurhash)) return -1;

if (punch < 1) punch = 1;

int sizeFlag = decodeToInt(blurhash, 0, 1);
Expand All @@ -133,13 +71,11 @@ int decodeToArray(const char * blurhash, int width, int height, int punch, int n
int iter = 0;

float r = 0, g = 0, b = 0;

int quantizedMaxValue = decodeToInt(blurhash, 1, 2);
if (quantizedMaxValue == -1) return -1;

float maxValue = ((float)(quantizedMaxValue + 1)) / 166;


int colors_size = numX * numY;
float colors[colors_size][3];

Expand Down Expand Up @@ -204,12 +140,11 @@ uint8_t * decode(const char * blurhash, int width, int height, int punch, int nC

if (decodeToArray(blurhash, width, height, punch, nChannels, pixelArray) == -1)
return NULL;

return pixelArray;
}

void freePixelArray(uint8_t * pixelArray) {
if (pixelArray) {
free(pixelArray);
}
if (pixelArray) {
free(pixelArray);
}
}
54 changes: 54 additions & 0 deletions C/decode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef __BLURHASH_DECODE_H__

#define __BLURHASH_DECODE_H

#include <math.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

/*
decode : Returns the pixel array of the result image given the blurhash string,
Parameters :
blurhash : A string representing the blurhash to be decoded.
width : Width of the resulting image
height : Height of the resulting image
punch : The factor to improve the contrast, default = 1
nChannels : Number of channels in the resulting image array, 3 = RGB, 4 = RGBA
Returns : A pointer to memory region where pixels are stored in (H, W, C) format
*/
uint8_t * decode(const char * blurhash, int width, int height, int punch, int nChannels);

/*
decodeToArray : Decodes the blurhash and copies the pixels to pixelArray,
This method is suggested if you use an external memory allocator for pixelArray.
pixelArray should be of size : width * height * nChannels
Parameters :
blurhash : A string representing the blurhash to be decoded.
width : Width of the resulting image
height : Height of the resulting image
punch : The factor to improve the contrast, default = 1
nChannels : Number of channels in the resulting image array, 3 = RGB, 4 = RGBA
pixelArray : Pointer to memory region where pixels needs to be copied.
Returns : int, -1 if error 0 if successful
*/
int decodeToArray(const char * blurhash, int width, int height, int punch, int nChannels, uint8_t * pixelArray);

/*
isValidBlurhash : Checks if the Blurhash is valid or not.
Parameters :
blurhash : A string representing the blurhash
Returns : bool (true if it is a valid blurhash, else false)
*/
bool isValidBlurhash(const char * blurhash);

/*
freePixelArray : Frees the pixel array
Parameters :
pixelArray : Pixel array pointer which will be freed.
Returns : void (None)
*/
void freePixelArray(uint8_t * pixelArray);

#endif
40 changes: 40 additions & 0 deletions C/decode_stb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "decode.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_writer.h"

int main(int argc, char **argv) {
if(argc < 5) {
fprintf(stderr, "Usage: %s hash width height output_file [punch]\n", argv[0]);
return 1;
}

int width, height, punch = 1;
char * hash = argv[1];
width = atoi(argv[2]);
height = atoi(argv[3]);
char * output_file = argv[4];

const int nChannels = 4;

if(argc == 6)
punch = atoi(argv[5]);

uint8_t * bytes = decode(hash, width, height, punch, nChannels);

if (!bytes) {
fprintf(stderr, "%s is not a valid blurhash, decoding failed.\n", hash);
return 1;
}

if (stbi_write_png(output_file, width, height, nChannels, bytes, nChannels * width) == 0) {
fprintf(stderr, "Failed to write PNG file %s\n", output_file);
return 1;
}

freePixelArray(bytes);

fprintf(stdout, "Decoded blurhash successfully, wrote PNG file %s\n", output_file);
return 0;

}
59 changes: 0 additions & 59 deletions C/decoder/decode.h

This file was deleted.

Loading

0 comments on commit 8deeac3

Please sign in to comment.