Обработка Сырых Данных

Для улучшения производительности API Aspose.PSD мы ввели метод обработки сырых данных в версии 2.4.0. Обработка сырых данных теперь используется внутренне и имеет внешнее API, таким образом, она может быть использована за пределами библиотеки для улучшения общей производительности. Иногда обработка может быть немного сложной и требует объяснения. В настоящее время обработка сырых данных доступна только для формата BMP.

Для помощи разработчикам в достижении лучшей производительности API Aspose.PSD предоставляет систему обработки сырых данных с внешним API для настройки. Разработчики вызывают методы LoadRawData и SaveRawData, чтобы использовать обработку сырых данных. Эти методы также требуют установки желаемого формата сырых данных с помощью класса RawDataSettings. Класс RawDataSettings позволяет разработчикам указать любой формат сырых данных. Однако, для достижения наилучшей производительности, необходимо использовать формат сырых данных, в котором данные сохранены. Класс RawDataSettings, определенный в классе RasterImage, помогает определить формат сырых данных изображения. Передавая экземпляр RawDataSettings в метод LoadRawData, данные возвращаются “как есть”, без применения какой-либо конвертации, что может улучшить производительность. С другой стороны, необходимо учитывать все возможные форматы размещения сырых данных, что иногда может быть немного сложным.

Для упрощения процесса обработки, за счет небольшого штрафа в производительности, вы можете указать желаемые настройки RawDataSettings, создав и инициализировав класс с нужными настройками сырых данных. Существуют случаи, когда невозможно вернуть сырые данные в указанном формате (например, конвертация из цветовой модели CMYK в RGB недоступна в версии 2.4.0). Более того, могут быть ситуации, когда обработка сырых данных вообще недоступна для формата изображения. Для определения возможности использования методов семейства LoadRawData и SaveRawData вам необходимо запросить свойство IsRawDataAvailable.

Инсайт

Для формата RGB сырых пиксельных данных доступны индексированные (основанные на палитре) и RGB-основанные форматы сырых данных. Индексированные форматы сырых данных содержат индексы элементов палитры в диапазоне 0..(2^количество бит - 1). Индексированные форматы сырых данных - это форматы 1, 2, 4 и 8 бит на пиксель. Остальные форматы сырых данных основаны на RGB. При загрузке сырых данных убедитесь, что доступно достаточное количество байт для загрузки данных, в противном случае будет сгенерировано соответствующее исключение. Вы можете просто оценить размер массива байт, умножив размер строки на ее количество. Размер строки может варьироваться и зависит от формата хранения сырых данных.

Для достижения наилучшей производительности всегда используйте размер строки сырых данных, равный значению свойства RasterImage.RawLineSize. Тем не менее, иногда может потребоваться добавить дополнительный отступ к строкам сырых данных или уменьшить его, и в этом случае может использоваться другой размер строки. Если требуется подмножество прямоугольника ограничивающего изображение, тогда учтите битовые сдвиги, которые могут возникнуть для индексированных RGB пиксельных форматов. Например, давайте рассмотрим изображение с размерами 100x100 пикселей и форматом сырых данных 1 бит на пиксель. Вы хотите загрузить прямоугольник сырых данных с координатами (7,0) и размерами (2,1), или другими словами, вам требуется 2 пикселя, начиная с x=7 и y=0. В этом случае вы получите следующую структуру данных:

название_изображения

Это значит, что вы получите 2 байта, где первый байт содержит 7 ненужных пикселей, затем 1 нужный пиксель, а второй байт содержит 1 нужный пиксель и затем 7 ненужных. Вы можете спросить, почему мы не выполнили сдвиг данных и не поместили те 2 пикселя в один байт? Ответ прост: чтобы обеспечить высокую производительность. Все внутренние вычисления обычно выполняются со всеми данными, начиная с первого пикселя и заканчивая последним доступным пикселем. Существуют редкие ситуации, когда требуется подмножество пикселей. Кроме того, мы не знаем, как эти пиксели будут обработаны далее, поэтому сдвиг негативно скажется на производительности и сделает код ненужно сложным. Всегда оценивайте правильный бит (необходимо определить правильный байт, так как данные всегда поступают с первым заполненным байтом), с которого начнутся запрошенные пиксели. Для вычисления правильного бита можно использовать простую формулу: (rect.Left * количество бит) % 8.

Конвертация Индексированного RGB Цвета

Для достижения наивысшей возможной производительности всегда используйте одни и те же исходные и конечные настройки сырых данных, форматы пикселей и размеры строк. Однако иногда может потребоваться выполнить конвертацию данных. Например, вы можете загрузить изображение RGB с глубиной цвета 1 бит на пиксель и сохранить его с глубиной цвета 2 бита на пиксель, или загрузить изображение RGB с глубиной цвета 4 бита и уменьшить его цветовой диапазон до 2 бит на пиксель. В любом случае требуется применить цветовую конвертацию. Конвертация индексированных изображений RGB иногда может быть сложной и не может быть выполнена без применения некоторых настроек. Нам необходимо определить, как диапазон цветов исходного изображения сопоставляется с целевым цветовым пространством. Для выполнения этой задачи у нас есть разные режимы:

При использовании конвертации палитры исходное цветовое пространство пытается соответствовать целевому цветовому пространству как можно ближе. Например, давайте предположим, у нас есть изображение с глубиной цвета 4 бита с следующими цветами: [0] RGB=0, 0, 0 [1] RGB=17, 17, 17 [2] RGB=34, 34, 34 [3] RGB=51, 51, 51 [4] RGB=68, 68, 68 [5] RGB=85, 85, 85 [6] RGB=102, 102, 102 [7] RGB=119, 119, 119 [8] RGB=136, 136, 136 [9] RGB=153, 153, 153 [10] RGB=170, 170, 170 [11] RGB=187, 187, 187 [12] RGB=204, 204, 204 [13] RGB=221, 221, 221 [14] RGB=238, 238, 238 [15] RGB=255, 255, 255

Исходное изображение будет выглядеть следующим образом:

название_изображения

И мы преобразуем 4-битное изображение в 1-битное изображение с определенными цветами палитры:

[0] RGB = 0, 0, 0 [1] RGB = 255, 255, 255

В режиме конвертации палитры конвертер считывает исходный цвет и определяет индекс цели с использованием метода GetNearestColorIndex целевой палитры. Значение свойства RasterImage.RawFallbackIndex используется в случае, если метод GetNearestColorIndex палитры дает индекс за пределами диапазона. Это преобразует исходные цвета в ближайшие целевые цвета в терминах интенсивностей. Целевое изображение соответствует исходному изображению как можно ближе. Вы можете увидеть следующий результат:

название_изображения

В режиме сопоставления сырых данных используется другой сценарий. Палитры исходного и целевого цветов просто игнорируются, и исходные индексы преобразуются в индексы назначения. Когда найдено значение, которое не может быть сопоставлено с диапазоном назначения (понижая количество битов), тогда используется значение свойства RasterImage.RawFallbackIndex. Значение по умолчанию равно 0 и будет сопоставлено с первым цветом в палитре назначения. Если это значение свойства находится вне диапазона назначения, будет сгенерировано соответствующее исключение. Это приводит к менее предсказуемым результатам, которые могут быть показаны на следующем изображении:

название_изображения

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

Для использования любого из этих подходов используйте свойство RawDitheringMethod класса RasterImage. По умолчанию оно установлено в метод конвертации палитры для достижения наилучших результатов. Вы можете изменить это свойство перед любой конвертацией (например, при сохранении изображения в поток). Обратите внимание, что режимы игнорирования палитры и конвертации палитры не будут применяться, если вы загрузили изображение и перезаписали некоторые изначальные пиксельные данные, поскольку новые данные сохраняются в кеше и кеш хранит данные в максимальном доступном формате 32ARGB (на момент версии 2.4.0, подлежит изменениям). Этот формат используется для преодоления проблем с возможными различиями цветовых диапазонов для загруженных и сохраненных изображений. Кроме того, режимы игнорирования палитры и конвертации палитры не будут применяться, когда изображение загружено в режиме RGB и конвертировано в индексированный режим или наоборот.

Пользовательские Конвертеры Цвета

Иногда недостаточно использовать стандартный подход к цветовой конвертации. Возможно, вам захочется использовать собственный алгоритм для получения полной свободы при использовании рутин конвертации цвета. Если форматы пикселей исходного и целевого изображений оба являются индексированными форматами RGB, то можно использовать более простой интерфейс [IIndexedColorConverter](https://reference.aspose.com/