none
Как вычисляется Checksum в структуре WmfPlaceableFileHeader RRS feed

  • Вопрос

  • Здравствуйте.

    Помогите с алгоритмом вычисления контрольной суммы.

    Имеется структура WmfPlaceableFileHeader:

    typedef struct {
      UINT32     Key;
      INT16      Hmf;
      PWMFRect16 BoundingBox;
      INT16      Inch;
      UINT32     Reserved;
      INT16      Checksum;
    } WmfPlaceableFileHeader;

    В документации написано:

    Checksum Type: INT16 Checksum for the previous 10 WORDs in the header. This value can be used to determine whether the metafile has

    become corrupted.

    Вот реальный заголовок (взятый из wmf-файла) :

    D7 CD C6 9A 00 00 00 00 00 00 B2 16 B2 16 B0 04 00 00 00 00 A1 53

    Как же вычисляется контрольная сумма (A1 53)? Пробовал  CRC16/32, Checksum из WinHex - не совпадает.

    Заранее спасибо.

    22 апреля 2020 г. 19:05

Все ответы

  • Похоже на обычное побитовое исключающие или.
    22 апреля 2020 г. 21:15
  • The checksum is calculated by joining each WORD value to an initial value of 0 by using the XOR operator.

    https://docs.microsoft.com/en-us/dotnet/api/system.drawing.imaging.wmfplaceablefileheader.checksum?view=netframework-4.8#System_Drawing_Imaging_WmfPlaceableFileHeader_Checksum


    This posting is provided "AS IS" with no warranties, and confers no rights.

    22 апреля 2020 г. 22:00
    Модератор
  • Спасибо за ответы, даже нашёл работающий пример:

          byte[] arr = { 215, 205, 198, 154, 0, 0, 0, 0, 0, 0, 178, 22, 178, 22, 176, 4, 0, 0, 0, 0};
          // D7 CD C6 9A 00 00 00 00 00 00 B2 16 B2 16 B0 04 00 00 00 00   A1 53
          // 53A1 = 21409
          ushort checksum = 0;
          for (int i = 0; i < 10; i++) {
              checksum ^= BitConverter.ToUInt16(arr, i * 2);
          }
          // checksum = 21409
    C# не знаю, а можно ли посмотреть реализацию метода BitConverter.ToUInt16 на C, VB или псевдокоде?

    23 апреля 2020 г. 11:42
  • Спасибо за ответы, даже нашёл работающий пример:

          byte[] arr = { 215, 205, 198, 154, 0, 0, 0, 0, 0, 0, 178, 22, 178, 22, 176, 4, 0, 0, 0, 0};
          // D7 CD C6 9A 00 00 00 00 00 00 B2 16 B2 16 B0 04 00 00 00 00   A1 53
          // 53A1 = 21409
          ushort checksum = 0;
          for (int i = 0; i < 10; i++) {
              checksum ^= BitConverter.ToUInt16(arr, i * 2);
          }
          // checksum = 21409
    C# не знаю, а можно ли посмотреть реализацию метода BitConverter.ToUInt16 на C, VB или псевдокоде?

    Это просто каст на 16 битное целое. Иными словами, берете указатель на структуру, кастите его в указатель на 16 битные целые и в цикле ксорите их. Проще наверное не бывает. :)

    This posting is provided "AS IS" with no warranties, and confers no rights.

    23 апреля 2020 г. 22:18
    Модератор
  • Разобрался, не так сложно, получилось вот такое:

            ushort checksum = 0;
            for (int i = 0; i < 20; i+=2) {
                checksum ^= (ushort) (arr[i] + (arr[i+1] << 8));
            }

    Всем спасибо.



    24 апреля 2020 г. 13:55