Frage

Hier finden Sie die Details für das, was Picasa als Hash speichert. Es speichert sie so:

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

Infos im Web sagen Folgendes:

Die in rect64 () eingeschlossene Zahl ist eine 64-Bit-Hexadezimalzahl.

  • Teilen Sie das in vier 16-Bit-Zahlen auf.
  • Teilen Sie jeweils durch die maximal nicht signierte 16-Bit-Zahl (65535) und Sie haben vier Zahlen zwischen 0 und 1.
  • Die vier verbleibenden Zahlen geben Ihnen relative Koordinaten für das Gesichtsrechteck: (links, oben, rechts, unten).
  • Wenn Sie mit absoluten Koordinaten enden möchten, sind Sie links und rechts durch die Bildbreite und die obere und unten nach der Bildhöhe.

Mein Code, um dies in ein Rechteck zu verwandeln, funktioniert einwandfrei (nur relative Koordinaten):

    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);
    }

Jetzt habe ich ein Rechteck und möchte ihn wieder in den oben genannten Hash verwandeln. Ich kann das nicht herausfinden. Es sieht so aus, als ob Picasa 2 Bytes einschließlich Präzision verwendet. Ein Float in C# ist jedoch 8 Bytes und sogar BitConverter.

Jede Hilfe geschätzt.

EDIT: Hier ist was ich gerade habe

    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();
    }
War es hilfreich?

Lösung

Ihr aktueller Code tauscht die Bytes jeder Koordinate aus. Dies liegt daran, dass BitConverter Ihnen die Bytes in wenig endianischer Reihenfolge gibt (dh das erste Byte im Array ist das am wenigsten bedeutende Byte). Wenn Sie Ihre Aufgaben wie folgt austauschen, wird das Dekodieren und Neukodieren des ursprünglichen Hash zurückgegeben.

        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];

Das heißt, ich denke, es ist klarer, die Konvertierung mit einfachen Multiplikationen und Adds durchzuführen. Sie können mit der Dekodierung der Hash -Zeichenfolge etwas Ähnliches tun, wenn Sie sie als Single lesen ulong und subtrahieren/dividieren. zB für die Codierung:

    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");
    }

Andere Tipps

Es sieht so aus, als müssten Sie die Schwimmertypen von HashfromRectangle (rect) wie SO herausnehmen:

    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);

Außerdem kann es lesbarer sein, dies zum Ausfüllen des Arrays zu verwenden:

    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);

Lassen Sie mich wissen, ob das funktioniert!

Aaron

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top