MAC2166 - Introdução à Computação

12/06/2017 - Aula 21 - Criação de arquivos de imagem

Problema 21.1

Dado um número inteiro ímpar n>0, faça uma função molduras_concentricas(n, v1, v2) que gera uma matriz quadrada nxn preenchida com um padrão de molduras concêntricas, alternando entre dois valores fornecidos v1 e v2 como nos exemplos.

Para n=5, v1=0, v2=1:

[[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]]

Para n=7, v1=0, v2=1:

[[1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1]]

Para n=15, v1=0, v2=1:

[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1], [1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1], [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

In [10]:
def cria_matriz(m, n, valor):
    '''(int,int,int) -> list
       Cria matriz com m linhas e n colunas, sendo que toda
       as posições da matriz contém o valor passado no 
       parâmetro "valor".
    '''
    M = []
    for i in range(m):
        linha = []
        for j in range(n):
            linha.append(valor)
        M.append(linha)
    return M


def molduras_concentricas(n, v1, v2):
    ''' (int,int,int) -> list
        Cria matriz com n linhas e n colunas preenchida com um padrão de molduras concêntricas, 
        alternando entre os dois valores fornecidos v1 e v2
    '''
    # Cria matriz com m linhas e n colunas
    M = cria_matriz(n, n, -1)  # cria matriz nxn; o valor nas posições não é importante
    
    for i in range(n):
        for j in range(n):
            #dh = distancia horizontal ao centro
            dh = n//2 - j
            if dh < 0:
                dh = -dh
            #dv = distancia vertical ao centro
            dv = n//2 - i
            if dv < 0:
                dv = -dv
            
            # d = max(dv, dh)
            if dh > dv:
                d = dh
            else:
                d = dv
                
            if d % 2 == 0: 
                M[i][j] = v1  # molduras que estão a uma distância par do centro, têm "cor" v1
            else:
                M[i][j] = v2  # molduras que estão a uma distância ímpar do centro, têm "cor" v2
    return M

########################################
# Teste
# Para n=7, v1=0, v2=1:
mat = (molduras_concentricas(7, 0, 1))
for linha in mat:
    print(linha)
[1, 1, 1, 1, 1, 1, 1]
[1, 0, 0, 0, 0, 0, 1]
[1, 0, 1, 1, 1, 0, 1]
[1, 0, 1, 0, 1, 0, 1]
[1, 0, 1, 1, 1, 0, 1]
[1, 0, 0, 0, 0, 0, 1]
[1, 1, 1, 1, 1, 1, 1]

Problema 21.2:

Faça um programa que gera uma imagem em tons de cinza no formato PGM (Portable Gray Map) do padrão gerado no Problema 21.2, usando zero (preto) para v1 e 255 (branco) para v2.

Uma explicação sobre o formato de imagem PGM pode ser encontrado aqui.

Solução:

In [9]:
def cria_matriz(m, n, valor):
    '''(int,int,int) -> list
       Cria matriz com m linhas e n colunas, sendo que toda
       as posições da matriz contém o valor passado no 
       parâmetro "valor".
    '''
    M = []
    for i in range(m):
        linha = []
        for j in range(n):
            linha.append(valor)
        M.append(linha)
    return M


def molduras_concentricas(n, v1, v2):
    ''' (int,int,int) -> list
        Cria matriz com n linhas e n colunas preenchida com um padrão de molduras concêntricas, 
        alternando entre os dois valores fornecidos v1 e v2
    '''
    # Cria matriz com m linhas e n colunas
    M = cria_matriz(n, n, -1)  # cria matriz nxn; o valor nas posições não é importante
    
    for i in range(n):
        for j in range(n):
            #dh = distancia horizontal ao centro
            dh = n//2 - j
            if dh < 0:
                dh = -dh
            #dv = distancia vertical ao centro
            dv = n//2 - i
            if dv < 0:
                dv = -dv
            
            # d = max(dv, dh)
            if dh > dv:
                d = dh
            else:
                d = dv
                
            if d % 2 == 0:
                M[i][j] = v1
            else:
                M[i][j] = v2
    return M

def grava_PGM(nome_arq_sem_extensao, M):
    ''' (str, list) -> None
        Grava em um arquivo PGM a imagem armazenada na matriz M.
    '''
    arquivo = open(nome_arq_sem_extensao + ".pgm", 'w')
    
    # Grava as três primeiras linhas do arquivo
    arquivo.write("P2\n")  # Linha 1:  "P2" indica que o arquivo é um arquivo de imagem PGM simples
    m = len(M)
    n = len(M[0])
    arquivo.write("%d %d\n" %(n,m))  # Linha 2: largura (número de colunas) e altura (número de linhas) da imagem
    arquivo.write("255\n")           # Maior valor de intensidade (de cor) que o arquivo contém; 255 neste caso
    
    # Grava os pixels (pontos) da imagem
    for i in range(m):
        for j in range(n):
            arquivo.write(" %3d"% (M[i][j]))
        arquivo.write("\n")
    arquivo.close()


def main():
    n = int(input("Digite a altura (= largura) da imagem: "))
    nome_arq = input("Digite o nome do arquivo (sem extensão) onde a imagem será gravada: ")
    M = molduras_concentricas(n, 0, 255)
    grava_PGM(nome_arq, M)
 
    
main()
Digite a altura (= largura) da imagem: 101
Digite o nome do arquivo (sem extensão) onde a imagem será gravada: imagem101

A execução acima gera um arquivo chamado imagem101.pgm que corresponde à imagem abaixo:

Molduras concêntricas