Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Gráficos (https://www.clubdelphi.com/foros/forumdisplay.php?f=8)
-   -   ¿Cómo convierto una imagen RAW de 8 bpp a BMP? (https://www.clubdelphi.com/foros/showthread.php?t=17391)

molarte 06-01-2005 21:01:52

¿Cómo convierto una imagen RAW de 8 bpp a BMP?
 
Buen día,

Estoy realizando una aplicación de huellas dáctilares y el dispositivo que estoy empleando me regresa las imágenes que captura en formato RAW de 8 bits por pixes a una escala de 256 grises.

Lo que quiero es convertir esa imagen a bitmap de 8 bits por pixel en gris y que me permita manipularlo con un TPicture.

¿Alguno de ustedes ha hecho una conversión de este tipo?
Agradecería su ayuda.

Saludos y feliz año nuevo desde México
Miguel

Héctor Randolph 06-01-2005 23:23:08

Hola Miguel!

El problema que veo es que el formato RAW en realidad no es un estándar, solamente es una forma de almacenar directamente los bytes que componen la imagen, es decir, no tiene compresión, ni encabezado definido, etc.


El formato RAW es una manera fácil de importar/exportar imagenes pero cada quién aplica sus propias reglas.

Lo primero sería descrifrar la manera en que fueron almacenados los datos, por ejemplo la información que siempre debe de existir para recuperar la imagen es el ancho y la altura de la imagen así como el formato de color, en este caso es 256 color a escala de grises, supongo que debe de ser RGB.

Como no existe un encabezado estándar, hay que investigar si esta información fue colocada al inicio del archivo o al final.

Una vez que se conozca que convención utilizaron para almacenar la imagen no debe de ser dificíl convertir a BMP.

Trata de investigar que convención se utilizó para guardar las imagenes, o bien adjunta una imagen de ejemplo que no ocupe mucho espacio y con gusto la revisaré para ver si puedo ayudarte con la conversión.

Un saludo.

molarte 10-01-2005 19:03:41

Hola Héctor,


Gracias por tu ayuda.

Efectivamente, me falto dar mas información en mi pregunta. La imagen tiene 416 X 416 pixeles, y cada pixel es de 8 bits, lo cual me genera un archivo de
173056 bytes.

En base a lo que me comentas hice un experimento tratando de abrir el archivo en Photo Shop 7 y me reconoce los 416 X 416 bytes, sin encabezado y a 8 bytes por pixel. Como es en grices, a mi me parece que es de $00 a $FF el color de cada pixel, pero no estoy seguro.

Te podria mandar un archivo de ejemplo, pero ¿cómo te lo envio? La verdad soy nuevo en este foro y no se si sea a través de aquí o a tu correo.

Nuevamente Gracias y espero me puedar dar una pista de como lo convierto. :rolleyes:

Gracias
Miguel

<Sergio> 12-01-2005 00:18:39

Nuevamente la solución es usar el Tbitmap.scanline :D

Creas un objeto Tbitmap, defines propiedades de bits por pixel a 8 bits, imagen de tipo "dib", ancho y alto. Luego con scanline vas llenando la información del Tbirmap (cada pixel es un byte en tu archivo, asi que posiblemente puedas optimizar aún más usando "move()" linea a linea teniendo cuidado de no pasar de los límites del área de memoria para cada linea), luego un saveToFile y listo.

//crear
...
HandleType:= bmDIB;
PixelFormat = pf8bit;
...

Mas detalles en:

http://www.clubdelphi.com/foros/showthread.php?t=17427

Héctor Randolph 12-01-2005 18:44:26

Hola Miguel!

Efectivamente la mejor opción es la que propone <Sergio>; por lo que comentas tu archivo solamente contiene los datos de la imagen, entonces la conversion es directa.

Lo único que me gustaría agregar es la cuestión de la paleta de colores a escala de grises.

Te pongo un ejemplo de como puedes generar una paleta simple.


Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
 Stream: TStream;
 Bitmap:TBitmap;
 P: PByteArray;
 PaletaGrises: TMaxLogPalette;
 y,x,N: Integer;
begin
  //Carga el archivo en memoria
  Stream:=TFileStream.Create('Imagen.raw',fmOpenRead);
  Bitmap:=TBitmap.Create;
  with Bitmap do begin
    Height:=416;
    Width:=416;
    PixelFormat:=pf8bit;// 8 bit por pixel
    HandleType:=bmDIB;
    //Asigna los valore a cada pixel de la imagen
    for y:=0 to Height-1 do begin
      P:=ScanLine[y];
      for x:=0 to Width-1 do
        Stream.Read(P[x],1);
    end;
    with PaletaGrises do// Crea una paleta de 256 colores en gris
    begin
      palVersion:= $0300;
      palNumEntries:= 256;
      for N:=0 to $FF do
      begin
          with palPalEntry[N] do
          begin
            peRed   := N;
            peGreen := N;
            peBlue  := N;
            peFlags := 0;
          end;
      end;
    end;
    //Fija la nueva paleta
    Palette:=CreatePalette(pLogPalette(@PaletaGrises)^);
  end;
  Bitmap.SaveToFile('Imagen.bmp');
  Image1.Picture.Bitmap.Assign(Bitmap);//Cargarlo en TImage opcional
  Bitmap.Free;
  Stream.Free;
end;

Un saludo.

molarte 12-01-2005 18:58:06

Héctor y Sergio,

Les agradezco mucho la ayuda. El método de Sergio es el más sencillo y efectivamente como comentas, Héctor, tenía problemas con la paleta; sin embargo, como lo voy a pasar a JPG, el bitmap lo creó a 24 bit por pixel y en un RGB con los cada canal al mismo valor tengo el gris correspondiente. Aparantemente estó no me implica mucha carga de procesamiento. Probaré la solución de Héctor a ver si hay diferencia en el desempeño.

A continuación les muestro mi solución: :)

Faltó comentar que el archivo de imagen RAW lo tengo en memoria en un arreglo de byte de 416*416.

Código:


procedure ConvierteImagen;
var
  BMP : TBitmap;
  ContRenglon, ContColumna, ContImagen  : integer;
  Renglon : PByteArray;
begin
  BMP := TBitmap.Create;
  BMP.HandleType := bmDIB;
  BMP.PixelFormat := pf24bit;
  BMP.Width := 416;
  BMP.Height := 416;
  ContImagen := 0;
  for ContRenglon := 0 to 415 do
  begin
        Renglon := BMP.ScanLine[ContRenglon];
        for ContColumna := 0 to 415 do
        begin
          Renglon[ContColumna*3] := Imagen[ContImagen];
          Renglon[ContColumna*3+1] := Imagen[ContImagen];
          Renglon[ContColumna*3+2] := Imagen[ContImagen];
          Inc(ContImagen);
        end;
  end;
  BMP.SaveToFile('C:\HuellaPrueba.bmp');
  BMP.Free;
end;

Agradezco mucho su ayuda y cualquier cosa estoy para servirles. :rolleyes:

Gracias
Miguel

<Sergio> 12-01-2005 20:26:09

Tip:

Ahora en tu ciclo interno lo único "pesado" son las multiplicaciones (que actualmente son mas "pesadas" que un salto corto).

Código Delphi [-]
   for ContColumna := 0 to 415 do
   begin
     Renglon[ContColumna*3] := Imagen[ContImagen];
     Renglon[ContColumna*3+1] := Imagen[ContImagen];
     Renglon[ContColumna*3+2] := Imagen[ContImagen];
     Inc(ContImagen);
   end;

Es mejor evitar multiplicaciones y divisiones al tratar cada pixel en la medida de lo posible. Por ejemplo se puede usar un while e incrementar contcolumna:

Código Delphi [-]
   ContColumna := 0;
   while ContColumna<(416{Ancho}*3{RGB}) do
   begin//evitando multiplicaciones
     Renglon[ContColumna] := Imagen[ContImagen];
     inc(ContColumna);
     Renglon[ContColumna] := Imagen[ContImagen];
     inc(ContColumna);
     Renglon[ContColumna] := Imagen[ContImagen];
     inc(ContColumna);
     Inc(ContImagen);
   end;

molarte 14-01-2005 23:01:48

Tienes mucha razón Sergio, modificaré mi código.

Muchas gracias y saludos :)

Miguel


La franja horaria es GMT +2. Ahora son las 10:50:12.

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