Конференция "Media" » Масштабирование [D7, WinXP]
 
  • dmk © (21.07.09 08:40) [0]
    Привет! При масштабировании изображения с нечетным числом пикселей (как по вертикали, так и по горизонтали) в 2 или 4 раза остаются краевые пикселы, которые тоже надо масштабировать. Например, ширина изображения 103 пикселя, соответственно при масштабе в 2 раза остается 3 необработанных пикселя. Как их лучше уменьшить в 2 раза?
    Нужно ли выравнивать изображение до кратного 2 или 4?
    И сколько пикселей (из тех 3) надо отобразить в отмасштабированном изображении при уменьшении в 2 раза?
  • Сергей М. © (21.07.09 23:16) [1]

    > 103 пикселя, соответственно при масштабе в 2 раза остается
    > 3 необработанных пикселя


    Вообще-то 103 mod 2 = 1

    Откуда взялось 3 ?
  • dmk © (22.07.09 10:19) [2]
    Извините за сумбурность мыслей :-)

    Я масштабирую так: из кубика 4х4 пикселя вычисляю среднее арифметическое, соответственно результат является пикселем.
    Результат получается очень хороший, т.к. это напоминает бикубическое масштабирование.
    Соответственно 103 mod 4 = 3.
    Или так: Ср. арифм. из кубика 2х2 пикселя, тогда соответственно может остаться 1 пиксель.

    Вот что делать если остается некратное 4-м или 2-м число пикселей?
    Выравнивать на границу 4-х или 2-х? Или вообще отрезать?

    Если 2 пикселя, то еще можно посчитать среднее арифметическое, а если их остается 3?

    Я пытался понять как это работает на примере фотошопа, но там алгоритм поведения разный, иногда он отрезает, а иногда оставляет. Вот я и думаю — как правильно? Ведь на краю изображения может остаться тонкая линия (например, рамка) и тогда при обрезке она исчезнет.

    В общем мне это нужно для создания миниатюр изображений.
  • Sapersky (22.07.09 11:00) [3]
    Если 2 пикселя, то еще можно посчитать среднее арифметическое, а если их остается 3?

    В большинстве случаев не 3, а 12 (3*4), насколько я понимаю.
    В общем, наверное, если координаты исходного пикселя выходят за границы картинки, нужно брать (м.б. несколько раз) крайний. Все подобные алгоритмы так делают.

    Вот ещё по теме, может, пригодится:
    http://sapersky.narod.ru/files/ResizeTest.rar
  • brother © (22.07.09 11:03) [4]
    а TImage не подходит для банального масштабирования?
  • dmk © (22.07.09 11:34) [5]
    brother ©   (22.07.09 11:03) [4]

    Не-а, у меня свой класс, аналогичный TImage. Делаю для него масштабирование.

    Sapersky   (22.07.09 11:00) [3]

    Буду пробовать, только мне нужно не как у Вас системное, а независимое.
    По любому спасибо за идею :-)
  • Sapersky (22.07.09 11:43) [6]
    Там только StretchBlt системное, просто для сравнения. Остальное независимое.
  • dmk © (22.07.09 11:44) [7]
    Собственно почему проблема возникла, у меня скан-линия выравнена на границу DWORD и используются MMX команды, которые тоже обсчитывают DWORD значения, вот и не знаю, что поместить в последний пиксель,чтобы было правильно.
    Немного кода:

    Procedure MakeOneLineCMYK_MMX(SrcAddr, DestAddr, ScLen:DWord; PShift:DWord; OrgScLen:DWord);
    asm
           push    esi
           push    edi

           mov     esi, SrcAddr            //esi -> Исходный адрес
           mov     edi, DestAddr           //edi -> Конечный адрес
           //mov     ecx, ScLen              //длина скан-линии уже в ECX
           mov     edx, PShift             //размер пикселя в байтах
           xor     eax, eax

    @@nP:  movd    mm0,[esi]               //Левый верхний пиксел
           movd    mm2,[edx+esi]           //Правый верхний пиксел

           movd    mm4, esi
           add     esi,OrgScLen            //Смещаемся на оригинальную ширину ScanLineLen
                                           //для чтения следующей строки пикселей
           movd    mm3,[esi]               //Левый нижний пиксел
           movd    mm1,[edx+esi]           //Правый нижний пиксел

           pavgb   mm0,mm1                 //  Среднее арифметическое
           pavgb   mm2,mm3                 //  Среднее арифметическое
           pavgb   mm0,mm2                 //  Среднее арифметическое

           movd    eax,mm0
           mov     [edi], eax              //Записывем результат

           add     edi, edx                //Смещаемся в конечной линии к следующему пикселю
           movd    esi, mm4                //Восстановим ESI для обработки следующих пикселей
           add     esi, edx                //Сместимся в исходном адресе 2 раза,
           add     esi, edx                //так как исходных пикселей всегда 2

           loop    @@nP

           pop     edi
           pop     esi
    end;
  • Sapersky (22.07.09 12:48) [8]
    Примерно так:
    1) Добавить к параметрам SrcImgWidth
    2) В начале push ecx
    3) В конце
     pop ecx
     add ecx, ecx // * 2
     cmp ecx, SrcImgWidth
     je @Exit // if ecx = SrcImgWidth - выходим
    @ProcLastPixel:
     movd mm0,[esi] // Левый верхний
     add esi, OrgScLen
     movd mm1,[esi] //Левый нижний
     pavgb mm0,mm1  //  Среднее арифметическое от двух последних
     movd [edi], mm0 // вроде так можно
    @Exit:

    По вертикали - для картинок нечётной высоты для последнего ряда OrgScLen = 0, т.е. просто берём одно и то же 2 раза.

    Для 4*4 пикселей, возможно, будет проще написать для "хвостов" отдельную ф-ю на Паскале. Сильно тормозить "хвосты" не должны в силу малого размера.
 
Конференция "Media" » Масштабирование [D7, WinXP]
Есть новые Нет новых   [133926   +462][b:0][p:0]