boost :: gil указатель на объект bgr8_view_t - PullRequest
2 голосов
/ 04 февраля 2012

Я хочу написать функцию для преобразования BGRA в BGR. void convertBGRAViewtoBGRView( const boost::gil::bgra8_view_t &src, boost::gil::bgr8_view_t dst ) Если я напишу это так:

size_t numPixels = src.width() * src.height();
boost::gil::bgra8_view_t::iterator it = src.begin();
boost::gil::bgr8_view_t::iterator itD = dst.begin();
for( int i = 0; i < numPixels; ++i ){

    boost::gil::bgra8_pixel_t pixe(it[0]);
    *it++;
    boost::gil::bgr8_pixel_t pix(pixe[0],pixe[1],pixe[2]);

    *itD++ = pix;        
}

это работает, но очень медленно. Поэтому я хочу использовать инструкции NEON и, следовательно, мне нужен указатель, например (UInt8 *) или (UInt32 *). Я попробовал это так:

UInt32 *temp = (UInt32*)&src(0,0);
for( int i = 0; i < numPixels; ++i ){        
    boost::gil::bgr8_pixel_t pixk( (( *temp) & 0xff), ( (*temp>>8) & 0xff), ((*temp >> 16 )& 0xff));
    *itD++ = pixk;
    temp += 1;
}

Это работает более или менее, но полученное изображение не является правильным. Я думаю, может быть, проблема с выравниванием. У кого-нибудь есть идеи, как заставить его работать? Это решение примерно в 3 раза быстрее, чем решение с итератором.

UPDATE: Я проверил с помощью отладчика: src имеет ширину 480x360 и до i == 259 все верно, но после слов решение с итератором и указателем отличается.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 06 февраля 2012

После некоторых вычислений, основанных на вашем ответе, я обнаружил, что 360*4 делится на что угодно до 32, тогда как 360*4+8*4 даже делится на 64. Поэтому я предполагаю, что причина ошибки в том, что GIL в вашем случае пытается выровнять строки изображения на 64-байтовых границах и поэтому не сохраняет их непрерывно.

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

0 голосов
/ 06 февраля 2012

ОК, я нашел, как это исправить, но до сих пор не знаю причину :) Это работает для изображений с шириной 360 в моем случае.

UInt32 *temp = (UInt32*)&src(0,0);
for( int i = 0; i < numPixels; ++i ){   
  if( i%360==0 && i!=0 ){
    temp += 8;
  }
  boost::gil::bgr8_pixel_t pixk( (( *temp) & 0xff), ( (*temp>>8) & 0xff), ((*temp >> 16 )& 0xff));
  *itD++ = pixk;
  temp += 1;
}

Еще лучше использовать это для платформы iOS:

UInt8 *temp = (UInt8*)&src(0,0);
for( int i = 0; i < numPixels; ++i ){   
  if( i%360==0 && i!=0 ){
    temp += 8*4;
  }
  boost::gil::bgr8_pixel_t pixk( *temp, *(temp+1), *(temp+2));
  *itD++ = pixk;
  temp += 4;
}

Избавление от другого итератора еще больше повышает скорость (протестировано на iOS).

...