Преобразование RGB в оттенки серого с помощью неона руки

Я пытаюсь эффективно преобразовать rgb в оттенки серого, поэтому я получил функцию от здесь, где объясняется, как преобразовать rgba в оттенки серого. Теперь я пытаюсь сделать то же самое, но только с rgb. Я изменил некоторые вещи, но, похоже, это не работает должным образом. Я не знаю почему, кто-нибудь видит мою ошибку?

void neon_asm_convert(uint8_t * __restrict dest, uint8_t * __restrict src, int numPixels)
{
    __asm__ volatile(
     "lsr %2, %2, #3 \n"
     "# build the three constants:  \n"
     "mov r4, #28                   \n" // Blue channel multiplier
     "mov r5, #151                  \n" // Green channel multiplier
     "mov r6, #77                   \n" // Red channel multiplier
     "vdup.8 d4, r4                 \n"
     "vdup.8 d5, r5                 \n"
     "vdup.8 d6, r6                 \n"
     "0: \n"
     "# load 8 pixels: \n"  //RGBR
     "vld4.8 {d0-d3}, [%1]! \n"
     "# do the weight average: \n"
     "vmull.u8 q7, d0, d4 \n"
     "vmlal.u8 q7, d1, d5 \n"
     "vmlal.u8 q7, d2, d6 \n"
     "# shift and store: \n"
     "vshrn.u16 d7, q7, #8 \n" // Divide q3 by 256 and store in the d7
     "vst1.8 {d7}, [%0]! \n"
     "subs %2, %2, #1 \n" // Decrement iteration count

     "# load 8 pixels: \n"
     "vld4.8 {d8-d11}, [%1]! \n" //Other GBRG
     "# do the weight average: \n"
     "vmull.u8 q7, d3, d4 \n"
     "vmlal.u8 q7, d8, d5 \n"
     "vmlal.u8 q7, d9, d6 \n"
     "# shift and store: \n"
     "vshrn.u16 d7, q7, #8 \n" // Divide q3 by 256 and store in the d7
     "vst1.8 {d7}, [%0]! \n"
     "subs %2, %2, #1 \n" // Decrement iteration count

     "# load 8 pixels: \n"
     "vld4.8 {d0-d3}, [%1]! \n"
     "# do the weight average: \n"
     "vmull.u8 q7, d10, d4 \n"
     "vmlal.u8 q7, d11, d5 \n"
     "vmlal.u8 q7, d0, d6 \n"
     "# shift and store: \n"
     "vshrn.u16 d7, q7, #8 \n" // Divide q3 by 256 and store in the d7
     "vst1.8 {d7}, [%0]! \n"
     "subs %2, %2, #1 \n" // Decrement iteration count


     "# do the weight average: \n"
     "vmull.u8 q7, d1, d4 \n"
     "vmlal.u8 q7, d2, d5 \n"
     "vmlal.u8 q7, d3, d6 \n"
     "# shift and store: \n"
     "vshrn.u16 d7, q7, #8 \n" // Divide q3 by 256 and store in the d7
     "vst1.8 {d7}, [%0]! \n"

     "subs %2, %2, #1 \n" // Decrement iteration count



     "bne 0b \n" // Repeat unil iteration count is not zero
     :
     : "r"(dest), "r"(src), "r"(numPixels)
     : "r4", "r5", "r6"
    );
}

person Gustavo    schedule 14.12.2011    source источник
comment
Изображение плохо трансформировалось.   -  person Gustavo    schedule 14.12.2011
comment
Скриншоты или что?   -  person Prof. Falken    schedule 14.12.2011


Ответы (3)


Вы загружаете четыре значения (RGBA) вместо трех (RGB).

у вас есть RGB RGB RGB в вашем изображении, но вы загружаете RGBR GBRG B... и т. д. в последовательных шагах.

"vld4.8 {d0-d3}, [%1]! \n"

Вместо этого вы должны

"vld3.8 {d0-d2}, [%1]! \n"

Обратите внимание, что я понятия не имею, правильный ли мой asm, но вот ошибка. Также проверьте ту же ошибку при перемещении пикселей обратно в память.

person Sam    schedule 14.12.2011
comment
Я уже принял во внимание, что я получаю в четыре раза больше вектора из источника, поэтому я могу конвертировать кратно. Я получаю RGBR / GBRG / BRGB и каждый раз преобразую это - person Gustavo; 14.12.2011
comment
Что вы делаете, так это загружаете RGBR, конвертируете RGB в оттенки серого и игнорируете второй R, затем загружаете GBRB, обрабатываете GBR как RGB (неправильно!), игнорируете последний B и снова... Итак, вы игнорируете некоторые пиксели и загружаете неправильные каналы каждый шаг. - person Sam; 14.12.2011

Вы должны использовать "vld3.8 {d0-d2}, [%1]! \n"

См. также http://hilbert-space.de/?p=22.

person auselen    schedule 22.01.2012
comment
Добро пожаловать в Stack Overflow! Хотя теоретически это может ответить на вопрос, было бы предпочтительнее включить сюда основные части ответа и предоставить ссылку для справки. - person Michael Myers; 22.01.2012

Василе прав. Используйте VLD3 для загрузки 24-битных пикселей.

У вас также есть 3 VLDx для 4 VSTx На самом деле ваш код довольно странный...

Вам не нужно дублировать код. Это довольно сложно объяснить, но вам не будет интересно с NEON повторять 4 раза ваш код.

void neon_asm_convert(uint8_t * __restrict dest, uint8_t * __restrict src, int numPixels)
{
  __asm__ volatile(
   "# build the three constants:  \n"
   "mov r4, #28                   \n" // Blue channel multiplier
   "mov r5, #151                  \n" // Green channel multiplier
   "mov r6, #77                   \n" // Red channel multiplier
   "vdup.8 d4, r4                 \n"
   "vdup.8 d5, r5                 \n"
   "vdup.8 d6, r6                 \n"

   "0: \n"
   "# load 8 pixels: \n"  //RGBR
   "vld3.8 {d0-d2}, [%1]! \n"
   "# do the weight average: \n"
   "vmull.u8 q7, d0, d4 \n"
   "vmlal.u8 q7, d1, d5 \n"
   "vmlal.u8 q7, d2, d6 \n"
   "# shift and store: \n"
   "vshrn.u16 d7, q7, #8 \n" // Divide q3 by 256 and store in the d7
   "vst1.8 {d7}, [%0]! \n"
   "subs %2, %2, #1 \n" // Decrement iteration count
   "bne 0b \n" // Repeat unil iteration count is not zero
   :
   : "r"(dest), "r"(src), "r"(numPixels)
   : "r4", "r5", "r6"
  );
}

Должно работать.

person webshaker    schedule 14.12.2011
comment
Выглядит хорошо, но выдает ошибку доступа к памяти, также я думаю, что вы забыли эту строку в начале функции: lsr %2, %2, #3 \n - person Gustavo; 15.12.2011
comment
да, это правильно или заменить подписи %2, %2, #1 на подписи %2, %2, #8 - person webshaker; 15.12.2011