2008-09-18 3 views
1

вопрос на C# (.net 3.5). У меня есть класс ImageData, который имеет поле ushort [,] пикселей. Я имею дело с проприетарными форматами изображений. Класс ImageData принимает местоположение файла в конструкторе, затем включает расширение файла, чтобы определить, как декодировать. В нескольких файлах изображений в заголовке есть поле «бит глубина». После декодирования заголовка я считываю значения пикселей в массив «пикселей». Пока у меня не было больше 16bpp, так что я в порядке. Но что, если у меня 32bpp?проблема с C# 'generic'

Что я хочу сделать, так это определить тип пикселей во время выполнения. Я хочу сделать это после того, как прочитаю битовую глубину из заголовка и до того, как скопирую данные пикселя в память. Есть идеи?

ответ

1

сводиться вашу проблему, вы хотите быть в состоянии иметь класс, который имеет UShort [,] пикселей поле (16 бит на пиксель), иногда и UInt32 [,] пикселей поле (32 -бит на пиксель) в другое время. Есть несколько способов добиться этого.

Вы можете создать замену для ushort/uint32, создав класс Pixel с 32-разрядными и 16-разрядными подклассами, переопределив различные операторы вверх по wazoo, но это навлечет много накладных расходов, сложно получить право и даже сложнее определить, является ли его право. В качестве альтернативы вы можете создавать классы прокси для ваших пиксельных данных (которые будут содержать массивы ushort [,] или uint32 [,] и будут полезны все необходимые аксессоры). Недостатком является то, что в классе ImageData вы, скорее всего, получите множество специальных кодов кода, которые выполняются так или иначе в зависимости от того, какой флаг 16-битного/32-битного режима.

Лучшее решение, я думаю, было бы для подкласса ImageData в 16-битных и 32-разрядных классах и использовать фабричный метод для создания экземпляров. Например. ImageData - это базовый класс, ImageData16bpp и ImageData32bpp - это подклассы, статический метод ImageData.Create (string imageFilename) - это фабричный метод, который создает либо ImageData16bpp, либо ImageData32bpp в зависимости от данных заголовка. Например:

public static ImageData Create(string imageFilename) 
{ 
    // ... 
    ImageDataHeader imageHeader = ParseHeader(imageFilename); 
    ImageData newImageData; 
    if (imageHeader.bpp == 32) 
    { 
     newImageData = new ImageData32(imageFilename, imageHeader); 
    } 
    else 
    { 
     newImageData = new ImageData16(imageFilename, imageHeader); 
    } 
    // ... 
    return newImageData; 
} 
2

Я бы сказал, что не нужно делать эту работу в конструкторе. Конструктор не должен делать так много работы, на мой взгляд. Используйте фабричный метод, который читает файл для определения глубины бита, а затем построит правильный общий вариант класса и вернет его.

0

Попросите функцию декодирования вернуть объект типа Array, который является базовым классом всех массивов. Тогда люди, которые заботятся о типе, могут делать «if (a is ushort [,])» и так далее, если они хотят пройти через пиксели. Если вы сделаете это так, вам нужно выделить массив в ImageData, а не наоборот.

В качестве альтернативы, вызывающий абонент, вероятно, знает, какие пиксельные массивы они хотят использовать. Даже если это изображение 8bpp или 16bpp, если вы декодируете его на 32-битный экран, вам нужно использовать uint вместо ushort. Таким образом, вы можете написать функцию ImageData, которая будет декодироваться в целые числа любого типа T.

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