Вопрос контроля подписи OpenNETCF - PullRequest
3 голосов
/ 17 апреля 2010

Я использую элемент управления Signature в OpenNETCF. Это прекрасно работает для большинства всего, что мне нужно.

Однако мне нужен способ инвертировать подпись и загрузить ее обратно.

Имеется вызов для получения "байтов" для подписи (GetSignatureEx()). Возвращает byte[] подписи. Эта подпись затем может быть загружена обратно с помощью LoadSignatureEx().

Я не могу понять систему для этих байтов. Я думал, что они могут быть координатами, но сейчас это не так.

Если кто-нибудь знает способ инвертировать подпись и загрузить ее обратно, я был бы рад услышать это.


Примечание для тех, кому это небезразлично:

Кажется, что эти байты имеют следующую структуру (по порядку):

2 bytes to show Width  
2 bytes to show Height  
  -- This next part repeats till the end of the array  
  2 bytes to show How many points are in the next line  
    -- This next part repeats as many times as the previous line indicated  
    1 byte for the x coordinate of the point  
    1 byte for the y coordinate of the point  
    2 bytes for the width of the pen (I am not 100% sure on this one)  

Я опубликую свой окончательный код, как только я это сделаю.


Позже Примечание: Хорошо, после огромного количества работы, я обнаружил, как легко перевернуть изображение, используя встроенный материал (спасибо MusiGenesis). Мне кажется, что этот процесс гораздо менее подвержен ошибкам.

