Home > Back-end >  What's the best way to compress multiple values into deserializable value?
What's the best way to compress multiple values into deserializable value?

Time:06-10

I'm implementing an openpeeps.com library for Flutter in which user can create their own peeps to use as an avatar within our product.

One of the reasons behind using peeps as avatar is that (in theory) it can be easily stored as a single value within a database.

A Peep within my library contains of up to 6 PeepAtoms:

class Peep {
  final PeepAtom head;
  final PeepAtom face;
  final PeepAtom facialHair;
  final PeepAtom? accessories;
  final PeepAtom? body;
  final PeepAtom? pose;
}

A PeepAtom is currently just a name identifying the underlying image file required to build a Peep:

class PeepAtom {
  final String name;
}

How to get a hash?

What I'd like to do now is get a single value from a Peep (int or string) which I can store in a database. If I retrieve the data, I'd like to deconstruct the value into the unique atoms so I can render the appropriate atom images to display the Peep. While I'm not really looking to optimize for storage size, it would be nice if the bytesize would be small.

Since I'm normally not working with such stuff I don't have an idea what's the best option. These are my (naïve) ideas:

  • do a Peep.toJson and convert the output to base64. Likely inefficient due to a bunch of unnecessary characters.
  • do a PeepAtom.hashCode for each field within a Peep and upload this. As an array that would be 64bit = 8 Byte * 6 (Atoms). Thats pretty ok but not a single value.
  • since there are only a limited number of Atoms in each category (less than 100) I could use bitshifts and ^ to put this into one int. However, I think this would not really working because I'd need a unique identifier and since I'm code generating the PeepAtoms within my code that likely would be quite complex.

Any better ideas/algorithms?

CodePudding user response:

I'm not sure what you mean by "quite complex". It looks quite simple to pack your atoms into a double.

Note that this is no way a "hash". A hash is a lossy operation. I presume that you want to recover the original data.

Based on your description, you need seven bits for each atom. They can range in 0..98 (since you said "less than 100"). A double has 52 bits of mantissa. Your six atoms needs 42 bits, so it fits easily. For atoms that can be null, just give that a special unused 7-bit value, like 127.

Now just use multiply and add to combine them. Use modulo and divide to pull them back out. E.g.:

double val = head;
val = val * 128   face;
val = val * 128   facialHair;
...

To extract:

int pose = val % 128;
val = (val / 128).floorToDouble();
int body = val % 128;
val = (val / 128).floorToDouble();
...
  • Related