2016-06-25 7 views
0

Я манипулирую кодом средства визуализации изображений, который создает выходное изображение из массива Color [], и мой код просто обновляет его дополнительными материалами прямо перед сохранением, то есть когда на самом деле готово исходное изображение (все позиции пикселей, подготовленные для заполнения RGB в массиве Color [], готовые для окончательной экономии).JAVA Color [] to BufferedImage to Color [] bleached output

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

По этой причине, - как у меня нет рича/доступа к оригинальной подготовленной BufferedImage (но у меня есть доступ к фактическому цвету [], что он создан из) я должен был сделать свой собственный метод класса, который:

  1. конвертировать этот оригинальный цвет [] в мое собственное время BufferedImage
  2. обновите эту температуру. BufferedImage моих вещей через Graphics2D (добавить текст к изображению)
  3. конвертировать мой результат (темп. BufferedImage с Graphics2D) обратно в цвет []
  4. отправить, что окончательный цвет [] вернуться к исходному изображению метода рендеринга, который будет на самом деле сделать это будет финальное изображение, которое вынес из и сохранить как PNG

Теперь все работает так хорошо, как я ожидал, за исключением одного очень раздражает то, что я не могу избавиться от: мой обновленный образ выглядит очень отбеленные -like/pale (почти нет глубины или теней) по сравнению с оригинальной версией без водяных знаков ver sion ...

Мне кажется, что после преобразования image2color [] (используя решение @ укладчика отсюда Converting Image to Color array) что-то пошло не так/неправильно, поэтому цвета бледнеют, и я не знаю, почему.

Вот основная часть моего кода, который находится под вопросом:

  BufferedImage sourceImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 

      // Color[] to BufferedImage 
      for (int k = 0; k < multiArrayList.size(); k++) { 

       // PREPARE... 
       int x = (int) multiArrayList.get(k)[0]; 
       int y = (int) multiArrayList.get(k)[1]; 
       int w = (int) multiArrayList.get(k)[2]; 
       int h = (int) multiArrayList.get(k)[3]; 
       Color[] data = (Color[]) multiArrayList.get(k)[4]; 
       int border = BORDERS[k % BORDERS.length]; 

       for (int by = 0; by < h; by++) { 
        for (int bx = 0; bx < w; bx++) { 
         if (bx == 0 || bx == w - 1) { 
          if (5 * by < h || 5 * (h - by - 1) < h) { 
           sourceImage.setRGB(x + bx, y + by, border); 
          } 
         } else if (by == 0 || by == h - 1) { 
          if (5 * bx < w || 5 * (w - bx - 1) < w) { 
           sourceImage.setRGB(x + bx, y + by, border); 
          } 
         } 
        } 
       } 
       // UPDATE... 
       for (int j = 0, index = 0; j < h; j++) { 
        for (int i = 0; i < w; i++, index++) { 
         sourceImage.setRGB(x + i, y + j, data[index].copy().toNonLinear().toRGB()); 
        } 
       } 
      } 

      Graphics2D g2d = (Graphics2D) sourceImage.getGraphics(); 

      // paints the textual watermark 
      drawString(g2d, text, centerX, centerY, sourceImage.getWidth()); 

      // when saved to png at this point ALL IS JUST FINE 
      ImageIO.write(sourceImage, "png", new File(imageSavePath)); 
      g2d.dispose(); 

      // BufferedImage to Color array 
      int[] dt = ((DataBufferInt) sourceImage.getRaster().getDataBuffer()).getData(); 

      bucketFull = new Color[dt.length]; 
      for (int i = 0; i < dt.length; i++) { 
       bucketFull[i] = new Color(dt[i]); 
      } 

      // update and repaint output image - THIS OUTPUT IS ALREADY BLEACHED/PALE 
      d.ip(0, 0, width, height, renderThreads.length + 1); 
      d.iu(0, 0, width, height, bucketFull); 

      // reset objects 
      g2d = null; 
      sourceImage = null; 
      bucketFull = null; 
      multiArrayList = new ArrayList<>(); 

Я тестируемый (сохранив его в другую .png файл сразу после добавления Graphics2D), что, прежде чем он получает, что второе преобразование его выглядит абсолютно нормально 1: 1 до исходного изображения вкл. мой текст на этом изображении.

Но как я сказал, когда он отправляется для рендеринга, он становится белевым/бледным, что является проблемой, которую я пытаюсь решить.

BTW Вначале я подумал, что это может быть то, что добавление Graphics2D, поэтому я пробовал его без него, но результат был таким же, что и отбеленная/бледная версия.

Хотя мой процесс и код полностью отличается вывод изображения в основном страдает точно так же, как и в этой теме (до сих пор не решена) BufferedImage color saturation

Вот мои 2 примера - первый ОРИГИНАЛ, второй ОБНОВЛЕНО (отбеленная/бледный)

enter image description here enter image description here

+1

Что такое класс «Цвет», который вы используете? Кажется, это не 'java.awt.Color' ... И более конкретно, что делает' data [index] .copy(). ToNonLinear(). ToRGB() 'do? Кажется, вы преобразовали значения цвета перед передачей их в «BufferedImage». Но вы ничего не делаете. Я подозреваю, что это проблема. – haraldK

+0

@haraldK использует float 0-1 вместо int 0-255, data [index] .copy(). ToNonLinear(). ToRGB() взят из исходного кода, не совсем уверен, что именно он делает, но я думаю, что он исправляет/манипулирует гамма ... в любом случае: я протестировал его сейчас без части .copy() .NonLinear() и ** WOW: NOW IT RENDERS OK ** - большое вам спасибо! Вы хотите опубликовать это как самостоятельное предложение, чтобы я мог подписать его как правильный ответ? ;-) – errerr

+0

Хорошо! Я добавил ответ. :-) – haraldK

ответ

0

Как и предполагалось, проблема заключается в том, что вы преобразовать значения цвета из RGB линейной гамма-скорректированные значения/SRGB при установке значения RGB в BufferedImage, но в обратном тр ansformation (back to linear RGB) не выполняется, когда вы возвращаете значения обратно в массив Color.

Либо измените строку (внутри двойной for петли):

sourceImage.setRGB(x + i, y + j, data[index].copy().toNonLinear().toRGB()); 

к

sourceImage.setRGB(x + i, y + j, data[index].toRGB()); 

(вам не нужно copy() больше, как вы больше не мутировать значения, используя toNonLinear()).

Это позволяет избежать конверсии вообще.


... или вы могли, вероятно, также изменить настройку значений линии спины, от:

bucketFull[i] = new Color(dt[i]); 

в

bucketFull[i] = new Color(dt[i]).toLinear(); 

Можно утверждать, что это более "правильный" (поскольку AWT обрабатывает значения как в цветовом пространстве sRGB, независимо), но я считаю, что первая версия быстрее, а разница в цвете незначительна. Поэтому я, вероятно, сначала попробую первое предложенное решение, и использую это, если вы не используете цвета, которые отключены.

+1

*** да, вот и все ***: "bucketFull [i] = новый цвет (dt [i]). ToLinear();" – errerr