¿SetPixel con un array?

Iniciado por e, 7 Septiembre 2019, 22:10 PM

0 Miembros y 1 Visitante están viendo este tema.

e

Hola  :D,
recientemente he exportado una imagen con gimp a una cabecera de C, y me ha quedado un array de bits.
Lo que me gustaría saber es como dibujar cada pixel con SetPixel, es decir, sacar cada valor RGB.
e

RayR

Justamente los comentarios de la cabecera explican su uso, pero básicamente hay que llamar a la macro HEADER_PIXEL. Algo así:

char pixel[3];
char *datos = header_data;
...
HEADER_PIXEL(data, pixel)


Una vez que llamas a HEADER_PIXEL, pixel[0], pixel[1] y pixel[2] contendrán los valores para los componentes rojo, verde y azul, en ese orden, del primer pixel. La siguiente vez que llames a HEADER_PIXEL, los valores de pixel serán actualizados a los del siguiente pixel y así sucesivamente.

Pero realmente es un "formato" feo y no muy eficiente. Tienes que llamar a esa macro que hace operaciones a nivel de bits porque los valores RGB se almacenan de tal manera que cada byte guardado sea un caracter ASCII imprimible, por lo que ocupan parte de un byte, y parte de otro. Te recomendaría que consideres usar algún formato de verdad. Por ejemplo, el BMP es tan simple que escribir una función que lo lea es una tarea prácticamente trivial; ni siquiera hace falta recurrir a bibliotecas externas.

e

Gracias, al final lo he exportado a un BMP con un simple fprintf, Entonces, ¿cómo se haría para dibujar un BMP a la pantalla o a una ventana (con su HWND).

Gracias   :D
e

RayR

¿Lo exportaste a un BMP con un simple fprintf  :o? ¿Cómo? Primero que nada, fprintf no es apta para archivos binarios, para eso usarías algo como fwrite. Pero además, lo que deduzco de lo que dices es que guardaste el contenido de la cabecera generada por GIMP en un archivo con extensión bmp, ¿cierto? Porque tampoco puedes hacer eso. Cada formato tiene su estructura y su forma de almacenar la información. El bmp lo debes generar desde GIMP o cualquier otro editor de imágenes, y luego, lo abres en tu programa y lo muestras en la ventana.

Hay varias formas de hacerlo. Una es cargarlo con LoadImage y usar funciones de GDI para copiarlo a un DC de memoria y luego de ahí a tu ventana, con la función BitBlt. A mí no me gusta esta forma, ya que limita lo que puedes hacer, pero es la más simple. Me parece mejor abrir y leer el archivo por uno mismo, y supongo que también es lo que te serviría más si quieres usar SetPixel. Aquí leerías del archivo (con fread), primero una estructura BITMAPFILEHEADER, y usando la información que contendrá la estructura, procedes a reservar memoria para un puntero unsigned char, y leer ahí los pixels, igualmente con fread. La otra opción, la más didáctica y que te da más control, y que te recomendaría si te interesa la programación gráfica, es leer todo el archivo "manualmente". Como te mencioné, el formato BMP es muy simple. Tienes una descripción en la Wikipedia, que aunque parece complicada, no lo es. Es larga porque explica todos los campos de las dos cabeceras que contienen los BMP, pero en realidad sólo unos cuantos son importantes. Realmente con un par de horas que le dediques podrías tener lista una función o funciones para leer bmps. O si no, ahí tienes las otras dos opciones para elegir. Ya sólo toca leer un poco y programar.

e

Pues literalmente fui haciendo un fprintf, escribiendo cada byte como un char y lo guardaba en el bmp, y funciona.

Y gracias, probaré con lo que me has dicho  ;D.
e

RayR

Sí, naturalmente, fprintf va a guardar los caracteres que le digas, pero el resultado no es un bmp. Como te dije, los bmp, igual que cualquier otro formato, tienen una estructura específica: dos cabeceras con información del archivo, y además los valores de color de los pixels deben seguir un orden específico que determina el formato, y algunas otras cosas. Sólo un archivo que contenga todo esto es un bmp, porque independientemente de la extensión, lo que define el tipo de un archivo es su contenido. Y también te decía que para eso no podrías usar fprintf, ya que esta función guarda texto. El BMP es un formato binario y, entre otras cosas, sus cabeceras contienen algunos campos que son enteros de 16 y 32 bits. Esos no los puedes guardar con fprintf porque los convertirá a caracteres. Por ejemplo, si tu imagen tiene un ancho de 1280 pixels, al intentar guardar el campo que especifica esa información, lo que en realidad se escribirá no será ese valor, sino los códigos ASCII de los caracteres '1', 2', '8' y '0'. Y así con cualquier otro número. Es decir, vas a tener un archivo no válido. En realidad sí hay alguna forma en que se podría hacer, pero requeriría bastante trabajo y sería muy ineficiente, ya que básicamente sería forzar a fprintf a hacer algo para lo que no fue diseñada. frwite es la función a usar para información binaria.

De cualquier forma, lo que yo te recomendaba era que escribieras alguna función para poder leer archivos bmp. De esa manera puedes crear las imágenes con prácticamente cualquier editor de imágenes, no sólo GIMP, y te evitas tener que lidiar con esa cabecera generada. Naturalmente, para esto tampoco usarías una función de lectura de texto como fscanf, sino fread.