Лучший подход к хранению пикселей изображения в порядке снизу вверх в Java - PullRequest
3 голосов
/ 17 марта 2010

У меня есть массив байтов, представляющих изображение в формате Windows BMP, и я хотел бы, чтобы моя библиотека представляла его приложению Java в виде BufferedImage, без копирования данных пикселей.

Основная проблема заключается в том, что все реализации Raster в JDK хранят пиксели изображения в порядке сверху вниз, слева направо, тогда как данные пикселей BMP хранятся снизу вверх, слева направо. Если это не компенсируется, полученное изображение будет перевернуто вертикально.

Наиболее очевидное «решение» - установить для свойства SampleModel s scanlineStride отрицательное значение и изменить смещение полосы (или смещение массива DataBuffer) так, чтобы оно указывало на верхний левый пиксель. первый пиксель последней строки в массиве. К сожалению, это не работает, потому что все конструкторы SampleModel выдают исключение, если дан отрицательный аргумент scanlineStride.

В настоящее время я работаю над этим, заставляя поле scanlineStride принимать отрицательное значение с помощью отражения, но я хотел бы сделать это более чистым и более переносимым способом, если это возможно. например Есть ли другой способ обмануть Raster или SampleModel, чтобы расположить пиксели в порядке снизу вверх, но без нарушения инкапсуляции? Или есть где-нибудь библиотека, которая обернет Raster и SampleModel, представляя строки пикселей в обратном порядке?

Я бы предпочел избегать следующих подходов:

  • Копирование всего изображения (по соображениям производительности. Код должен обрабатывать сотни больших (> = 1 мегапикселей) изображений в секунду, и, хотя все изображение должно быть доступно приложению, оно обычно получает доступ только к маленьким (но жестким предсказать) часть изображения.)
  • Изменение DataBuffer для выполнения преобразования координат (это на самом деле работает, но является еще одним «грязным» решением, потому что буферу не нужно знать о макете отсканированной линии / пикселя.)
  • Повторная реализация интерфейсов Raster и / или SampleModel с нуля (из-за того, как реализована проверка совместимости (по крайней мере, в JDK Sun)), требующая определенных подклассов SampleModel, поэтому универсальный BottomUpSampleModel класс-обертка не будет работать.)

Ответы [ 3 ]

1 голос
/ 26 марта 2010

Я обнаружил, что могу реализовать это, используя только один новый класс, который я назвал BottomUpComponentSampleModel. Он расширяет ComponentSampleModel и отменяет значение поля scanlineStride (которое, к счастью, равно protected, а не private) после вызова конструктора суперкласса. Все вычисления адреса пикселя работают нормально, хотя проверка в Raster.createWritableRaster не работает (может не получиться определить, если вы предоставите ему слишком маленький массив), но это не является серьезной проблемой.

Это не обязательно с MultiPixelPackedSampleModel или SinglePixelPackedSampleModel, так как они принимают отрицательный scanlineStride. У них нет смещений полосы, но это можно обойти, установив смещение на DataBuffer.

0 голосов
/ 17 марта 2010

даже лучше, похоже, что приложению не нужно отображать изображение? Зачем беспокоиться о желании перевернуть его, чтобы оно выглядело правильно на экране? Просто напишите логику для работы на той версии, которая у вас есть? Нет необходимости иметь BufferedImage таким же образом, работать непосредственно с массивом.

0 голосов
/ 17 марта 2010

как насчет того, чтобы приложение (или слой доступа) выполнял перевод и переворачивал свою копию при доступе к крошечной (но трудно предсказуемой) части изображения?

...