Обработка Сырых Данных
Для улучшения производительности 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 иногда может быть сложной и не может быть выполнена без применения некоторых настроек. Нам необходимо определить, как диапазон цветов исходного изображения сопоставляется с целевым цветовым пространством. Для выполнения этой задачи у нас есть разные режимы:
- Сопоставление палитры (DitheringMethods.PaletteConversion)
- Сопоставление сырых данных (DitheringMethods.PaletteIgnore)
- Пользовательская конвертация (DitheringMethods.CustomConverter)
При использовании конвертации палитры исходное цветовое пространство пытается соответствовать целевому цветовому пространству как можно ближе. Например, давайте предположим, у нас есть изображение с глубиной цвета 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/