Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Gráficos (https://www.clubdelphi.com/foros/forumdisplay.php?f=8)
-   -   Pasar un JPEG en color a sepia (https://www.clubdelphi.com/foros/showthread.php?t=18454)

pampitasnowman 12-02-2005 15:24:10

Pasar un JPEG en color a sepia
 
Hola a todos! Tengo la siguiente consulta, hay alguna forma de pasar una imagen JPEG, que esta en color, a sepia (sepia es una gama de colores marrones y amarillos). Muchas gracias.

Neftali [Germán.Estévez] 14-02-2005 10:27:44

Cita:

Empezado por pampitasnowman
Tengo la siguiente consulta, hay alguna forma de pasar una imagen JPEG, que esta en color, a sepia (sepia es una gama de colores marrones y amarillos).

Tal vez estoy diciendo tonterías, pero me da la impresión de que pasar una imagen a sepia debe ser "lo mismo" que pasarla a Grises, pero simplemente con otro parámetro de color. Para pasar una imagen a escala de Grises, se coge un pixel y se hace su correspondencia en su escala de Grises, así con todos los pixel de la imagen (con un doble bucle for, debería bastar). Pasarla a sepia es lo mismo, pero pasando ese pixel a su correspondencia en la "escala de sepia". Eso me lleva a una pregunta. ¿Está definida esa "escala de sepia"?

Por ejemplo, la escala de Grises se obtiene asignando el mismo valor a los tres colores principales(R,G,B); Variando esos valores (pero siempre iguales en los tres) se obtienen los Grises. ¿Hay algo parecido para la escala de Sepia? ¿debe haber una especificación?

Gydba 14-02-2005 13:07:18

Hola,

Como dice el amigo Neftali la solución a tu problema puede ser similar a pasar una imágen a grices o a dos colores.

Un ejemplo de como hacerlo está en:
http://www.swissdelphicenter.ch/en/showcode.php?id=437

Saludos!

pampitasnowman 14-02-2005 21:42:36

Encontré el siguiente código en la página que me mandaste Gydba:
Código:

//This function adds a sepia effect to a bitmap.
//the 'depth' sets the colour intensity of the red-brown colour
//greater numbers set a higher intensity.
//To create a greyscale effect instead, set 'depth' to 0

function bmptosepia(const bmp: TBitmap; depth: Integer): Boolean;
var
color,color2:longint;
r,g,b,rr,gg:byte;
h,w:integer;
begin
  for h := 0 to bmp.height do
  begin
    for w := 0 to bmp.width do
    begin
//first convert the bitmap to greyscale
    color:=colortorgb(bmp.Canvas.pixels[w,h]);
    r:=getrvalue(color);
    g:=getgvalue(color);
    b:=getbvalue(color);
    color2:=(r+g+b) div 3;
    bmp.canvas.Pixels[w,h]:=RGB(color2,color2,color2);
//then convert it to sepia
    color:=colortorgb(bmp.Canvas.pixels[w,h]);
    r:=getrvalue(color);
    g:=getgvalue(color);
    b:=getbvalue(color);
    rr:=r+(depth*2);
    gg:=g+depth;
    if rr <= ((depth*2)-1) then
    rr:=255;
    if gg <= (depth-1) then
    gg:=255;
    bmp.canvas.Pixels[w,h]:=RGB(rr,gg,b);
    end;
  end;
end;

//Example:
procedure TForm1.Button1Click(Sender: TObject);
begin
  bmptosepia(image1.picture.bitmap, 20);
end;

La cosa es que clickeo en el botón y la imagen desaparece, o se pone negra, no lo sé. Tendrá algo que ver que la imagen original es un JPG? Osea, Image1.Picture es un JPG.
Y tampoco entiendo porque es una función que retorna un buleano y sin el codigo "return". Bueno, espero que alguno se de cuenta donde está el error o que hago mal. Muchas gracias.

Héctor Randolph 14-02-2005 21:47:58

Cita:

Empezado por Neftalí
Eso me lleva a una pregunta. ¿Está definida esa "escala de sepia"?

Por ejemplo, la escala de Grises se obtiene asignando el mismo valor a los tres colores principales(R,G,B); Variando esos valores (pero siempre iguales en los tres) se obtienen los Grises. ¿Hay algo parecido para la escala de Sepia? ¿debe haber una especificación?

Hola a todos!

Con respecto a esta cuestión sólo quisiera añadir algo, es posible crear una escala de tonos sepia a nuestra conveniencia, es decir asi como hay una escala de 256 tonos de gris podemos crear una escala de 256 tonos en sepia, rojo, amarillo, azul, etc.

Aqui pongo un ejemplo de una escala de 256 tonos en sepia, en realidad solamente tomé un gradiente que comienza con café oscuro y que pasa por amarillos hasta llegar a blanco.

Código Delphi [-]
const
  TSepiaTonos: array[0..255] of TColor=(
  $71730, $71831, $81932, $91A33, $A1B34, $B1C36, $C1D37, $D1E38,
  $E2039, $E213A, $F223C, $10233D, $11243E, $12253F, $132640, $142742,
  $152943, $152A44, $162B45, $172C46, $182D48, $192E49, $1A2F4A, $1B304B,
  $1C324C, $1C334E, $1D344F, $1E3550, $1F3651, $203752, $213854, $223955,
  $233B56, $233C57, $243D58, $253E5A, $263F5B, $27405C, $28415D, $29425E,
  $2A4460, $2A4561, $2B4662, $2C4763, $2D4864, $2E4966, $2F4A67, $304B68,
  $314D69, $314E6A, $324F6C, $33506D, $34516E, $35526F, $365370, $375472,
  $385673, $385774, $395875, $3A5976, $3B5A78, $3C5B79, $3D5C7A, $3E5D7B,
  $3F5F7D, $3F607E, $40617F, $416280, $426381, $436483, $446584, $456685,
  $466886, $466987, $476A89, $486B8A, $496C8B, $4A6D8C, $4B6E8D, $4C6F8F,
  $4D7190, $4D7291, $4E7392, $4F7493, $507595, $517696, $527797, $537898,
  $547A99, $547B9B, $557C9C, $567D9D, $577E9E, $587F9F, $5980A1, $5A81A2,
  $5B83A3, $5B84A4, $5C85A5, $5D86A7, $5E87A8, $5F88A9, $6089AA, $618AAB,
  $628CAD, $628DAE, $638EAF, $648FB0, $6590B1, $6691B3, $6792B4, $6893B5,
  $6995B6, $6996B7, $6A97B9, $6B98BA, $6C99BB, $6D9ABC, $6E9BBD, $6F9CBF,
  $709EC0, $709FC1, $71A0C2, $72A1C3, $73A2C5, $74A3C6, $75A4C7, $76A5C8,
  $77A7CA, $77A7CA, $78A7CA, $79A8CA, $7AA9CB, $7BA9CB, $7CAACC, $7DABCC,
  $7EABCC, $7FACCD, $80ADCD, $81ADCE, $82AECE, $83AFCF, $85B0CF, $86B0CF,
  $87B1D0, $88B2D0, $89B2D1, $8AB3D1, $8BB4D1, $8CB4D2, $8DB5D2, $8EB6D3,
  $8FB7D3, $90B7D4, $91B8D4, $93B9D4, $94B9D5, $95BAD5, $96BBD6, $97BBD6,
  $98BCD7, $99BDD7, $9ABED7, $9BBED8, $9CBFD8, $9DC0D9, $9EC0D9, $A0C1D9,
  $A1C2DA, $A2C2DA, $A3C3DB, $A4C4DB, $A5C5DC, $A6C5DC, $A7C6DC, $A8C7DD,
  $A9C7DD, $AAC8DE, $ABC9DE, $ACC9DF, $AECADF, $AFCBDF, $B0CCE0, $B1CCE0,
  $B2CDE1, $B3CEE1, $B4CEE1, $B5CFE2, $B6D0E2, $B7D0E3, $B8D1E3, $B9D2E4,
  $BBD3E4, $BCD3E4, $BDD4E5, $BED5E5, $BFD5E6, $C0D6E6, $C1D7E7, $C2D7E7,
  $C3D8E7, $C4D9E8, $C5D9E8, $C6DAE9, $C7DBE9, $C9DCE9, $CADCEA, $CBDDEA,
  $CCDEEB, $CDDEEB, $CEDFEC, $CFE0EC, $D0E0EC, $D1E1ED, $D2E2ED, $D3E3EE,
  $D4E3EE, $D5E4EF, $D7E5EF, $D8E5EF, $D9E6F0, $DAE7F0, $DBE7F1, $DCE8F1,
  $DDE9F1, $DEEAF2, $DFEAF2, $E0EBF3, $E1ECF3, $E2ECF4, $E4EDF4, $E5EEF4,
  $E6EEF5, $E7EFF5, $E8F0F6, $E9F1F6, $EAF1F7, $EBF2F7, $ECF3F7, $EDF3F8,
  $EEF4F8, $EFF5F9, $F0F5F9, $F2F6F9, $F3F7FA, $F4F8FA, $F5F8FB, $F6F9FB,
  $F7FAFC, $F8FAFC, $F9FBFC, $FAFCFD, $FBFCFD, $FCFDFE, $FDFEFE, $FFFFFF);


Ahora la cuestión sola es tomar un vector de componentes de color (R,G,B) y aplicar una transformación que convierta a escala de 256 grises como las que han recomendado en este hilo.

Voy a tomar el producto punto como ejemplo:

GRIS=(R,G,B).(0.30,0.59,0.11)=R*0.30+G*0.59+B*0.11

Esto nos dará un valor entre [0..255] correspondiente a un color en la escala de 256 tonos de gris.

Ahora sólo buscamos el equivalente en la escala de 256 tonos sepia que construimos.

NuevoColor=TonosSepia[GRIS]

Un ejemplo de como aplicarlo sería

Código Delphi [-]
type
  TRGBArray = array[0..32767] of TRGBTriple;
  PRGBArray = ^TRGBArray;
procedure TForm1.Button3Click(Sender: TObject);
var
 Row: PRGBArray;
 y,x,Gris: Integer;
begin
  Image1.Picture.Bitmap.PixelFormat := pf24Bit;
  for y := 0 to Image1.Picture.Bitmap.Height - 1 do
  begin
    Row := Image1.Picture.Bitmap.ScanLine[y];
    for x := 0 to Image1.Picture.Bitmap.Width - 1 do
    begin
      Gris           := Round(Row[x].rgbtRed*0.3 + Row[x].rgbtGreen*0.59 + Row[x].rgbtBlue*0.11);
      Row[x].rgbtRed := GetRValue(ColorToRGB(TSepiaTonos[Gris]));
      Row[x].rgbtGreen := GetGValue(ColorToRGB(TSepiaTonos[Gris]));
      Row[x].rgbtBlue := GetBValue(ColorToRGB(TSepiaTonos[Gris]));
    end;
  end;
  Image1.Repaint;
end;

Es tan sólo un ejemplo, la escala de tonos la he creado arbitrariamente y cada quien puede definir su propia escala de acuerdo a su preferencia.

Un saludo y seguimos en contacto

Neftali [Germán.Estévez] 15-02-2005 10:01:58

Cita:

Empezado por pampitasnowman
...La cosa es que clickeo en el botón y la imagen desaparece, o se pone negra, no lo sé. Tendrá algo que ver que la imagen original es un JPG? Osea, Image1.Picture es un JPG.

La función "funciona" (valga la redundancia) perfectamente si la utilizas con un BMP; Prueba a convertir primero el JPG a BMP y luego "pasarle" la función. En cuanto al Result, tienes razón, supongo que debe ser un olvido, aunque no afecta al funcionamiento (conversión).

Antes de que lo preguntes...:D

Convert JPEG to BMP

pampitasnowman 15-02-2005 12:43:43

Por fin! Muchas gracias a todos por responder mis inquietudes. Probé las dos funciones que estaban en cuestión y funcionaron las dos perfectamente. Nuevamente, gracias a todos por responderme este post. Saludos, Nacho.

PD: Había que pasar nomás el JPG a BITMAP. :)

Héctor Randolph 16-02-2005 03:34:27

Hola Nacho!

Recibí tu correo en donde me pides que te explique como puedes modificar la escala de tonos sepia que puse como ejemplo en el código.

Voy a publicar el código que utilicé para crearla, por si le interesa a alguien más.

Con esta función puedes llenar un arreglo con un gradiente de colores.

Código Delphi [-]
type
  TEscala= array[0..255] of TColor;
//Crea un gradiente entre tres colores fijos
//La función está limitada a tres colores pero puede adaptarse para cuatro o más
function TForm1.CrearGradiente(Colors: array of TColor):TEscala;
type
  RGBArray = array[0..2] of Byte;
var
  x, y, z, mx, bis, faColorsh: Integer;
  Factor: double;
  A: RGBArray;
  B: array of RGBArray;
  Escala: TEscala;
  I:Integer;
begin
  mx := High(Colors);
  if (mx <1) or ( mx>2) then
    raise Exception.Create('El número de colores debe estar entre 2..3');
  SetLength(b, mx + 1);
  for x := 0 to mx do
  begin
    Colors[x] := ColorToRGB(Colors[x]);
    b[x][0] := GetRValue(Colors[x]);
    b[x][1] := GetGValue(Colors[x]);
    b[x][2] := GetBValue(Colors[x]);
  end;
  faColorsh := Round(255 / mx);
  I:=0;

  for y := 0 to mx - 1 do
  begin
    if y = mx - 1 then
      bis := 255 - y * faColorsh - 1
    else
      bis := faColorsh;
    for x := 0 to bis do
    begin
      Factor := x / bis;
      for z := 0 to 3 do
        a[z] := Trunc(b[y][z] + ((b[y + 1][z] - b[y][z]) * Factor));
      Escala[i]:= RGB(a[0], a[1], a[2]);
      Inc(I);
    end;
  end;
  b := nil;
  Result:=Escala;
end;


Con esta función lo puedes enviar a un archivo de texto para después incluirla en el código.

Código Delphi [-]
//  Guarda la escala en un archivo de texto

procedure TForm1.GuardarEnTxt(Escala:TEscala;FileName: String);
var
 I: Integer;
 S: String;
 Stream:TFileStream;
begin
  Stream:=TFileStream.Create(FileName,fmCreate);
  S:='const'+#13+'TTonos: array[0..255] of TColor=('+#13;
  Stream.Write(PChar(S)^,Length(S));
  S:=' ';
  for I:=0 to 255 do
  begin
    S:=S+'$'+IntToHex(Escala[i],6);
    if I=255 then
    begin
      S:=S+');';
      Stream.Write(PChar(S)^,Length(S));
    end
    else
    begin
      S:=S+',';
      if (I mod 8)=7 then
      begin
        S:=S+#13;
        Stream.Write(PChar(S)^,Length(S));
        S:='  ';
      end;
    end;
  end;
  Stream.Free;
end;

Un ejemplo de como puedes llamar la función.

Código Delphi [-]

procedure TForm1.Button1Click(Sender: TObject);
var
  Escala:TEscala;
begin
  //Crea una escala de tonos en ROJO
  Escala:=CrearGradiente([clBlack, clRed, clWhite]);
  GuardarEnTxt(Escala,'c:\escala.txt');
end;


Con este ejemplo creas una escala de tonos que comienza en NEGRO, pasando por ROJO y que termina en BLANCO.

Puedes experimentar con otros colores para obtener mejores efectos.

Un saludo.

pampitasnowman 16-02-2005 15:51:30

Nuevamente muchas gracias! :)


La franja horaria es GMT +2. Ahora son las 17:57:40.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi