1 module lib;
2 
3 version(lib){
4 	import utils.misc;
5 	import pngtext;
6 	import std..string;
7 	import core.runtime;
8 	import core.memory;
9 
10 	/// to init the runtime, idk why `shared static this` won't work
11 	extern (C) void init(){
12 		rt_init();
13 	}
14 
15 	/// to terminate the runtime, idk why `shared static ~this` won't work
16 	extern (C) void term(){
17 		if (dataRead.ptr !is null){
18 			.destroy (dataRead);
19 		}
20 		GC.collect();
21 		rt_term;
22 	}
23 
24 	/// stores the return from readFromPng so the GC doesn't free that memory
25 	private ubyte[] dataRead;
26 
27 	/// reads data from png image
28 	extern (C) ubyte* readFromPng(char* fn, uint* length){
29 		string filename = fromStringz(fn).idup;
30 		if (dataRead.ptr !is null){
31 			.destroy (dataRead);
32 		}
33 		try{
34 			dataRead = readDataFromPng(filename);
35 		}catch (Exception e){
36 			*length = 0;
37 			return null;
38 		}
39 		*length = cast(uint)dataRead.length;
40 		return dataRead.ptr;
41 	}
42 
43 	/// writes data to png image
44 	/// 
45 	/// Returns: true if successful
46 	extern (C) bool writeToPng(char* fn, char* oFn, ubyte* dataPtr, uint dataLength){
47 		string filename = fromStringz(fn).idup;
48 		string outputFilename = fromStringz(oFn).idup;
49 		ubyte[] data;
50 		data.length = dataLength;
51 		ubyte* ptr = dataPtr;
52 		foreach (i; 0 .. dataLength){
53 			data[i] = *dataPtr;
54 			dataPtr++;
55 		}
56 		try{
57 			return writeDataToPng(filename, outputFilename, data).length == 0? true : false;
58 		}catch (Exception e){
59 			return false;
60 		}
61 	}
62 
63 	/// returns the number of bytes that can be stored
64 	extern (C) uint pngCapacity(char* fn, ubyte density){
65 		string filename = fromStringz(fn).idup;
66 		return cast(uint)calculatePngCapacity (filename, density);
67 	}
68 
69 	/// returns a float number, which tells the quality of the output image
70 	/// 
71 	/// the number is the average number of bits used per one byte (each pixel = 4 bytes). Only bytes from pixels which are used to hold
72 	/// data are considered in the calcualtion, untouched pixels are not counted as they remain as-they-were;
73 	/// the number can be at max 8 (saturated image), lowest 0 (no data & highest quality). Lower means higher quality.
74 	extern (C) float getQuality(char* fn, uint dataLength){
75 		string filename = fromStringz(fn).idup;
76 		// get the optimum quality assoc_array
77 		uinteger[ubyte] optimumQ = calculateOptimumDensity(filename , dataLength);
78 		// The formula is (index * value at index, for each index) / (total used bytes, = sum of values at all indexes)
79 		uinteger numerator = 0, denominator = 0;
80 		foreach (index, value; optimumQ){
81 			numerator += index * value;
82 			denominator += value;
83 		}
84 		return (cast(float)numerator*8) / (cast(float)denominator*8);
85 		
86 	}
87 }