Поддержка нескольких форматов пикселей - PullRequest
0 голосов
/ 09 сентября 2010

Мне нужно написать некоторый код, который будет работать с рядом форматов пикселей (например, A8R8G8B8, R8G8B8, R5G6B6 и даже потенциально с плавающей запятой).

В идеале я бы не хотел писать каждыйфункция для каждого формата, поскольку это огромное количество практически идентичного кода.

Единственное, о чем я мог подумать, это какой-то интерфейс, позволяющий ему работать с преобразованиями в пиксельных форматах, например:

class IBitmap
{
public:
    virtual unsigned getPixel(unsigned x, unsigned y)const=0;
    virtual void setPixel(unsigned x, unsigned y, unsigned argb)=0;
    virtual unsigned getWidth()const=0;
    virtual unsigned getHeight()const=0;
};

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

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

Ответы [ 5 ]

1 голос
/ 09 сентября 2010

Рассмотрите возможность использования шаблонов. Это позволит вам писать, где это возможно, в общем случае и использовать для специализации код во время компиляции.

Иногда известный как статический полиморфизм. http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern

0 голосов
/ 09 июля 2011

Затраты на преобразование всего в один общий формат и последующее преобразование после операции могут быть меньше, чем вы думаете.Если вы можете ограничить количество пикселей, которые конвертируются за раз, скажем, до одной строки, промежуточные результаты могут оставаться в кэше для всей операции.Я действительно видел случай, когда сквозные времена были быстрее с использованием этого подхода, хотя он включал однобитовые пиксели, с которыми по сути сложно работать, когда они все еще упакованы.* Вы правы, опасаясь вызова функции на уровне пикселей.Я никогда не видел случая, чтобы функция пикселя не делала обработку неприемлемо медленной.

0 голосов
/ 09 июля 2011

(Это мой новый ответ, потому что после обширных исследований я пришел к выводу, что Adobe GIL не подходит для этой цели.)

Я очень рекомендую архитектуру и дизайн интерфейса Windows Imaging Component.

Что я имею в виду:

  • Их интерфейс - то, что я рекомендую. Не реализация.
    • Каждый может реализовать нечто подобное. Фактически, Mono Project (Wine) содержит частичную реализацию WIC.
  • Вместо модели производитель-потребитель WIC использует модель конвейерного хранения.
    • Битовая карта только для чтения реализует IWICBitmapSource интерфейс
      • Есть только 5 методов-членов.
    • Печатное растровое изображение реализует IWICBitmap интерфейс и обеспечивает прямой доступ к памяти для чтения / записи данных пикселей.
      • В дополнение к IWICBitmapSource есть только 3 дополнительных метода-члена.
      • Наличие класса «storage» означает, что этот класс не зависит ни от каких других экземпляров растрового изображения при создании значений пикселей.
0 голосов
/ 09 сентября 2010

Чтобы избежать необходимости загружать множество форматов, напишите класс Color или аналогичный, который всегда хранит определенный формат (например, A8R8G8B8 или A32R32G32B32F), затем используйте методы для этого класса для извлечения в различных форматах, например.get(FORMAT_R5G6B6) или аналогичный.Все ваши методы могут иметь дело с этим классом.Когда это возможно, преобразуйте цвет только один раз (например, при рисовании прямоугольника преобразуйте цвет прямоугольника в формат назначения, а затем запишите его во все пиксели - не конвертируйте его для каждого пикселя!).

Избегатьимеющий метод SetPixel / GetPixel вообще.Это невозможно сделать эффективно, особенно если вы выполняете преобразование цветов на лету, особенно если оптимизатор решает не выполнять вызовы.Вы бы лучше выставляли буферы памяти напрямую и верили, что вызывающая сторона будет правильно использовать память.Вот как это делает любой другой API, который я использовал раньше.

0 голосов
/ 09 сентября 2010

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

...