/*
 * Problema 21.  Suavização ("blurring") de imagens (variante do Problema
 * 12).
 * 
 * - Escreva um programa que lê uma imagem em formato PGM e cria uma
 *   versão suavizada dessa imagem.  Não imponha restrições no
 *   tamanho da imagem.  
 * 
 *   Veja https://www.ime.usp.br/~yoshi/2020i/mac2166/sandbox/2020.06.09/PGM/suavize.c
 */

#include <stdio.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0

int media(int **A, int i, int j, int M, int N);
void matriz_transformada(int **B, int **A, int M, int N);
int **leia_pgm(int *M, int *N, int *max_val);
void imprima_pgm(int **A, int M, int N, int max_val);
int valido(int i, int j, int M, int N);

int **malloc2d(int M, int N);
void free2d(int **A, int M);

void *mallocc(size_t nbytes);

int main(int argc, char *argv[])
{
  int k = atoi(argv[1]);
  int M, N, max_val;
  int **A;

  A = leia_pgm(&M, &N, &max_val);

  while (k-- > 0) {
    int **B = malloc2d(M, N);
    matriz_transformada(B, A, M, N);
    free2d(A, M);
    A = B;
  }
  
  imprima_pgm(A, M, N, max_val);
  free2d(A, M);
  return 0;
}

int valido(int i, int j, int M, int N)
{
  return 0 <= i && i < M && 0 <= j && j < N;
}

int media(int **A, int i, int j, int M, int N)
{
  int t = 0, l;
  int a[] = {0, 0, -1, -1, -1, 0, 1, 1, 1};
  int b[] = {0, 1, 1, 0, -1, -1, -1, 0, 1};
  int s = 0;

  for (l = 0; l < 9; l++)
    if (valido(i + a[l], j + b[l], M, N)) {
      t++;
      s += A[i + a[l]][j + b[l]]; 
    }
  
  return (int)(1.0*s / t + .5);
}

void matriz_transformada(int **B, int **A, int M, int N)
{
  int i, j;
  for (i = 0; i < M; i++) 
    for (j = 0; j < N; j++) 
      B[i][j] = media(A, i, j, M, N);
}
  
int **leia_pgm(int *M, int *N, int *max_val)
{
  char c;
  int i, j, MM, NN, lmax_val;
  int **A;
  scanf("%c", &c);
  scanf("%c", &c);
  scanf("%d %d", &NN, &MM);
  scanf("%d", &lmax_val);
  A = malloc2d(MM, NN);
  for (i = 0; i < MM; i++) 
    for (j = 0; j < NN; j++) 
      scanf("%d", &A[i][j]);
  *M = MM; *N = NN; *max_val = lmax_val;
  return A;
}

void imprima_pgm(int **A, int M, int N, int max_val)
{
  int i, j;
  printf("P2\n");
  printf("%d %d\n", N, M);
  printf("%d\n", max_val);
  for (i = 0; i < M; i++) {
    for (j = 0; j < N; j++) 
      printf("%03d ", A[i][j]);
    printf("\n");
  }
}

int **malloc2d(int M, int N)
{
  int i;
  int **t = mallocc(M * sizeof(int *));
  for (i = 0; i < M; i++)
    t[i] = mallocc(N * sizeof(int));
  return t;  
}

void free2d(int **A, int M)
{
  int i;
  for (i = 0; i < M; i++) 
    free(A[i]);
  free(A);
}

void *mallocc(size_t nbytes)
{
  void *ptr;
  ptr = malloc(nbytes);
  if (ptr == NULL) {
    printf ("Socorro! malloc devolveu NULL!\n");
    exit(EXIT_FAILURE); /* EXIT_FAILURE: definido pelo sistema */
  }
  return ptr;
}
