• Miércoles 20 de Noviembre de 2024, 14:22

Autor Tema:  Matriz De Imágenes  (Leído 6503 veces)

Danielo

  • Miembro activo
  • **
  • Mensajes: 69
    • Ver Perfil
Matriz De Imágenes
« en: Sábado 11 de Febrero de 2006, 03:58 »
0
Hola a todos...

Necesito mostrar varias imágenes en un formulario, por ejemplo:

    [imagen01.bmp]  [imagen02.bmp]  [imagen03.bmp]  [imagen04.bmp]

    [imagen05.bmp]  [imagen06.bmp]  [imagen07.bmp]  [imagen08.bmp]

    [imagen09.bmp]  [imagen10.bmp]  [imagen11.bmp]  [imagen12.bmp]

quisiera saber (en caso de que sea posible) como se puede hacer utilizando una matriz de imágenes (array de 2 dimensiones) en tiempo de ejecución.

Intenté con algo como esto:

myArray: array[0..2,0..3] of TImage;

... pero si bien funciona, no se como hacer para mostrar las imágenes en el formulario con los TImage.

Salu2...
   Danielo.

PD: Estoy utilizando el Lazarus, por si a alguien le interesa hace unos días apareció una nueva versión: la 0.9.12  ;)
Recuerda siempre que eres único... Exactamente igual que todos los demás.
No existen frases de seis palabras.
Seamos realistas. Busquemos lo imposible.
Lo difícil tarda un poco en resolverse, lo imposible un poco más.

Amilius

  • Miembro HIPER activo
  • ****
  • Mensajes: 665
    • Ver Perfil
Re: Matriz De Imágenes
« Respuesta #1 en: Domingo 12 de Febrero de 2006, 00:41 »
0
Bueno hace tiempo que doy la misma respuesta y sigue siendo válida.  :lol:

No uses un Timage para tus bitmaps, usa un Tbitmap. Creas los tbitmaps, los cargas con los bmp, o asignas jpeg. (no olvides de destruirlos!!!)

Luego colocas en tu formulario un Tpaintbox y en su evento OnPaint pintas los bitmaps en la posicion que quieras. Incluso puedes revisar si realmente necesitas pintarlos todos o solo algunos dependiendo de la zona de clip.

Supongo que lazarus seguira la misma idea respecto a Tbitmap, TCanvas y TPaintbox

En si el Tbitmap sirve literalmente como pedazo de memoria para tener almacenado tu bitmap. Mejor si le asignas el tipo DIB (Device independet bitmap, osea en memoria RAM y no en video en caso que quieras trabajar sobre la imagen)

El Tpaintbox no tiene memoria asignada de ningun tipo, sólo sirve para saber en que posicion de la memoria de video tiene que poner nuestros bitmaps y responde a eventos como onPaint que ocurre cuando otra ventana se puso encima de la nuestra y luego se necesita repintar nuestra ventana.

El Tcanvas es el que tiene la capacidad de pintar (graficos de todo tipo, texto, bitmaps, etc.) en memoria de video(en este caso el Tpaintbox) o en RAM (un bitmap DIB)

Enko

  • Miembro de PLATA
  • *****
  • Mensajes: 1562
  • Nacionalidad: 00
    • Ver Perfil
Re: Matriz De Imágenes
« Respuesta #2 en: Domingo 12 de Febrero de 2006, 01:50 »
0
No se si en lazarus está el componente pero tambien es bueno para eso  el TDrawGrid.
Es una gradilla en la cual  hay que dibujar usando directamente la propiedad TCanvas.

Como parametro se recibe la recta de la celda que se va a dibujar y las  coordenadas de la celda.
El siguiente codigo dibujaria un bitmap en la primera celda del Grid.

Código: Text
  1.  
  2. procedure TfrmEditor.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
  3. begin
  4.    if (aCol=0) and (aRow=0) DrawGrid1.Canvas.StretchDraw(Rect, Bitmap);
  5. end;
  6.  
  7.  

Danielo

  • Miembro activo
  • **
  • Mensajes: 69
    • Ver Perfil
Re: Matriz De Imágenes
« Respuesta #3 en: Domingo 12 de Febrero de 2006, 14:44 »
0
Saludos Amilius y Enko...

Para fijar ideas creo que lo mejor sera que explique (brevemente) lo que quiero hacer:

