2010-02-04 2 views
4

다음은 Picasa가 해시로 저장하는 항목에 대한 세부 정보입니다. 그것은이처럼 저장 :RectangleF를 Picasa 얼굴 해시로 바꾸는 방법

rect64 쌌다 수는() 64 비트 16 진수입니다 : 웹

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

정보이 말했다.

  • 4 개의 16 비트 숫자로 나눕니다.
  • 최대 부호없는 16 비트 숫자 (65535)로 나누면 0과 1 사이에 네 개의 숫자가 나옵니다.
  • 네 개의 숫자로 얼굴 사각형의 상대 좌표를 얻을 수 있습니다 : (왼쪽, 위, 오른쪽 , 하단).
  • 절대 좌표로 끝내려면 왼쪽과 오른쪽을 이미지 너비로, 위쪽과 아래쪽을 이미지 높이로 곱하십시오.
    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); 
        } 
    

    지금 나는 RectangleF하고 난 다시 위에서 언급 한 해시로 돌려하려면 :

그래서 RectangleF가 (만 상대 좌표를 유지) 잘 작동에 내 코드는 전원을 켭니다. 나는 이것을 알아낼 수 없다. picasa는 정밀도를 포함하여 2 바이트를 사용하지만 C#의 float는 8 바이트이고 BitConverter.ToSingle조차도 4 바이트입니다.

도움을 주시면 감사하겠습니다.

편집 : 여기에 내가 지금 무엇을 당신이과 같이 HashFromRectangle (RECT)에서 플로트 형식을 취할 필요 것 같습니다

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(); 
    } 
+0

, 당신은 대신 짧은으로 변환을 시도 할 수 . 변환이 명시 적이어야합니다 (http://msdn.microsoft.com/en-us/library/ybs77ex4%28VS.71%29.aspx). 그렇지 않으면 컴파일러에서 오류가 발생합니다. – keyboardP

+0

나는 그것을 시도했지만, 내 해시가 같은 곳 근처에서 돌지 않고있다.위의 코드를 게시하여 내가 분명히 잘못된 것을하고 있는지 확인합니다. – esac

답변

1

현재 코드가 각 좌표의 바이트를 서로 바꿉니다. 이것은 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으로 읽고 빼기/나누기 만하면 해시 문자열의 해독과 비슷한 작업을 수행 할 수 있습니다. 예 : 인코딩을 위해 : (C# http://www.techotopia.com/index.php/C_Sharp_Variables_and_Constants에서) 2 바이트 부동 소수점 데이터 유형이없는 것처럼

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

감사합니다. 약간의 정확도를 잃어 버리는 것 같지만 올바르게 처리됩니다. – esac

0

: 또한

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

내가 작동하는지 알려주세요.

아론

+0

불행히도 아닙니다. 나는 이것을 1cf0102160008916의 알려진 해시에서 테스트했습니다. 해시가 ff2983393f520976으로 바뀌고 잘못된 좌표로 바뀝니다. – esac