문제

다음은 Picasa가 해시로 저장하는 것에 대한 세부 사항입니다. 다음과 같이 저장합니다.

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

웹에 대한 정보는 다음과 같이 말합니다.

rect64 ()에 포함 된 숫자는 64 비트 16 진수입니다.

  • 그것을 4 개의 16 비트 번호로 나눕니다.
  • 각각을 최대 부호없는 16 비트 번호 (65535)로 나누면 0과 1 사이의 4 개의 숫자가 있습니다.
  • 나머지 4 개의 숫자는 얼굴 사각형의 상대 좌표를 제공합니다 : (왼쪽, 상단, 오른쪽, 하단).
  • 절대 좌표로 끝나려면 왼쪽과 오른쪽을 이미지 너비와 이미지 높이로 상단과 하단으로 여러 가지로 끝내십시오.

그래서 그것을 사각형으로 바꾸는 내 코드는 잘 작동합니다 (상대 좌표를 유지하는 것만) :

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

이제 직사각형을 가지고 있으며 위에서 언급 한 해시로 다시 바꾸고 싶습니다. 나는 이것을 알아낼 수없는 것 같다. Picasa는 정밀도를 포함한 2 바이트를 사용하는 것처럼 보이지만 C#의 플로트는 8 바이트이고 Bitconverter.tosingle은 4 바이트입니다.

모든 도움이 감사합니다.

편집 : 여기에 내가 지금 가지고있는 것이 있습니다

    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();
    }
도움이 되었습니까?

해결책

현재 코드는 각 좌표의 바이트를 바꾸는 것입니다. BitConverter가 작은 엔디 언 순서로 바이트를 제공하기 때문입니다 (즉, 배열의 첫 바이트는 가장 중요한 바이트입니다). 다음과 같이 과제를 바꾸면 디코딩 및 재 인코딩이 원래 해시를 돌려줍니다.

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

즉, 간단한 곱셈을 사용하여 변환을 수행하는 것이 더 명확하다고 생각합니다. 해시 스트링의 디코딩으로 비슷한 일을 할 수 있습니다. ulong 그리고 빼기/분열. 예 : 인코딩을위한 :

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

다른 팁

HashfromEctangle (rect)에서 플로트 유형을 꺼내야 할 것 같습니다.

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

또한 배열을 채우기 위해 이것을 사용하는 것이 더 읽기 쉬울 수 있습니다.

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

이것이 작동하는지 알려주세요!

아론

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top