Se trata del juego Mastermind, como ya sabrán el objetivo es adivinar una secuencia de fichas de colores, que en este caso el programa se encargará de generar.

El problema que tengo es con la representación de las fichas, o sea elegir una estrategia para poder manipularlas de una forma no muy complicada.
Por eso lo que se me ocurrió fue una matriz de imágenes de esta forma:

Primeramente coloco en el formulario varios TImage, más precisamente 12 filas x 5 columnas. Esto tiene como ventaja, que de ser necesario puedo utilizar la propiedad de dobleClick sobre la TImage, para por ejemplo borrar una ficha de color, para poder cambiarla por otra.

Luego declaro un array:

mat:array[0..11,0..4] of TImage;

La desventaja que le encuentro a esto es que tendría que cargar la matriz manualmente, o sea:

mat[0,0]:=Image1;
mat[0,1]:=Image2;
mat[0,2]:=Image3;
...

Bueno, suponiendo que haya alguna mejor manera de hacer lo anterior, lo
que faltaría es cargar los archivos de imágen en la matriz mat y eso lo
encuentro bastante sencillo, utilizando un ImageList (Seguramente en Delphi
también existe, no lo se).

Entonces, una vez cargado el ImageList con las imágenes de las fichas, habría que hacer:

ImageList1.Draw(mat[fil,col].Canvas,1,1,indice_imagen);

donde fil y col, son las coordenadas (fila y columna) donde se quiere asignar
la ficha (imágen) cuyo indice en el imageList es indice_imagen.


Ahora paso a responder sobre las alternativas que me han dado:



Para Amilius:

Por lo que he visto, te puedo decir que en Lazarus existe tanto el TBitmap como el TPaintbox, sin embargo el TBItmap no soporta algunos métodos de Delphi, basicamente los relacionados con las Apis de windows, como por ejemplo el método ScanLine que según parece requiere la GDI32.dll. De todas formas no creo que el ScanLine sea necesario en este caso, por si te interesa en este link hay más información:

http://wiki.lazarus.freepascal.org/index.p...g_with_Graphics

Volviendo al TBitmap que me sugieres, no me queda muy claro la forma de utilizarlo. En lugar de utilizar una matriz de TImages me sugieres utilizar una matriz de Tbitmaps?

esto es:

mat:array[0..11,0..4] of TBitmap;

luego creo cada celda de la matriz:

mat[fil,col]:=TBitmap.create;

Luego me dices que coloque un Tpaintbox en el formulario y en la propiedad OnPaint pinte los bitmas en la posición que quiera (¿?), esto último no tengo idea de como hay que hacerlo. Además no entiendo como con un solo Tpaintbox puedo mostrar todas las imágenes bmp.


Para Enko:

Sobre el TDrawGrid, al menos con ese nombre no parece estar en Lazarus. Lo más perecido parece ser TDbGrid que está en la ficha Data Controls y tengo mis dudas de que sea lo mismo porque cuando coloco ese componente en el formulario queda algo parecido a una tabla en excel.
Recuerda siempre que eres único... Exactamente igual que todos los demás.
No existen frases de seis palabras.
Seamos realistas. Busquemos lo imposible.
Lo difícil tarda un poco en resolverse, lo imposible un poco más.

Enko

  • Miembro de PLATA
  • *****
  • Mensajes: 1562
  • Nacionalidad: 00
    • Ver Perfil
Re: Matriz De Imágenes
« Respuesta #4 en: Domingo 12 de Febrero de 2006, 15:22 »
0
Citar
Para Enko:

Sobre el TDrawGrid, al menos con ese nombre no parece estar en Lazarus. Lo más perecido parece ser TDbGrid que está en la ficha Data Controls y tengo mis dudas de que sea lo mismo porque cuando coloco ese componente en el formulario queda algo parecido a una tabla en excel.
Tonces no está.

Amilius

  • Miembro HIPER activo
  • ****
  • Mensajes: 665
    • Ver Perfil
Re: Matriz De Imágenes
« Respuesta #5 en: Domingo 12 de Febrero de 2006, 16:10 »
0
Cita de: "Danielo"
...Luego me dices que coloque un Tpaintbox en el formulario y en la propiedad OnPaint pinte los bitmas en la posición que quiera (¿?), esto último no tengo idea de como hay que hacerlo. Además no entiendo como con un solo Tpaintbox puedo mostrar todas las imágenes bmp.
...
Para pintar:

miTpaintBox.canvas.draw();

En delphi existe un tab de properties para asignar a un evento como onPaint la función que quieras que se ejecute para responder al evento.

Un evento como "OnPaint" es similar a una variable, pero del tipo función de objeto que recibe ciertos tipos de parámetros.

Danielo

  • Miembro activo
  • **
  • Mensajes: 69
    • Ver Perfil
Re: Matriz De Imágenes
« Respuesta #6 en: Domingo 12 de Febrero de 2006, 22:45 »
0
Gracias Amilius...

Finalmente logré cargar un bmp en un TPaintBox!!  :rolleyes:

Citar
En delphi existe un tab de properties para asignar a un evento como onPaint la función que quieras que se ejecute para responder al evento.

En Lazarus también está el tab de propiedades, eso es lo que me faltaba para cargar el bmp.

Lo que veo es que al igual que con los TImage, con los TBitmap no escapo de asignarlos uno por uno a la matriz que contendrá las fichas  :(


 :hola: Salu2...
Recuerda siempre que eres único... Exactamente igual que todos los demás.
No existen frases de seis palabras.
Seamos realistas. Busquemos lo imposible.
Lo difícil tarda un poco en resolverse, lo imposible un poco más.

Enko

  • Miembro de PLATA
  • *****
  • Mensajes: 1562
  • Nacionalidad: 00
    • Ver Perfil
Re: Matriz De Imágenes
« Respuesta #7 en: Lunes 13 de Febrero de 2006, 14:33 »
0
La cosa es que no necesitas una matriz de imagenes para tu juego.

Primero que tu matriz debería ser  de byte o algo así:
Código: Text
  1.  
  2.   Matriz: array[0..3,0..3] of Byte;
  3.  
  4.  

Luego necesitarias un procedimieto que te inicialize la matriz, digamos, ponga todas las cadenas de las imagenes de a pares ordenadas de alguna forma, todavia sin mezclar.
Código: Text
  1.  
  2. procedure InicializarMatriz;
  3. begin
  4.   Matriz[0,0] := 1;
  5.   Matriz[0,1] := 1;
  6.   Matriz[0,2] := 2;
  7.   Matriz[0,3] := 2;
  8. end;
  9.  
  10.  
Por supuesto que es mejor que lo hagas con un ciclo :rolleyes:

Luego necesitarias un procedimiento simple que te mezcle la matriz.

Tambien necesitar'ias un procedimiento que te cargue todas las imagenes
Pero para eso necesitar'ias un arreglo con todas las imagenes
Código: Text
  1.  
  2.   Imagenes: array[1..MAX_IMG] of TBitmap;
  3.  
  4.  
 
Código: Text
  1.  
  2. procedure cargarImagenes;
  3. var
  4.   iCount : integer;
  5. begin
  6.    for i:=1 to MAX_IMG do
  7.    begin
  8.      Imagenes[iCount] := TBitmap.Create;
  9.      Imagenes[iCount].LoadFromFile('NombreImagen' + IntegerToString(i) + '.bmp');
  10.   end;
  11. end;
  12.  
  13.  
Tus imagenes deber'ian llamarse NombreImagen1.bmp, NOmbreImagen2.bmp, etc....
 Supondr'e que las imagenes son cuadradas...
 
Y finalmente, uno quien te la imprima  que ser'ia algo asi:
Código: Text
  1.  
  2. procedure ImprimirMatriz;
  3. var
  4.   iCount, jCount: integer;
  5. begin
  6.   for jCount := 1 to MAX_CELL do
  7.     for iCount := 1 to MAX_CELL do
  8.         PaintBox.Canvas.Draw(iCount*IMG_WIDTH, jCount*IMG_WIDTH,  
  9.                                            Imagenes[Matriz[iCount, jCount]]);
  10. end;
  11.  
  12.  

Por supuesto que te har'ia falta todo lo que es la jugada pero no necesariamente necesitas matriz de imagenes.

Enko

  • Miembro de PLATA
  • *****
  • Mensajes: 1562
  • Nacionalidad: 00
    • Ver Perfil
Re: Matriz De Imágenes
« Respuesta #8 en: Lunes 13 de Febrero de 2006, 14:38 »
0
Lastima que Lazarus no posee el TDrawgrid ya que este posee un metodo que te devuelve en que celda el usuario hizo clic, algo indispensable para vos.
Igualmente ese procedimiento lo podr'ias hacer vos mismo, es tan solo recalcular segun la X,Y del raton, en que imagen se hizo clic.
Esto es proque en realidad la imagen es una sola compuesta de muchas imagenes.

Deberia ser algo asi:
Código: Text
  1.  
  2. procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  3.   Shift: TShiftState; X, Y: Integer);
  4. begin
  5.   CeldaX := X div IMG_WIDTH;
  6.   CeldaY :  Y div IMG_WIDTH;
  7. end;
  8.  
  9.  
