How to Change RectangleF to Face of Picasa

Below is information about what Picasa stores as a hash. He stores them as follows:

faces=rect64(54391dc9b6a76c2b),4cd643f64b715489 [DSC_2289.jpg] faces=rect64(1680000a5c26c82),76bc8d8d518750bc 

Information on the Internet says this:

The number enclosed in rect64 () is a 64-bit hexadecimal number.

  • A break for four 16-bit numbers.
  • Divide each by the maximum 16-bit unsigned number (65535), and you will have four digits from 0 to 1.
  • The remaining four digits give the relative coordinates for the face rectangle: (left, top, right, bottom).
  • If you want to get the absolute coordinates, the image is slightly left and right across the width of the image, and the image height above and below.

So, my code, to turn this into a RectangleF, works just fine (keeping only relative coordinates):

  public static RectangleF GetRectangle(string hashstr) { UInt64 hash = UInt64.Parse(hashstr, System.Globalization.NumberStyles.HexNumber); byte[] bytes = BitConverter.GetBytes(hash); UInt16 l16 = BitConverter.ToUInt16(bytes, 6); UInt16 t16 = BitConverter.ToUInt16(bytes, 4); UInt16 r16 = BitConverter.ToUInt16(bytes, 2); UInt16 b16 = BitConverter.ToUInt16(bytes, 0); float left = l16 / 65535.0F; float top = t16 / 65535.0F; float right = r16 / 65535.0F; float bottom = b16 / 65535.0F; return new RectangleF(left, top, right - left, bottom - top); } 

Now I have RectangleF and I want to return it to the hash mentioned above. I can not understand this. It looks like picasa uses 2 bytes, including precision, however the float in C # is 8 bytes and even a bit converter. ToSingle - 4 bytes.

Any help was appreciated.

EDIT: That's what I have right now

  public static string HashFromRectangle(RectangleCoordinates rect) { Console.WriteLine("{0} {1} {2} {3}", rect.Left, rect.Top, rect.Right, rect.Bottom); UInt16 left = Convert.ToUInt16((float)rect.Left * 65535.0F); UInt16 top = Convert.ToUInt16((float)rect.Top * 65535.0F); UInt16 right = Convert.ToUInt16((float)rect.Right * 65535.0F); UInt16 bottom = Convert.ToUInt16((float)rect.Bottom * 65535.0F); byte[] lb = BitConverter.GetBytes(left); byte[] tb = BitConverter.GetBytes(top); byte[] rb = BitConverter.GetBytes(right); byte[] bb = BitConverter.GetBytes(bottom); byte[] barray = new byte[8]; barray[0] = lb[0]; barray[1] = lb[1]; barray[2] = tb[0]; barray[3] = tb[1]; barray[4] = rb[0]; barray[5] = rb[1]; barray[6] = bb[0]; barray[7] = bb[1]; return BitConverter.ToString(barray).Replace("-", "").ToLower(); } 
+4
source share
2 answers

Your current code replaces the bytes of each coordinate. This is because BitConverter gives you bytes in a small trailing order (i.e., the first byte in the array is the least significant byte). Switching between your assignments causes decoding and re-encoding to return the original hash.

  barray[0] = lb[1]; barray[1] = lb[0]; barray[2] = tb[1]; barray[3] = tb[0]; barray[4] = rb[1]; barray[5] = rb[0]; barray[6] = bb[1]; barray[7] = bb[0]; 

However, I think it’s clearer to do the conversion using simple multiplications and additions. You can do a similar thing with decrypting the hash string if you read it as a single ulong and subtract / split. for example for encoding:

  public static ushort ToUShort(double coordinate) { double ratio = Math.Max(0, Math.Min(Math.Round(coordinate * 65535), 65535)); return (ushort)ratio; } public static string HashFromRectangle(Rect rect) { ulong left = ToUShort(rect.Left); ulong top = ToUShort(rect.Top); ulong right = ToUShort(rect.Right); ulong bottom = ToUShort(rect.Bottom); ulong hash = (((left * 65536) + top) * 65536 + right) * 65536 + bottom; return hash.ToString("x"); } 
+1
source

It looks like you need to take out the float types from the HashFromRectangle (rect) as follows:

  UInt16 left = (UInt16)( rect.Left * 65535.0F); UInt16 top =(UInt16) (rect.Top * 65535.0F); UInt16 right = (UInt16) (rect.Right * 65535.0F); UInt16 bottom = (UInt16) (rect.Bottom * 65535.0F); 

Also, it may be more readable to use this to populate the array:

  Array.Copy(lb, 0, barray, 0, 2); Array.Copy(tb, 0, barray, 2, 2); Array.Copy(rb, 0, barray, 4, 2); Array.Copy(bb, 0, barray, 6, 2); 

Let me know if this works!

Aaron

0
source

Source: https://habr.com/ru/post/1300315/


All Articles