На всякий случай, если кто-то еще захочет, вот мой незаконченный код. (Я был близок, но материал для перехода к следующей «строке» работает не совсем правильно.) (РЕДАКТИРОВАТЬ: Я решил, что мне больше понравилось, как это работает. работать до тех пор, пока ширина или высота элемента управления Signature не превышает 256. (См. ответ ctacke ниже).

Но сначала большое спасибо MusiGenesis, который помог мне разобраться во всем этом. Вы очень полезны, и я очень ценю ваши усилия!

Теперь код:

private void InvertSignature(ref byte[] original)
{
    int currentIndex = 0;
    short width = BitConverter.ToInt16(original, 0);
    short height = BitConverter.ToInt16(original, 2);
    while (currentIndex < original.Length - 4)
    {
        // Move past the last iteration (or the width and hight for the first time through).
        currentIndex += 4;
        // Find the length of the next segment.
        short nextGroup = BitConverter.ToInt16(original, currentIndex);
        //Advance one so we get past the 2 byte group
        currentIndex += 2;
        // Find the actual index of the last set of coordinates for this segment.
        int nextNumberOfItems = ((nextGroup) * 4) + currentIndex;
        // Invert the coordinates
        for (int i = currentIndex; i < (nextNumberOfItems - 1); i += 4)
        {
            currentIndex = i;

            //Invert Horizontal
            int newHorzPoint = width - original[i] - 1;
            if (newHorzPoint <= 0)
                newHorzPoint = 0;
            else if (newHorzPoint >= width - 1)
                newHorzPoint = width - 1;
            original[i] = (byte)newHorzPoint;

            // Invert Vertical
            int newVertPoint = height - original[i + 1] - 1;
            if (newVertPoint <= 0)
                newVertPoint = 0;
            else if (newVertPoint >= height - 1)
                newVertPoint = height - 1;
            original[i + 1] = (byte)newVertPoint;
        }
    }
}

Ответы [ 2 ]

3 голосов
/ 19 апреля 2010

Возможно, я немного опоздал, но сейчас я смотрю на код, и вот некоторые моменты, на которые стоит обратить внимание.

  • Первые 2 байта являются шириной.
  • Следующие 2 байта - это высота.
  • Остальные данные представляют собой координаты X, Y, однако формат хранения обманчив и может измениться. Если размерность (x или y) <256, мы используем один байт для хранения значения. Если оно больше, мы используем 2 байта. Это означает, что вы можете увидеть вейлы, хранящиеся как XYXY, XXYXXY или XYYXYY. </li>
2 голосов
/ 17 апреля 2010

Полностью непроверенный код Гольф:

public void InvertSignature(ref byte[] original, 
    bool invertHorizontal, bool invertVertical)
{
    for (int i = 0; i < original.Length; i += 2)
    {
        if ((original[i] != 0) && (original[i + 1] != 0))
        {
            if (invertHorizontal)
            {
                original[i] = 232 - original[i] - 1;
            }
            if (invertVertical)
            {
                original[i + 1] = 64 - original[i + 1] - 1;
            }
        }
    }
}

Или попробуйте эту версию, исходя из предположения, что первые 4 байта используются для хранения ширины и высоты подписи (2 байта коротких целых для каждого):

public void InvertSignature(ref byte[] original, 
    bool invertHorizontal, bool invertVertical)
{
    byte w = (byte)BitConverter.ToInt16(original, 0) - 1;
    byte h = (byte)BitConverter.ToInt16(original, 2) - 1;
    // TO DO: blow up if w or h are > 255
    for (int i = 4; i < original.Length; i += 2)
    {
        if ((original[i] != 0) && (original[i + 1] != 0))
        {
            if (invertHorizontal)
            {
                original[i] = w - original[i];
            }
            if (invertVertical)
            {
                original[i + 1] = h - original[i + 1];
            }
        }
    }
}

См .: Преобразование OpenNetCF GetSignatureEx в растровое изображение на рабочем столе

Обновление: Учитывая ваше описание того, почему вам нужно инвертировать подпись, вам может быть проще просто инвертировать ScreenOrientation вашего устройства на 180 градусов (а затем обратно после того, как клиент подпишет). Таким образом, у вас также могут быть ярлыки, которые сообщают клиенту о том, что они подписывают, иначе они будут смотреть на кучу перевернутых вещей (кроме самого элемента управления подписью).

Для этого добавьте ссылку на Microsoft.WindowsCE.Forms в ваш проект, затем добавьте using Microsoft.WindowsCE.Forms; в начало вашего файла.

Чтобы перевернуть экран на 180 градусов:

SystemSettings.ScreenOrientation = ScreenOrientation.Angle180;

Чтобы вернуться к обычному режиму:

SystemSettings.ScreenOrientation = ScreenOrientation.Angle0;

Если вы запускаете это в эмуляторе, ваш экран будет по-прежнему нормально выглядеть, но кожа переворачивается вверх ногами.

Обновление: последний выстрел, основанный на ответе ctacke (это должно работать для подписей с любыми измерениями):

public void InvertSignature(ref byte[] original, 
    bool invertHorizontal, bool invertVertical)
{
    short w = BitConverter.ToInt16(original, 0);
    short h = BitConverter.ToInt16(original, 2);
    int i = 4;
    while (i < original.Length)
    {
        if (invertHorizontal)
        {
            if (w < 256)
            {
                if (original[i] != 0)
                {
                    original[i] = (byte)w - original[i] - 1;
                }
                i++;
            }
            else
            {
                short val = BitConverter.ToInt16(original, i);
                if (val != 0)
                {
                    val = w - val - 1;
                    byte[] valbytes = BitConverter.GetBytes(val);
                    Buffer.BlockCopy(valbytes, 0, original, i, 2);
                }
                i += 2;
            }
        }
        else
        {
            i += (w < 256) ? 1 : 2;
        }
        if (invertVertical)
        {
            if (h < 256)
            {
                if (original[i] != 0)
                {
                    original[i] = (byte)h - original[i] - 1;
                }
                i++;
            }
            else
            {
                short val = BitConverter.ToInt16(original, i);
                if (val != 0)
                {
                    val = h - val - 1;
                    byte[] valbytes = BitConverter.GetBytes(val);
                    Buffer.BlockCopy(valbytes, 0, original, i, 2);
                }
                i += 2;
            }
        }
        else
        {
            i += (h < 256) ? 1 : 2;
        }
    }
}
...