ahora que lo veo, no hay problema con eso.

Danielo

  • Miembro activo
  • **
  • Mensajes: 69
    • Ver Perfil
Re: Matriz De Imágenes
« Respuesta #9 en: Martes 14 de Febrero de 2006, 23:14 »
0
:good:  Muchas Gracias, Enko!!

Muy buena la explicación, gracias al código que escribiste ahora entiendo y de hecho he logrado cargar en un TBitmap varias imágenes, o sea las fichas de colores... por supuesto despliego la matriz de fichas teniendo en cuenta los valores numericos previamente cargados en otra matriz cuyos elementos son enteros (de tipo byte).

En el procedimiento de cargar imágenes me queda una pequeña duda :blink:  y es sobre la ruta  desde la cual se cargarán las imágenes. Recuerdo que en visual basic existe el app.path que retorna un string con la ruta en que se encuentra el programa, en Delphi existe algo parecido???

Continuando con el procedimiento de cargar imágenes, otra alternativa que encontré fue cargarlas todas en un TImageList (en lugar de utilizar un array de TBitmaps), que es una especie de arreglo dinámico de imágenes en el que a cada una se le asigna un índice, de esa forma no es necesario cargarlas de un directorio y ademas luego de compilado el programa las imágenes quedan embutidas en el ejecutable. Otra ventaja es que en el TImageList (de Lazarus) puedo cargar imagenes de varios tipos (ico, ppm, pgm, pbm, png, xpm, bmp).

Entonces, con lo anterior el procedimiento de Imprimir la matriz quedaría así:
Código: Text
  1.  
  2. procedure ImprimirMatriz;
  3. var
  4.  iCount, jCount: integer;
  5. begin
  6.  for jCount := 1 to MAX_CELL do
  7.    for iCount := 1 to MAX_CELL do                  
  8.      imagelist.Draw(PaintBox.Canvas,iCount*IMG_WIDTH,jCount*IMG_WIDTH,
  9. Matriz[iCount,jCount]);
  10. end;
  11.  
  12.  

Buenísimo el procedimiento para calcular las coordenadas de la imágen en que se hizo clic!! funciona fenomenál!!... ignoraba que se pudiese hacer algo así.

En cuanto al TDrawgrid...  :brickwall:  al final descubrí que existe en Lazarus :( (más vale tarde que nunca) está en la Ficha Additional, no lo he probado aún pero imagino que habrá alguna manera quitarle la apariencia de tabla.
Recuerda siempre que eres único... Exactamente igual que todos los demás.
No existen frases de seis palabras.
Seamos realistas. Busquemos lo imposible.
Lo difícil tarda un poco en resolverse, lo imposible un poco más.

Enko

  • Miembro de PLATA
  • *****
  • Mensajes: 1562
  • Nacionalidad: 00
    • Ver Perfil
Re: Matriz De Imágenes
« Respuesta #10 en: Jueves 16 de Febrero de 2006, 01:21 »
0
Citar
En el procedimiento de cargar imágenes me queda una pequeña duda blink.gif y es sobre la ruta desde la cual se cargarán las imágenes. Recuerdo que en visual basic existe el app.path que retorna un string con la ruta en que se encuentra el programa, en Delphi existe algo parecido???
Código: Text
  1.  
  2. Directorio := ExtractFilePath(Application.ExeName);
  3.  
  4.  

Aunque deber'ia funcionar (suponiendo que tienes en la carpeta de la ejecutable una carpeta llamada imagenes:
Código: Text
  1.  
  2. TBitMap.LoadFromFile('imagenes\nombre.bmp');
  3.  
  4.