Brilho na imagem com RGB
Como fazer para intensificar as cores (dar brilho) de uma imagem que está em um componente image?
O efito que quero é semelhante ao que ocorre nos botões do outlook.
Tentei usando a função RGB, mas só em aumentar apenas uma unidade nos valores as cores já ficam muito diferentes.
Quero também o inverso. Escurecer um pouquinho a imagem.
O efito que quero é semelhante ao que ocorre nos botões do outlook.
Tentei usando a função RGB, mas só em aumentar apenas uma unidade nos valores as cores já ficam muito diferentes.
Quero também o inverso. Escurecer um pouquinho a imagem.
Raserafim
Curtidas 0
Respostas
Beppe
17/02/2005
Você terá que converter para HSV(ou seria HSB, B de Bright?), Aí é só alterar o valor e converter pra RGB de volta.
GOSTEI 0
Marcelo Saviski
17/02/2005
Numa edição da revista saiu uma matéria sobre isso, naõ na última, acho que na edição 57, não tenho certeza.
Ou vc pode tentar ver nesse [url=http://forum.clubedelphi.net/viewtopic.php?t=5986&highlight=brilho+imagem]outro tópico[/url]
Ou vc pode tentar ver nesse [url=http://forum.clubedelphi.net/viewtopic.php?t=5986&highlight=brilho+imagem]outro tópico[/url]
GOSTEI 0
Raserafim
17/02/2005
Beppe, vc poderia explicar melhor como utilizar esta função? como fazer esta conversão?
Marcelo, eu já havia visto este tópico, mas não entendi o código. Não gosto de escrever uma função sem saber exatamente o q esto fazendo. Caso o código da revista seja mais simples, vc poderia colocar aqui?
Marcelo, eu já havia visto este tópico, mas não entendi o código. Não gosto de escrever uma função sem saber exatamente o q esto fazendo. Caso o código da revista seja mais simples, vc poderia colocar aqui?
GOSTEI 0
Beppe
17/02/2005
Cara, até vou pesquisar melhor sobre isto. Se conseguir algo concreto(ou não, rsrsrs) eu posto.
GOSTEI 0
Massuda
17/02/2005
Se você estiver usando D6 ou mais recente, dê uma olhada na função ColorAdjustLuma da unit GraphUtils. Talvez você consiga ´garimpar´ mais informações [url=http://www.efg2.com/Lab/Library/Delphi/Graphics/Color.htm]nesta página[/url].
GOSTEI 0
Beppe
17/02/2005
Colega,
Como o Massuda disse vc pode usar a rotina ColorAdjustLuma, mas também existem lá as rotinas GetHighLightColor e GetShadowColor(note que elas tomam um argumento padrão), entretanto, eu chequei, elas não fazem exatamente o que o Outlook faz. Se vc quer duplicar o efeito, acho que terá que usar uma destas 3 funções com um valor baseado na luminosidade atual.
Eu também olhei a implementação, e isto me desencorajou de implementar em MMX. Como elas me parecem(não testei) lentas, considere fazer um ´cache´ das imagens, ou monte uma tabela de hash com as cores. Em GraphUtils isto é feito apenas para a última cor.
T+
Como o Massuda disse vc pode usar a rotina ColorAdjustLuma, mas também existem lá as rotinas GetHighLightColor e GetShadowColor(note que elas tomam um argumento padrão), entretanto, eu chequei, elas não fazem exatamente o que o Outlook faz. Se vc quer duplicar o efeito, acho que terá que usar uma destas 3 funções com um valor baseado na luminosidade atual.
Eu também olhei a implementação, e isto me desencorajou de implementar em MMX. Como elas me parecem(não testei) lentas, considere fazer um ´cache´ das imagens, ou monte uma tabela de hash com as cores. Em GraphUtils isto é feito apenas para a última cor.
T+
GOSTEI 0
Beppe
17/02/2005
Eu definitivamente não gostei em ter que decompor os canais e compor de novo, então parti para uma solução aditiva, eficiente e com um ótimo resultado.
Pode ver que o resultado é diferente, mas melhor, na minha opinião.
unit Unit1;
interface
uses
Windows, Forms, Controls, StdCtrls, Buttons, Graphics, Classes, ExtCtrls,
SysUtils, GraphUtil;
type
TForm1 = class(TForm)
Image1: TImage;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
procedure FormCreate(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
private
{ Private declarations }
public
Bmp: TBitmap;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function ColorAddChannel(C: TColor; N: Integer): TColor;
asm
pxor mm0, mm0
movd mm1, C
movd mm2, N
punpcklbw mm1, mm0
packuswb mm2, mm2
packuswb mm2, mm2
paddusb mm2, mm1
packuswb mm2, mm0
movd eax, mm2
and eax, $ffffff
emms
end;
procedure ColorAddChannelArray32(A, B: PIntegerArray; Size, N: Integer);
asm
pxor mm0, mm0
movd mm2, N
packuswb mm2, mm2
packuswb mm2, mm2
@loop:
movd mm1, [A]
punpcklbw mm1, mm0
paddusb mm1, mm2
packuswb mm1, mm0
movd [B], mm1
and [B], $ffffff
add A, 4
add B, 4
dec Size
jnz @loop
emms
end;
procedure TForm1.FormCreate(Sender: TObject);
var
A: TColor;
X, Y: TColor;
begin
A := clRed;
X := ColorAddChannel(A, 30);
ColorAddChannelArray32(@A, @Y, 1, 30);
Caption := Format(´¬x - ¬x´, [X, Y]);
Image1.Picture.Bitmap.PixelFormat := pf32bit;
Bmp := TBitmap.Create;
Bmp.Assign(Image1.Picture.Graphic);
Image1.Picture.Assign(Bmp);
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
var
X, Y: Integer;
begin
for X := 0 to Bmp.Width - 1 do
for Y := 0 to Bmp.Height - 1 do
Image1.Canvas.Pixels[X, Y] := ColorAddChannel(Bmp.Canvas.Pixels[X, Y], 90);
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
var
I: Integer;
A, B: Pointer;
S, F: Int64;
begin
QueryPerformanceCounter(S);
// A := Bmp.ScanLine[Image1.Height - 1];
// B := Image1.Picture.Bitmap.ScanLine[Image1.Height - 1];
// ColorAddChannelArray32(A, B, Bmp.Width * Bmp.Height, 90);
for I := 0 to Bmp.Height - 1 do
begin
A := Bmp.ScanLine[I];
B := Image1.Picture.Bitmap.ScanLine[I];
ColorAddChannelArray32(A, B, Bmp.Width, 90);
end;
QueryPerformanceCounter(F);
Caption := IntToStr(F - S);
end;
procedure TForm1.BitBtn3Click(Sender: TObject);
var
X, Y: Integer;
begin
for X := 0 to Bmp.Width - 1 do
for Y := 0 to Bmp.Height - 1 do
Image1.Canvas.Pixels[X, Y] := GetHighLightColor(Bmp.Canvas.Pixels[X, Y]);
end;
end.Pode ver que o resultado é diferente, mas melhor, na minha opinião.
GOSTEI 0
Raserafim
17/02/2005
valeu beep pela atenção e pelo trabalhão. p.... até assembler ;) valeu.
mas valeu tb massuda, era mesmo o q eu queria, algo simples. E a procedure ColorAdjustLuma caiu certinho. É só eu passar como parâmetro o pixel que quero modificar (ex: Image1.Canvas.Pixels[X, Y]), mais um parämetro que diz o brilho (coloquei 35 e -35, para clarear e escurecer respectivamente), e mais um parâmetro que não entendi pra q serve mas coloquei true.
Mas agora preciso resolver um outro problema:
Tive que criar um laço for para varrer toda imagem pegando pixel por pixel e colando em um outro image. Mas o problema é que essa varredura é muito lenta e demora um pouco para a imagem alterada aparecer.
Como faço para agilizar esse processo?
mas valeu tb massuda, era mesmo o q eu queria, algo simples. E a procedure ColorAdjustLuma caiu certinho. É só eu passar como parâmetro o pixel que quero modificar (ex: Image1.Canvas.Pixels[X, Y]), mais um parämetro que diz o brilho (coloquei 35 e -35, para clarear e escurecer respectivamente), e mais um parâmetro que não entendi pra q serve mas coloquei true.
Mas agora preciso resolver um outro problema:
Tive que criar um laço for para varrer toda imagem pegando pixel por pixel e colando em um outro image. Mas o problema é que essa varredura é muito lenta e demora um pouco para a imagem alterada aparecer.
Como faço para agilizar esse processo?
GOSTEI 0
Marcelo Saviski
17/02/2005
Como faço para agilizar esse processo?
Usa a função do Beppe :) :P
GOSTEI 0
Beppe
17/02/2005
valeu beep pela atenção e pelo trabalhão. p.... até assembler ;) valeu.
Trabalho algum, apenas uma oportunidade para treinar meu MMX.
e mais um parâmetro que não entendi pra q serve mas coloquei true.
O último parâmetro é ignorado pela função.
Mas agora preciso resolver um outro problema:
Tive que criar um laço for para varrer toda imagem pegando pixel por pixel e colando em um outro image. Mas o problema é que essa varredura é muito lenta e demora um pouco para a imagem alterada aparecer.
Como faço para agilizar esse processo?
Está sendo gentil né? ColorAdjustLuma foi umas 100x mais lenta que a minha função. O problema é que vc deve estar usando Canvas.Pixels[], que é bem lento por design. Use ScanLine, que recupera o array de pixels(lembre-se de chamar Refresh na imagem depois, eu esqueci disso no exemplo).
[quote:709c368e52=´Marcelo Saviski´]
Como faço para agilizar esse processo?
Usa a função do Beppe :) :P[/quote:709c368e52]
Eu concordo. :P Mas se ele prefere fazer do modo lento, doloroso, e mais feim, opção dele... :D
ColorAdjustLuma(60), ColorAddChannelArray32(90)
[URL=http://img67.exs.cx/my.php?loc=img67&image=high6sw.jpg][img:709c368e52]http://img67.exs.cx/img67/8725/high6sw.th.jpg[/img:709c368e52][/URL]
GOSTEI 0
Marcelo Saviski
17/02/2005
esse MMX funciona em qualquer processador? ou só nos da Intel?
GOSTEI 0
Beppe
17/02/2005
[quote:27a9e17db0=´Marcelo Saviski´]esse MMX funciona em qualquer processador? ou só nos da Intel?[/quote:27a9e17db0]
MMX é mais básico que tem. Mas é meu preferido, questão de utilidade e padronização.
MMX - Desde o Pentium (I) MMX. AMD também tem. Aritmética inteira.
SS2 - Desde o Pentium III. AMD também tem. Aritmética flutuante.
SS3 - Desde o Pentium 4. Aritmética inteira.
3DNOW - Apenas AMD.
Todos são SIMD(instrução única operando sobre dados múltiplos, i.e. um array)
MMX é mais básico que tem. Mas é meu preferido, questão de utilidade e padronização.
MMX - Desde o Pentium (I) MMX. AMD também tem. Aritmética inteira.
SS2 - Desde o Pentium III. AMD também tem. Aritmética flutuante.
SS3 - Desde o Pentium 4. Aritmética inteira.
3DNOW - Apenas AMD.
Todos são SIMD(instrução única operando sobre dados múltiplos, i.e. um array)
GOSTEI 0
Marcelo Saviski
17/02/2005
ha ta, vlw
quem sabe um dia ainda acordo sabendo isso...
quem sabe um dia ainda acordo sabendo isso...
GOSTEI 0
Raserafim
17/02/2005
beppe, como posso utilizar a função ScanLine, associada com o ColorAdjustLuma?
GOSTEI 0
Beppe
17/02/2005
Uma desvantagem de ScanLine é que vc precisa ter uma versão para cada formato, esta que segue é apenas para bitmaps de 32 bits.
Este é um exemplo básico, pode aplicar qualquer transformação de cor assim.
procedure TForm1.BitBtn2Click(Sender: TObject); var I: Integer; A, B: Pointer; S, F: Int64; begin QueryPerformanceCounter(S); A := Bmp.ScanLine[Image1.Height - 1]; B := Image1.Picture.Bitmap.ScanLine[Image1.Height - 1]; for I := 0 to Bmp.Height * Bmp.Width - 1 do PIntegerArray(B)[I] := ColorAdjustLuma(PIntegerArray(A)[I], Valor); QueryPerformanceCounter(F); ShowMessage(´Demorou ´ + IntToStr(F - S) + ´ ciclos.´); end;
Este é um exemplo básico, pode aplicar qualquer transformação de cor assim.
GOSTEI 0
Raserafim
17/02/2005
Beepe, foi mal cara, mas ainda não consegui.
me diz o código pra seguinte situação:
Tenho um componente Image1 que tem a imagem que vou utilizar de base para o brilho. Tenho um Image2 que quero colocar a imagem com o brilho. E um button1 que ao pressionar dispara o procedimento. Me diz o código que tenho que utilizar para esta combinação.
me diz o código pra seguinte situação:
Tenho um componente Image1 que tem a imagem que vou utilizar de base para o brilho. Tenho um Image2 que quero colocar a imagem com o brilho. E um button1 que ao pressionar dispara o procedimento. Me diz o código que tenho que utilizar para esta combinação.
GOSTEI 0
Raserafim
17/02/2005
beppe, olha só quantos views teve este tópico!
não é justo deixar ele sem conclusão, sem resposta.
já tentei outra vez e não consegui.
se vc conseguir pode ser q agente consiga fazer um efeito interessante com um comando de certa forma simples, ou pelo menos não tão complicado, e com um bom desempenho.
não é justo deixar ele sem conclusão, sem resposta.
já tentei outra vez e não consegui.
se vc conseguir pode ser q agente consiga fazer um efeito interessante com um comando de certa forma simples, ou pelo menos não tão complicado, e com um bom desempenho.
GOSTEI 0
Beppe
17/02/2005
Desculpe, raserafim, não havia visto sua pergunta. Quer uma função usando qual rotina? A da VCL ou a minha?
GOSTEI 0
Raserafim
17/02/2005
beppe, o que quero é dar o brilho na imagem com a função ColorAdjustLuma. Mas o código que fiz (usando Canvas.Pixels[]) ficou muito lento. Você deu a idéia de usar o ColorAdjustLuma com a função ScanLine, porém não consegui fazer isto.
Então o que queria que fizesse era montar este código para a seguinte situação:
Tenho um componente Image1 que tem a imagem que vou utilizar de base para o brilho. Tenho um Image2 que quero colocar a imagem com o brilho. E um button1 que ao pressionar dispara o procedimento. Me diz o código que tenho que utilizar para esta combinação.
Então o que queria que fizesse era montar este código para a seguinte situação:
Tenho um componente Image1 que tem a imagem que vou utilizar de base para o brilho. Tenho um Image2 que quero colocar a imagem com o brilho. E um button1 que ao pressionar dispara o procedimento. Me diz o código que tenho que utilizar para esta combinação.
GOSTEI 0