2012-05-16 1 views
5

Я экспериментировал с Change HUE/Saturation например найти на сайте EFG: http://www.efg2.com/Lab/Library/Delphi/Graphics/Color.htmИзменить HUE растрового изображения, но сохранить цвет фона?

enter image description here

Я хочу использовать методы, найденные в этом примере, чтобы изменить цветовые значения некоторых растровых изображений (для использования на TImage). Есть одна проблема, с которой я столкнулся, и это с TImages, которые имеют прозрачные растровые изображения; Я не хочу, чтобы цвет фона менял свой HUE, а скорее фактические данные изображения.

Возьмите этот образец изображения, мы можем работать с (хотя любое изображение с прозрачностью могут быть использованы):

enter image description here

  • Скачать Change HUE/Saturation демку по ссылке вверху.
  • Загрузите изображение кнопки выше в ImageOriginal.
  • Установить насыщенность дельта на 1.
  • Запустите проект.

Некоторые выходные результаты:

enter image description hereenter image description here

То, что я хотел бы произойти здесь является сохранить первоначальный цвет фона (определяется в нижней левой позиции пикселя) и только регулировать цветовой тон для остальных изображения. Таким образом, результаты вывода будет выглядеть на самом деле это (редактируется в Paint.NET):

enter image description hereenter image description here

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

enter image description here

Как и раньше с первым образцом изображения, результаты могут быть чем-то вроде:

enter image description hereenter image description here

Когда результаты я хочу должен быть примерно так:

enter image description hereenter image description here

Одна идея у меня было после изменения HUE, замените в левом нижнем углу наиболее цвет с цветом от оригинала, но я не уверен, что это правильный подход или нет, и даже если я не уверен, как заменить цвет X на другой цвет. (Графика и математика вне меня).

Например, если я нарисовал два синего цвета кругов на ухо Микки (синий был оригинальный прозрачный цвет из нижней левой позиции пикселей), а также цветные глаза:

enter image description here

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

enter image description here

, когда на самом деле он хотел бы это:

enter image description here

Проще говоря, я хотел бы изменить HUE изображения, будь то методами, используемыми в демо-версии EFG или другом решении. Прозрачный цвет, определяемый нижним левым пикселем, не должен меняться при изменении HUE, это должно оставаться таким же, как показано на образце.

Как изменить HUE растрового изображения, сохранив цвет фона?

ответ

5

Код, на который вы ссылаетесь, просматривает все пиксели изображения для изменения оттенка/насыщенности. Вы можете изменить код так, чтобы он не мешал, если пиксель имеет определенный цвет:

PROCEDURE TFormChangeHS.UpdateBitmap; 
    .. 
    S    : TReal; 
    V    : TReal; 

    FixColor: TRGBTriple;       // New variable 
BEGIN 
    DeltaSaturation := SpinEditDeltaSaturation.Value; 
    NewHue := TrackBarHue.Position; 

    Bitmap := TBitmap.Create; 
    TRY 
    Bitmap.Width := ImageOriginal.Width; 
    Bitmap.Height := ImageOriginal.Height; 
    Bitmap.PixelFormat := ImageOriginal.Picture.Bitmap.PixelFormat; 
    ASSERT(Bitmap.PixelFormat = pf24bit); 

    // save bottom left color 
    FixColor := PRGBTripleArray(
        ImageOriginal.Picture.Bitmap.ScanLine[Bitmap.Height - 1])^[0]; 
    //-- 

    FOR j := 0 TO Bitmap.Height-1 DO 
    BEGIN 
     RowIn := ImageOriginal.Picture.Bitmap.Scanline[j]; 
     RowOut := Bitmap.Scanline[j]; 
     FOR i := 0 TO Bitmap.Width-1 DO 
     BEGIN 
     WITH RowIn[i] DO 
     BEGIN 

      // copy the color to target and continue with next iteration 
      if (RowIn[i].rgbtBlue = FixColor.rgbtBlue) and 
       (RowIn[i].rgbtGreen = FixColor.rgbtGreen) and 
       (RowIn[i].rgbtRed = FixColor.rgbtRed) then begin 
      RowOut[i] := FixColor; 
      Continue; 
      end; 
      //-- 

      // convert pixel coordinates to HSV 
      RGBtoHSV(rgbtRed, rgbtGreen, rgbtBlue, H, S, V); 
     END; 
     .. 
     .. 


Выход:

enter code here

+0

Отлично Sertac, который работает, как я надеялся. Не могли бы вы объяснить эту строку, хотя пожалуйста: 'FixColor: = PRGBTripleArray ( ImageOriginal.Picture.Bitmap.ScanLine [Bitmap.Height - 1])^[0];' Это эквивалентно использованию пикселей [], но быстрее? Я не уверен, что делает бит [0]. –

+1

@Blobby - Вы действительно можете удалить '^', это не нужно (что указывает PRGBTripleArray, но компилятор может разрешить его без «^»), левая часть - TRGBTripleArray, поэтому [0] - это первый элемент массива. Скорость не важна, так как мы читаем только один пиксель, вы можете очень хорошо использовать пиксели. –

+0

Огромное спасибо за очищение. Я думаю, что я понимаю и другой код: 'if (RowIn [i] .rgbtBlue = FixColor.rgbtBlue) и' .. это проверка цвета каждого пикселя в канале RGB, и если каждый из компонентов RGB равен FixColor вы конвертируете его в FixColor? –

2

В теории, вы можете, например:

Во-первых, вы должны определить, что является фоном ... (вероятно, выбирая цвет определенного пикселя как Дельфи делает ...)

Тогда , с этим цветом фона, вы можете создать маску на основе этого цвета ...

вы продублировать изображение ... применить оттенок ...

вы объедините 2 растровых изображений с использованием маски ...

+0

звучит как хорошая идея, я никогда не работал с масками, прежде Однако. –

+1

проверить их .. они могут быть очень полезными; o) самая сложная часть, возможно, ** эффективно * создать маску с ** сжатым ** jpeg – Whiler

+0

Как ответ Sertac работает отлично, но благодаря вашему ответу я думаю, что я могу смотреть дальше в масках, у меня есть идея, что они есть, но я обязательно получу некоторую информацию о них :) –