Что означает «без знака по модулю 256» в контексте декодирования изображения - PullRequest
3 голосов
/ 22 апреля 2011

Поскольку я мазохист, я пытаюсь написать что-то на C, чтобы декодировать 8-битный файл PNG (это учебная вещь, я не пытаюсь изобретать libpng ...)

IДошло до того, что материал в моем дефлированном, нефильтрованном буфере данных безошибочно напоминает исходное изображение (см. ниже), но он все еще довольно ошибочен, и я почти уверен, что с моей реализацией * что-то искажается1003 * алгоритмы фильтрации .Большинство из них довольно просты, но есть одна важная вещь, которую я не понимаю в документах : не очень хорошо разбираться в математике или когда-либо проходить курс компьютерной науки:

Используется арифметика без знака по модулю 256, так что и входы, и выходы помещаются в байты.

Что это значит ?

Если кто-то может сказать мнечто я был бы очень благодарен!

Для справки (и я извиняюсь за дерьмовый C) моя неряшливая реализация алгоритмов фильтрации, описанных в документах , выглядит как :

unsigned char paeth_predictor (unsigned char a, unsigned char b, unsigned char c) {
    // a = left, b = above, c = upper left
    char p = a + b - c; //  initial estimate
    char pa = abs(p - a);    //  distances to a, b, c
    char pb = abs(p - b);
    char pc = abs(p - c);
    // return nearest of a,b,c,
    // breaking ties in order a,b,c.
    if (pa <= pb && pa <= pc) return a;
    else if (pb <= pc) return b;
    else return c;
}

void unfilter_sub(char* out, char* in, int bpp, int row, int rowlen) {
    for (int i = 0; i < rowlen; i++)
        out[i] = in[i] + (i < bpp ? 0 : out[i-bpp]);
}

void unfilter_up(char* out, char* in, int bpp, int row, int rowlen) {
    for (int i = 0; i < rowlen; i++)
        out[i] = in[i] + (row == 0 ? 0 : out[i-rowlen]);
}

void unfilter_paeth(char* out, char* in, int bpp, int row, int rowlen) {
    char a, b, c;
    for (int i = 0; i < rowlen; i++) {
        a = i < bpp ? 0 : out[i - bpp];
        b = row < 1 ? 0 : out[i - rowlen];
        c = i < bpp ? 0 : (row == 0 ? 0 : out[i - rowlen - bpp]);
        out[i] = in[i] + paeth_predictor(a, b, c);
    }
}              

И изображения, которые я вижу:

Источник

Источник http://img220.imageshack.us/img220/8111/testdn.png

Выход

Выход http://img862.imageshack.us/img862/2963/helloworld.png

Ответы [ 3 ]

6 голосов
/ 22 апреля 2011

Это означает, что в алгоритме всякий раз, когда выполняется арифметическая операция, она выполняется по модулю 256 , т. Е. Если результат больше 256, то он "оборачивается" вокруг, В результате все значения всегда помещаются в 8 бит и не переполняются.

Беззнаковые типы уже ведут себя таким образом по мандату , и если вы используете unsigned char (а байт в вашей системе равен 8 битам, что, вероятно, так и есть), то ваши результаты вычислений, естественно, никогда не будут переполнение за пределы 8 бит.

1 голос
/ 22 апреля 2011

Это означает, что используются только последние 8 битов результата.2 ^ 8 = 256, последние 8 битов беззнакового значения v совпадают с (v% 256).

Например, 2 + 255 = 257 или 100000001, последние 8 бит из 257 равны 1,и 257% 256 тоже 1.

0 голосов
/ 20 октября 2017

В «простом языке» это означает, что вы никогда не выходите «из» своего размера байта.

Например, в C #, если вы попытаетесь это сделать, это не удастся:

byte test = 255 + 255;

(1,13): ошибка CS0031: постоянное значение «510» не может быть преобразовано в 'Байт'

byte test = (byte)(255 + 255);

(1,13): ошибка CS0221: постоянное значение «510» не может быть преобразовано в 'byte' (используйте синтаксис unchecked для переопределения)

Для каждого вычисления вы должны сделать по модулю 256 (C #:% 256). Вместо записи % 256 вы также можете сделать И 255 :

(175 + 205) mod 256 = (175 + 205) AND 255

Некоторые образцы C #:

byte test = ((255 + 255) % 256);
// test: 254
byte test = ((255 + 255) & 255);
// test: 254
byte test = ((1 + 379) % 256);
// test: 124
byte test = ((1 + 379) & 0xFF);
// test: 124

Обратите внимание, что иногда вы можете упростить серию байтов:

(byteVal1 + byteVal2 + byteVal3) % 256
= (((byteVal1 % 256) + (byteVal2 % 256)) % 256 + (byteVal3 % 256)) % 256
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...