Publi

#tuentiContest solución del Challenge 14 en C. Colours are beautiful

Presento aquí mi solución al reto 14, en el que nos pasan una imagen en BMP, y por la stdin nos dan una componente (R, G, B) y un número de línea. Tenemos que hacer la suma de los valores de esa componente a lo largo de la línea especificada, y luego sumar 1.

Para ello, vamos a valernos del post dedicado a la lectura de archivos BMP en C, esta será una de las aplicaciones que vamos a hacer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#define STRSIZE 1000

typedef struct bmpFileHeader
{
  uint32_t size;
  uint16_t resv1;
  uint16_t resv2;
  uint32_t offset;
} bmpFileHeader;

typedef struct bmpInfoHeader
{
  uint32_t headersize;      /* DIB header size */
  uint32_t width;
  uint32_t height;
  uint16_t planes;         /* color planes */
  uint16_t bpp;            /* bits per pixel */
  uint32_t compress;
  uint32_t imgsize;    
  uint32_t bpmx;        /* X bits per meter */
  uint32_t bpmy;        /* Y bits per meter */
  uint32_t colors;      /* colors used */
  uint32_t imxtcolors;      /* important colors */
} bmpInfoHeader;

/* old function I made */
unsigned char *LoadBMP(char *filename, bmpInfoHeader *bInfoHeader);
int calculate_sum(bmpInfoHeader *info, unsigned char *img, char rgb, int line);

int main()
{
  bmpInfoHeader info;
  unsigned char *img;
  char bigstr[STRSIZE];
  int line_number;

  img=LoadBMP("trabaja.bmp", &info);

  while (fgets(bigstr, STRSIZE, stdin)!=NULL)
    {
      line_number=info.height-atoi(bigstr+1)-1; /* bmps are inverted. Line 0 is count*/
      printf("%d\n", calculate_sum(&info, img, bigstr[0],line_number));
    }

  return 0;
}

unsigned char *LoadBMP(char *filename, bmpInfoHeader *bInfoHeader)
{

  FILE *f;
  bmpFileHeader header;
  unsigned char *imgdata;
  uint16_t type;
  f=fopen (filename, "r");
  /* handle open error */
  fread(&type, sizeof(uint16_t), 1, f);
  if (type !=0x4D42)
    {
      fclose(f);
      return NULL;
    }
  fread(&header, sizeof(bmpFileHeader), 1, f);

  fread(bInfoHeader, sizeof(bmpInfoHeader), 1, f);
  imgdata=(unsigned char*)malloc(bInfoHeader->imgsize);
  fseek(f, header.offset, SEEK_SET);
  fread(imgdata, bInfoHeader->imgsize,1, f);
  fclose(f);

  return imgdata;
}

int calculate_sum(bmpInfoHeader *info, unsigned char *img, char rgb, int line)
{
  int i;
  int sum=0;
  int comp;
  char *bgr="BGR";
  char *tcomp=strchr(bgr, rgb);
  if (tcomp==NULL)
    return 0;

  comp=tcomp-bgr;

  for (i=0; i<info->width; i++)
    {
      sum+=img[3*(i+line*info->width)+comp];
    }
 
  return sum+1;
}

Ya que las cabeceras y la función LoadBMP() ya están analizadas en el post anterior. Analizaremos las funciones calculate_sum() y la principal.

En calculate_sum(), lo que hacemos es primero, obtener el número de la componente a extraer, ya que B=0, G=1, R=2, hallaremos la posición del carácter en la cadena, y si éste existe (tcomp!=NULL), en la variable comp almacenaremos dicha posición (como strchr devuelve un puntero a la parte de la cadena correspondiente, sólo tenemos que restar con la cadena con la que comparamos.
Luego, hacemos un for para recorrer todos los puntos de la línea, pero sólo leyendo los datos de la componente seleccionada. En cada iteración incrementaremos la variable sum para que nos devuelva la suma total de todos los pixels.

En la función principal, lo único que hacemos es cargar en memoria el BMP, y leer por la stdin la entrada propuesta Wxxx, donde W es la componente a leer (R,G,B) y xxx es el número de línea a leer. Desde main() invertimos la línea (como ya dijimos en los BMP, la imagen está boca abajo), por lo que en lugar de leer la línea Y, debemos leer la línea [ ALTO – Y – 1 ] (restamos 1 porque la primera línea es la 0).

Tal vez para hacer la función calculate_sum() más general, debería haber hecho la conversión de línea dentro de ésta (la conversión es algo interno), y la suma de 1 (es algo que nos pide el problema).

También podría interesarte...

There are 5 comments left Ir a comentario

  1. Pingback: Bitacoras.com /

  2. Pingback: Poesía binaria » Recopilación de soluciones para los retos de #tuentiContest . Challenge #14 /

  3. Pingback: Poesía binaria » Salvando archivos de imagen BMP en C /

  4. guillermo /
    Usando Google Chrome Google Chrome 54.0.2840.99 en Windows Windows NT

    hola genio y figura que tal el archivo trabaja .bmp donde lo descargo o lo creo yo mismo .

    muy buena pagina te falta el pos para compartir en google+ , saludos

    gracias

    1. Gaspar Fernández / Post Author
      Usando Mozilla Firefox Mozilla Firefox 49.0 en Ubuntu Linux Ubuntu Linux

      Gracias Guillermo!!
      El archivo bmp lo puedes crear tú mismo. Eso sí, asegúrate de que sea formato bmp y sin comprimir.

      Es verdad, compartir en Google+ estaría bien, lo investigo y coloco el botón.

Leave a Reply