commit 45a2ad4060d9b717c5ad0ea68a94131c58dfb9ee
parent 1d11a26ceb1458791883218a2889d0e9e802900e
Author: Dominik Schmidt <das1993@hotmail.com>
Date: Thu, 27 Aug 2015 12:40:38 +0200
Move puzzle.d in src/ subdirectory
Diffstat:
puzzle.d | | | 435 | ------------------------------------------------------------------------------- |
src/puzzle.d | | | 435 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 435 insertions(+), 435 deletions(-)
diff --git a/puzzle.d b/puzzle.d
@@ -1,435 +0,0 @@
-module puzzle;
-
-version(unittest){
- static immutable string testimage="iVBORw0KGgoAAAANSUhEUgAAAE4AAAASAQMAAADPKHrSAAAABlBMVEX///8AAABVwtN+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wgbCSsvSqRkugAAAGxJREFUCNdjYEAAGyYDMH2AgUGCSQDMdAAyGTCZDQwSbLL9yRL//jkrANVKHDPk6OlxEwBpcxHkkJCAMwUE3H9AmQYGbkATlEDMhAQwE6htxqFDTgIM9s+3tz549+/f5wcg01kQLkJi8jHgAQA3KhrFG5DorwAAAABJRU5ErkJggg==";
- ubyte[] testimagedat(){
- import std.base64;
- return cast(ubyte[])Base64.decode(testimage);
- }
-}
-
-extern(C){
- struct PuzzleContext {
- uint puzzle_max_width;
- uint puzzle_max_height;
- uint puzzle_lambdas;
- double puzzle_p_ratio;
- double puzzle_noise_cutoff;
- double puzzle_contrast_barrier_for_cropping;
- double puzzle_max_cropping_ratio;
- int puzzle_enable_autocrop;
- ulong magic;
- };
- struct PuzzleDvec {
- size_t sizeof_vec;
- size_t sizeof_compressed_vec;
- double *vec;
- };
-
- struct PuzzleCvec {
- size_t sizeof_vec;
- char *vec;
- };
- struct PuzzleCompressedCvec {
- size_t sizeof_compressed_vec;
- ubyte *vec;
-};
-
- void
- puzzle_init_context(PuzzleContext *context);
-
- void
- puzzle_free_context(PuzzleContext *context);
-
- void
- puzzle_init_cvec(PuzzleContext *context, PuzzleCvec *cvec);
-
- void
- puzzle_init_dvec(PuzzleContext *context, PuzzleDvec *dvec);
-
- int
- puzzle_fill_dvec_from_file(PuzzleContext *context, PuzzleDvec * dvec, const char *file);
-
- int
- puzzle_fill_cvec_from_file(PuzzleContext *context, PuzzleCvec * cvec, const char *file);
-
- int
- puzzle_fill_dvec_from_mem(PuzzleContext *context, PuzzleDvec * dvec, const void *mem,
- size_t size);
-
- int
- puzzle_fill_cvec_from_mem(PuzzleContext *context, PuzzleCvec * cvec, const void *mem,
- size_t size);
-
- int
- puzzle_fill_cvec_from_dvec(PuzzleContext *context, PuzzleCvec * cvec,
- const PuzzleDvec *dvec);
-
- void
- puzzle_free_cvec(PuzzleContext *context, PuzzleCvec *cvec);
-
- void
- puzzle_free_dvec(PuzzleContext *context, PuzzleDvec *dvec);
-
- void
- puzzle_init_compressed_cvec(PuzzleContext *context,
- PuzzleCompressedCvec * compressed_cvec);
-
- void
- puzzle_free_compressed_cvec(PuzzleContext *context,
- PuzzleCompressedCvec * compressed_cvec);
-
- int
- puzzle_compress_cvec(PuzzleContext *context, PuzzleCompressedCvec * compressed_cvec,
- const PuzzleCvec * cvec);
-
- int
- puzzle_uncompress_cvec(PuzzleContext *context, PuzzleCompressedCvec * compressed_cvec,
- const(PuzzleCvec *) cvec);
-
- double
- puzzle_vector_normalized_distance(PuzzleContext *context, const PuzzleCvec * cvec1,
- const PuzzleCvec * cvec2, int fix_for_texts);
-
-}
-import std.string;
-
-static bool valid(in PuzzleContext ctx){
- return (ctx.magic==0xdeadbeef);
-}
-static bool valid(in PuzzleContext *ctx){
- return (ctx!=null && valid(*ctx));
-}
-
-class PuzzleException : Exception{
- pure nothrow @safe this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null){
- super(msg,file,line,next);
- }
-}
-
-/**
- * PuzzleContext wrapper
- *
- * Has to be inititialized with `Puzzle.initialize();`
- * and frees the context on destruction.
- *
- * Be careful, when you stack-allocate it, the object gets
- * rendered unusable once the scope has been left.
- *
- */
-struct Puzzle{
- PuzzleContext ctx;
- /**
- * Initializes the Puzzle-context.
- *
- */
- void initialize()
- out{
- assert(ctx.valid());
- }
- body{
- puzzle_init_context(&ctx);
- }
-
- ///Frees the PuzzleContext (If there is one)
- ~this(){
- if(ctx.valid){
- puzzle_free_context(&ctx);
- }
- }
- /**
- * Returns a newly allocated DVec-Structure
- *
- * $(DDOC_SEE_ALSO struct DVec)
- *
- */
- DVec dvec(){
- return DVec(&ctx);
- }
-
- /**
- * Returns a newly allocated CVec-Structure
- *
- * $(DDOC_SEE_ALSO struct CVec)
- *
- */
- CVec cvec(){
- return CVec(&ctx);
- }
-}
-///
-unittest{
- Puzzle p;
- assert(!p.ctx.valid);
- p.initialize();
- assert(p.ctx.valid);
-
- DVec d=p.dvec();
- assert(d.ctx.valid);
-
- DVec c=p.dvec();
- assert(c.ctx.valid);
-}
-
-/**
- * Wraps the PuzzleDVec-structure
- *
- */
-struct DVec{
- PuzzleDvec vec;
- PuzzleContext *ctx;
- @disable this();
-
- ///Initializes the DVec
- this(PuzzleContext *ctx)
- in{
- assert(ctx.valid(), "Context invalid");
- }
- body{
- this.ctx=ctx;
- puzzle_init_dvec(ctx,&vec);
- }
-
- ///Frees the DVec (If it has been allocated by the library);
- ~this(){
- if(ctx!=null){
- puzzle_free_dvec(ctx,&vec);
- }
- }
-
- /**
- * Generates the vector from a file.
- * Params:
- * f = File to read the data from.
- * Throws:
- * PuzzleException if the puzzle-function fails to load the image
- */
- void load(string f){
- if(puzzle_fill_dvec_from_file(ctx, &vec, toStringz(f))!=0){
- throw new PuzzleException("Couldn't read from file");
- }
- }
-
- /**
- * Generates the vector from memory
- * Params:
- * mem = The memory of an Image
- * Throws:
- * PuzzleException if the memory couldn't be read.
- */
- void load(void mem[]){
- if(puzzle_fill_dvec_from_mem(ctx, &vec, cast(void*)mem, mem.length)!=0){
- throw new PuzzleException("Couldn't read from memory");
- }
- }
- /**
- * Get the CVec derived from this DVector.
- * Returns:
- * The corresponding(and comparable) CVector to this DVector
- */
- CVec cvec(){
- CVec cvec=CVec(ctx);
- puzzle_fill_cvec_from_dvec(ctx,&cvec.vec,&vec);
- return cvec;
- }
-
- /**
- * Get the length of the vector
- * Returns:
- * The length of the vector
- */
- @safe @nogc @property size_t length(){
- return vec.sizeof_vec;
- }
-}
-
-///
-struct CVec{
- PuzzleCvec vec;
- PuzzleContext *ctx;
- @disable this();
- this(ref CVec_Compressed c){
- this(c.ctx);
- puzzle_uncompress_cvec(ctx, &c.vec, &vec);
- }
- /**
- * Generates a Vector by hand.
- *
- * This can be used to save a Vector and reload it again.
- *
- * Params:
- * a = The array of data to fill the vector with.
- */
- @nogc pure nothrow this(byte[] a){
- this(cast(char*)a.ptr, a.length);
- }
- ///ditto
- @nogc pure nothrow this(char *a, size_t length){
- vec.vec=a;
- vec.sizeof_vec=length;
- }
-
- ///
- unittest{
- Puzzle p;
- p.initialize();
- CVec c=p.cvec();
-
- c.load(testimagedat());
- assert(c.length>0);
-
- CVec c2=CVec(c.vec.vec,c.length);
- assert(std.math.approxEqual(c.compare(c2),0));
- }
-
- ///Initializes a Vector
- this(PuzzleContext *ctx)
- in{
- assert(ctx.valid(), "Context invalid");
- }
- body{
- this.ctx=ctx;
- puzzle_init_cvec(ctx,&vec);
- }
- ///Frees the vector(If it was allocated by the library)
- ~this(){
- if(ctx!=null){
- puzzle_free_cvec(ctx,&vec);
- }
- }
-
- /**
- * Generates the vector from a file.
- * Params:
- * f = File to read the data from.
- * Throws:
- * PuzzleException if the puzzle-function fails to load the image
- */
- void load(string f){
- if(puzzle_fill_cvec_from_file(ctx, &vec, toStringz(f))!=0){
- throw new PuzzleException("Couldn't read from file");
- }
- }
-
- /**
- * Generates the vector from memory
- * Params:
- * mem = The memory of an Image
- * Throws:
- * PuzzleException if the memory couldn't be read.
- */
- void load(void mem[]){
- if(puzzle_fill_cvec_from_mem(ctx, &vec, cast(void*)mem, mem.length)!=0){
- throw new PuzzleException("Couldn't read from memory");
- }
- }
-
- /**
- * Compare two CVectors.
- * Params:
- * b = The second vector to compare to
- * hasText = Wether one of the images had any text in it.
- * Returns:
- * The distance of both vectors.
- */
- double compare(in ref CVec b, bool hasText=false){
- return puzzle_vector_normalized_distance(ctx,&vec,&b.vec,(hasText) ? 1 : 0);
- }
-
-
- /**
- * Compresses a CVector
- * Returns:
- * A compressed CVector
- */
- CVec_Compressed compress(){
- return CVec_Compressed(this);
- }
-
- /**
- * Get the length of the vector
- * Returns:
- * The length of the vector
- */
- @nogc @safe @property size_t length(){
- return vec.sizeof_vec;
- }
-}
-
-///
-unittest{
- Puzzle p;
- p.initialize();
- CVec c=p.cvec();
- c.load(testimagedat());
-
- assert(std.math.approxEqual(c.compare(c),0));
-}
-
-///A compressed CVector
-struct CVec_Compressed{
- PuzzleCompressedCvec vec;
- PuzzleContext *ctx;
- @disable this();
-
- ///Generates a compressed CVector corresponding to c
- this(ref CVec c){
- this(c.ctx);
- puzzle_compress_cvec(ctx, &vec, &c.vec);
- }
-
- /**
- * Generates a Vector by hand.
- *
- * Params:
- * a = The array of data to fill the vector with.
- */
- this(ubyte[] a){
- this(a.ptr,a.length);
- }
-
- ///ditto
- this(ubyte* a, size_t length){
- vec.vec=a;
- vec.sizeof_compressed_vec=length;
- }
-
- ///Allocates a new Compressed CVector in the library
- this(PuzzleContext *ctx)
- in{
- assert(ctx.valid(), "Context invalid");
- }
- body{
- this.ctx=ctx;
- puzzle_init_compressed_cvec(ctx,&vec);
- }
-
- ///Frees the Vector, if it was allocated by the library
- ~this(){
- if(ctx!=null){
- puzzle_free_compressed_cvec(ctx,&vec);
- }
- }
-
- ///Returns the corresponding uncompressed CVector
- CVec uncompress(){
- return CVec(this);
- }
-
- ///
- @safe @nogc @property size_t length(){
- return vec.sizeof_compressed_vec;
- }
-}
-
-///
-unittest{
- Puzzle p;
- p.initialize();
- CVec c=p.cvec();
- c.load(testimagedat());
- CVec_Compressed cc=c.compress();
- CVec c2=cc.uncompress();
-
- assert(std.math.approxEqual(c.compare(c2),0));
-}
diff --git a/src/puzzle.d b/src/puzzle.d
@@ -0,0 +1,435 @@
+module puzzle;
+
+version(unittest){
+ static immutable string testimage="iVBORw0KGgoAAAANSUhEUgAAAE4AAAASAQMAAADPKHrSAAAABlBMVEX///8AAABVwtN+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wgbCSsvSqRkugAAAGxJREFUCNdjYEAAGyYDMH2AgUGCSQDMdAAyGTCZDQwSbLL9yRL//jkrANVKHDPk6OlxEwBpcxHkkJCAMwUE3H9AmQYGbkATlEDMhAQwE6htxqFDTgIM9s+3tz549+/f5wcg01kQLkJi8jHgAQA3KhrFG5DorwAAAABJRU5ErkJggg==";
+ ubyte[] testimagedat(){
+ import std.base64;
+ return cast(ubyte[])Base64.decode(testimage);
+ }
+}
+
+extern(C){
+ struct PuzzleContext {
+ uint puzzle_max_width;
+ uint puzzle_max_height;
+ uint puzzle_lambdas;
+ double puzzle_p_ratio;
+ double puzzle_noise_cutoff;
+ double puzzle_contrast_barrier_for_cropping;
+ double puzzle_max_cropping_ratio;
+ int puzzle_enable_autocrop;
+ ulong magic;
+ };
+ struct PuzzleDvec {
+ size_t sizeof_vec;
+ size_t sizeof_compressed_vec;
+ double *vec;
+ };
+
+ struct PuzzleCvec {
+ size_t sizeof_vec;
+ char *vec;
+ };
+ struct PuzzleCompressedCvec {
+ size_t sizeof_compressed_vec;
+ ubyte *vec;
+};
+
+ void
+ puzzle_init_context(PuzzleContext *context);
+
+ void
+ puzzle_free_context(PuzzleContext *context);
+
+ void
+ puzzle_init_cvec(PuzzleContext *context, PuzzleCvec *cvec);
+
+ void
+ puzzle_init_dvec(PuzzleContext *context, PuzzleDvec *dvec);
+
+ int
+ puzzle_fill_dvec_from_file(PuzzleContext *context, PuzzleDvec * dvec, const char *file);
+
+ int
+ puzzle_fill_cvec_from_file(PuzzleContext *context, PuzzleCvec * cvec, const char *file);
+
+ int
+ puzzle_fill_dvec_from_mem(PuzzleContext *context, PuzzleDvec * dvec, const void *mem,
+ size_t size);
+
+ int
+ puzzle_fill_cvec_from_mem(PuzzleContext *context, PuzzleCvec * cvec, const void *mem,
+ size_t size);
+
+ int
+ puzzle_fill_cvec_from_dvec(PuzzleContext *context, PuzzleCvec * cvec,
+ const PuzzleDvec *dvec);
+
+ void
+ puzzle_free_cvec(PuzzleContext *context, PuzzleCvec *cvec);
+
+ void
+ puzzle_free_dvec(PuzzleContext *context, PuzzleDvec *dvec);
+
+ void
+ puzzle_init_compressed_cvec(PuzzleContext *context,
+ PuzzleCompressedCvec * compressed_cvec);
+
+ void
+ puzzle_free_compressed_cvec(PuzzleContext *context,
+ PuzzleCompressedCvec * compressed_cvec);
+
+ int
+ puzzle_compress_cvec(PuzzleContext *context, PuzzleCompressedCvec * compressed_cvec,
+ const PuzzleCvec * cvec);
+
+ int
+ puzzle_uncompress_cvec(PuzzleContext *context, PuzzleCompressedCvec * compressed_cvec,
+ const(PuzzleCvec *) cvec);
+
+ double
+ puzzle_vector_normalized_distance(PuzzleContext *context, const PuzzleCvec * cvec1,
+ const PuzzleCvec * cvec2, int fix_for_texts);
+
+}
+import std.string;
+
+static bool valid(in PuzzleContext ctx){
+ return (ctx.magic==0xdeadbeef);
+}
+static bool valid(in PuzzleContext *ctx){
+ return (ctx!=null && valid(*ctx));
+}
+
+class PuzzleException : Exception{
+ pure nothrow @safe this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null){
+ super(msg,file,line,next);
+ }
+}
+
+/**
+ * PuzzleContext wrapper
+ *
+ * Has to be inititialized with `Puzzle.initialize();`
+ * and frees the context on destruction.
+ *
+ * Be careful, when you stack-allocate it, the object gets
+ * rendered unusable once the scope has been left.
+ *
+ */
+struct Puzzle{
+ PuzzleContext ctx;
+ /**
+ * Initializes the Puzzle-context.
+ *
+ */
+ void initialize()
+ out{
+ assert(ctx.valid());
+ }
+ body{
+ puzzle_init_context(&ctx);
+ }
+
+ ///Frees the PuzzleContext (If there is one)
+ ~this(){
+ if(ctx.valid){
+ puzzle_free_context(&ctx);
+ }
+ }
+ /**
+ * Returns a newly allocated DVec-Structure
+ *
+ * $(DDOC_SEE_ALSO struct DVec)
+ *
+ */
+ DVec dvec(){
+ return DVec(&ctx);
+ }
+
+ /**
+ * Returns a newly allocated CVec-Structure
+ *
+ * $(DDOC_SEE_ALSO struct CVec)
+ *
+ */
+ CVec cvec(){
+ return CVec(&ctx);
+ }
+}
+///
+unittest{
+ Puzzle p;
+ assert(!p.ctx.valid);
+ p.initialize();
+ assert(p.ctx.valid);
+
+ DVec d=p.dvec();
+ assert(d.ctx.valid);
+
+ DVec c=p.dvec();
+ assert(c.ctx.valid);
+}
+
+/**
+ * Wraps the PuzzleDVec-structure
+ *
+ */
+struct DVec{
+ PuzzleDvec vec;
+ PuzzleContext *ctx;
+ @disable this();
+
+ ///Initializes the DVec
+ this(PuzzleContext *ctx)
+ in{
+ assert(ctx.valid(), "Context invalid");
+ }
+ body{
+ this.ctx=ctx;
+ puzzle_init_dvec(ctx,&vec);
+ }
+
+ ///Frees the DVec (If it has been allocated by the library);
+ ~this(){
+ if(ctx!=null){
+ puzzle_free_dvec(ctx,&vec);
+ }
+ }
+
+ /**
+ * Generates the vector from a file.
+ * Params:
+ * f = File to read the data from.
+ * Throws:
+ * PuzzleException if the puzzle-function fails to load the image
+ */
+ void load(string f){
+ if(puzzle_fill_dvec_from_file(ctx, &vec, toStringz(f))!=0){
+ throw new PuzzleException("Couldn't read from file");
+ }
+ }
+
+ /**
+ * Generates the vector from memory
+ * Params:
+ * mem = The memory of an Image
+ * Throws:
+ * PuzzleException if the memory couldn't be read.
+ */
+ void load(void mem[]){
+ if(puzzle_fill_dvec_from_mem(ctx, &vec, cast(void*)mem, mem.length)!=0){
+ throw new PuzzleException("Couldn't read from memory");
+ }
+ }
+ /**
+ * Get the CVec derived from this DVector.
+ * Returns:
+ * The corresponding(and comparable) CVector to this DVector
+ */
+ CVec cvec(){
+ CVec cvec=CVec(ctx);
+ puzzle_fill_cvec_from_dvec(ctx,&cvec.vec,&vec);
+ return cvec;
+ }
+
+ /**
+ * Get the length of the vector
+ * Returns:
+ * The length of the vector
+ */
+ @safe @nogc @property size_t length(){
+ return vec.sizeof_vec;
+ }
+}
+
+///
+struct CVec{
+ PuzzleCvec vec;
+ PuzzleContext *ctx;
+ @disable this();
+ this(ref CVec_Compressed c){
+ this(c.ctx);
+ puzzle_uncompress_cvec(ctx, &c.vec, &vec);
+ }
+ /**
+ * Generates a Vector by hand.
+ *
+ * This can be used to save a Vector and reload it again.
+ *
+ * Params:
+ * a = The array of data to fill the vector with.
+ */
+ @nogc pure nothrow this(byte[] a){
+ this(cast(char*)a.ptr, a.length);
+ }
+ ///ditto
+ @nogc pure nothrow this(char *a, size_t length){
+ vec.vec=a;
+ vec.sizeof_vec=length;
+ }
+
+ ///
+ unittest{
+ Puzzle p;
+ p.initialize();
+ CVec c=p.cvec();
+
+ c.load(testimagedat());
+ assert(c.length>0);
+
+ CVec c2=CVec(c.vec.vec,c.length);
+ assert(std.math.approxEqual(c.compare(c2),0));
+ }
+
+ ///Initializes a Vector
+ this(PuzzleContext *ctx)
+ in{
+ assert(ctx.valid(), "Context invalid");
+ }
+ body{
+ this.ctx=ctx;
+ puzzle_init_cvec(ctx,&vec);
+ }
+ ///Frees the vector(If it was allocated by the library)
+ ~this(){
+ if(ctx!=null){
+ puzzle_free_cvec(ctx,&vec);
+ }
+ }
+
+ /**
+ * Generates the vector from a file.
+ * Params:
+ * f = File to read the data from.
+ * Throws:
+ * PuzzleException if the puzzle-function fails to load the image
+ */
+ void load(string f){
+ if(puzzle_fill_cvec_from_file(ctx, &vec, toStringz(f))!=0){
+ throw new PuzzleException("Couldn't read from file");
+ }
+ }
+
+ /**
+ * Generates the vector from memory
+ * Params:
+ * mem = The memory of an Image
+ * Throws:
+ * PuzzleException if the memory couldn't be read.
+ */
+ void load(void mem[]){
+ if(puzzle_fill_cvec_from_mem(ctx, &vec, cast(void*)mem, mem.length)!=0){
+ throw new PuzzleException("Couldn't read from memory");
+ }
+ }
+
+ /**
+ * Compare two CVectors.
+ * Params:
+ * b = The second vector to compare to
+ * hasText = Wether one of the images had any text in it.
+ * Returns:
+ * The distance of both vectors.
+ */
+ double compare(in ref CVec b, bool hasText=false){
+ return puzzle_vector_normalized_distance(ctx,&vec,&b.vec,(hasText) ? 1 : 0);
+ }
+
+
+ /**
+ * Compresses a CVector
+ * Returns:
+ * A compressed CVector
+ */
+ CVec_Compressed compress(){
+ return CVec_Compressed(this);
+ }
+
+ /**
+ * Get the length of the vector
+ * Returns:
+ * The length of the vector
+ */
+ @nogc @safe @property size_t length(){
+ return vec.sizeof_vec;
+ }
+}
+
+///
+unittest{
+ Puzzle p;
+ p.initialize();
+ CVec c=p.cvec();
+ c.load(testimagedat());
+
+ assert(std.math.approxEqual(c.compare(c),0));
+}
+
+///A compressed CVector
+struct CVec_Compressed{
+ PuzzleCompressedCvec vec;
+ PuzzleContext *ctx;
+ @disable this();
+
+ ///Generates a compressed CVector corresponding to c
+ this(ref CVec c){
+ this(c.ctx);
+ puzzle_compress_cvec(ctx, &vec, &c.vec);
+ }
+
+ /**
+ * Generates a Vector by hand.
+ *
+ * Params:
+ * a = The array of data to fill the vector with.
+ */
+ this(ubyte[] a){
+ this(a.ptr,a.length);
+ }
+
+ ///ditto
+ this(ubyte* a, size_t length){
+ vec.vec=a;
+ vec.sizeof_compressed_vec=length;
+ }
+
+ ///Allocates a new Compressed CVector in the library
+ this(PuzzleContext *ctx)
+ in{
+ assert(ctx.valid(), "Context invalid");
+ }
+ body{
+ this.ctx=ctx;
+ puzzle_init_compressed_cvec(ctx,&vec);
+ }
+
+ ///Frees the Vector, if it was allocated by the library
+ ~this(){
+ if(ctx!=null){
+ puzzle_free_compressed_cvec(ctx,&vec);
+ }
+ }
+
+ ///Returns the corresponding uncompressed CVector
+ CVec uncompress(){
+ return CVec(this);
+ }
+
+ ///
+ @safe @nogc @property size_t length(){
+ return vec.sizeof_compressed_vec;
+ }
+}
+
+///
+unittest{
+ Puzzle p;
+ p.initialize();
+ CVec c=p.cvec();
+ c.load(testimagedat());
+ CVec_Compressed cc=c.compress();
+ CVec c2=cc.uncompress();
+
+ assert(std.math.approxEqual(c.compare(c2),0));
+}