Darle la vuelta, dejarlo caer, decirlo en serio

24

Visión general

Dada una imagen en formato PPM simple (P3) como entrada, para cada píxel pen la imagen, reemplace cada uno de los siguientes 4 píxeles rojo, verde y azul con el valor promedio de los canales respectivos de los 4 píxeles:

  1. p sí mismo

  2. El píxel ubicado en pla ubicación de cuando la imagen se voltea verticalmente

  3. El píxel ubicado en pla ubicación de cuando la imagen se voltea horizontalmente

  4. El píxel ubicado en pla ubicación de cuando la imagen se voltea tanto vertical como horizontalmente

Imprima la imagen resultante en formato PPM (P3) simple.

Para una explicación más detallada, considere esta imagen de 8x8, ampliada a 128x128:

paso 2 ejemplo

Deja que psea ​​el píxel rojo. Para calcular el nuevo valor de p(y los 3 píxeles azules), los valores de py los 3 píxeles azules se promediarán juntos:

p1 = (255, 0, 0)
p2 = (0, 0, 255)
p3 = (0, 0, 255)
p4 = (0, 0, 255)
p_result = (63, 0, 191)

Ejemplos

PPM: entrada , salida


PPM: entrada , salida


PPM: entrada , salida


PPM: entrada , salida


Implementación de referencia

#!/usr/bin/python

import sys
from itertools import *

def grouper(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return list(izip_longest(*args, fillvalue=fillvalue))

def flatten(lst):
    return sum(([x] if not isinstance(x, list) else flatten(x) for x in lst), [])

def pnm_to_bin(p):
    w,h = map(int,p[1].split(' '))
    data = map(int, ' '.join(p[3:]).replace('\n', ' ').split())
    bin = []
    lines = grouper(data, w*3)
    for line in lines:
        data = []
        for rgb in grouper(line, 3):
            data.append(list(rgb))
        bin.append(data)
    return bin

def bin_to_pnm(b):
    pnm = 'P3 {} {} 255 '.format(len(b[0]), len(b))
    b = flatten(b)
    pnm += ' '.join(map(str, b))
    return pnm

def imageblender(img):
    h = len(img)
    w = len(img[0])
    for y in range(w):
        for x in range(h):
            for i in range(3):
                val = (img[x][y][i] + img[x][~y][i] + img[~x][y][i] + img[~x][~y][i])//4
                img[x][y][i],img[x][~y][i],img[~x][y][i],img[~x][~y][i] = (val,)*4
    return img

def main(fname):
    bin = pnm_to_bin(open(fname).read().split('\n'))
    bin = imageblender(bin)
    return bin_to_pnm(bin)

if __name__ == '__main__':
    print main(sys.argv[1])

Este programa toma un solo nombre de archivo como entrada, formateado como la salida de pngtopnm <pngfile> -plain, y genera una sola línea de datos PPM separados por espacios.


Una breve descripción del formato P3

Un archivo de texto sin formato PPM generado a partir de este pngtopnm <pngfile> -plainse verá así:

P3
<width in pixels> <height in pixels>
<maximum value as defined by the bit depth, always 255 for our purposes>
<leftmost 24 pixels of row 1, in RGB triples, space-separated; like (0 0 0 1 1 1 ...)>
<next 24 pixels of row 1>
<...>
<rightmost (up to) 24 pixels of row 1>

<leftmost 24 pixels of row 2>
<next 24 pixels of row 2>
<...>
<rightmost (up to) 24 pixels of row 2>

<...>

Este es el formato que utilizan los archivos de entrada y salida de ejemplo. Sin embargo, PNM es muy flojo sobre su formato: cualquier espacio en blanco puede separar valores. Puede reemplazar todas las líneas nuevas en el archivo anterior con un solo espacio cada una, y aún así tener un archivo válido. Por ejemplo, este archivo y este archivo son válidos y representan la misma imagen. Los únicos otros requisitos son que el archivo debe terminar con una nueva línea final, y debe haber width*heighttripletes RGB después de 255.


Reglas

  • Esto es , por lo que gana la solución válida más corta.
  • Puede ingresar y enviar datos PPM formateados de manera conveniente y consistente, siempre que sean válidos de acuerdo con el formato PPM descrito anteriormente. La única excepción es que debe usar el formato plano (P3) y no el formato binario (P6).
  • Debe proporcionar la verificación de que su solución genera las imágenes correctas para las imágenes de prueba anteriores.
  • Todas las imágenes tendrán una profundidad de 8 bits.

Lectura adicional: página de Wikipedia en formato Netpbm


Prueba de fragmentos (gracias a los pasatiempos de Calvin por esto)

Mego
fuente
¿Están permitidas las bibliotecas de imágenes que abren / guardan archivos ppm?
Aficiones de Calvin
@ Calvin'sHobbies Sí
Mego
3
" Dale la vuelta, déjalo, promételo
Luis Mendo
3
¿Tal vez "voltearlo, dejarlo caer en serio"?
Conor O'Brien el
2
@ CᴏɴᴏʀO'Bʀɪᴇɴ Eso suena como una fiesta antes, oh, espera, lo que Luis publicó.
Addison Crump

Respuestas:

4

Pyth, 30 29 bytes

zjms.OdC.nM[JrR7.zKm_cd3J_J_K

Mi programa espera todos los metadatos en la primera línea, y los datos de la imagen fila por fila en las líneas después de stdin. Para ayudar, este es un pequeño programa de Python para convertir cualquier archivo PPM válido en un archivo PPM que mi programa pueda entender:

import sys
p3, w, h, d, *data = sys.stdin.read().split()
print(p3, w, h, d)
for i in range(0, int(w) * int(h), int(w)):
    print(" ".join(data[i:i+int(w)]))

Una vez que tiene los datos de la imagen fila por fila, las operaciones son realmente simples. Primero leo los datos de la imagen en una lista de listas de enteros ( JrR7.z), luego creo la versión reflejada horizontalmente agrupando cada 3 enteros e invirtiéndolos para cada fila ( Km_cd3J). Entonces las versiones espejadas verticalmente son simplemente_J_K , ya que podemos simplemente revertir filas.

Tomo todas esas matrices, las aplasto en una matriz 1d .nM, las transpongo Cpara obtener una lista de listas de cada uno de los componentes de píxeles, promedio y trunco ​​en int cada una de esas listas ( ms.Od), y finalmente imprimo unidas por nuevas líneasj .

Tenga en cuenta que mi programa genera resultados en un formato diferente (pero aún válido PPM). Las imágenes de demostración se pueden ver en este álbum de imgur .

orlp
fuente
13

Bash (+ ImageMagick), 64 + 1 = 65 bytes

C=convert;$C a -flip b;$C a -flop c;$C c -flip d;$C * -average e

Herramienta adecuada para el trabajo.

Debe ejecutarse en un directorio que contenga un único archivo aque contenga los datos PPM para transformar. Como este nombre de archivo es significativo, he agregado un byte al recuento de bytes.

Salidas en miniatura PNG (no estoy seguro de por qué esto es necesario porque de todos modos son todas iguales, pero la pregunta lo dice, así que ...):

pingüino quintapia Peter minibits

¡Gracias a nneonneo por guardar 2 bytes!

Pomo de la puerta
fuente
3
Exijo los resultados porque la gente tiene la mala costumbre de publicar soluciones sin probarlas. +1 para -flop, realmente quiero sorprenderme de que sea una bandera.
Mego
1
Afeite 2 bytes usando C=converty en $Clugar de alias.
nneonneo
12

Matlab, 106 82 80 bytes

i=imread(input(''))/4;for k=1:2;i=i+flipdim(i,k);end;imwrite(i,'p3.pnm','e','A')

La imagen se carga como n*m*3matriz. Luego volteamos la matriz y la agregamos a sí misma para ambos ejes, y la escribimos nuevamente en un archivo.


No pude encontrar un lugar para cargar archivos de texto tan grandes, así que aquí están las versiones PNG:

falla
fuente
Omg, ¡ni siquiera sabía que podías usar <imgetiquetas!
flawr
1
En MATLAB R2013b y versiones posteriores, es posible usar flip en lugar de flipdim . Eso debería ahorrarte 3 bytes más. La ayuda de flipdim en realidad dice: "flipdim se eliminará en una versión futura. Utilice FLIP en su lugar".
slvrbld
10

Mathematica, 86 84 bytes

Gracias a DavidC por el consejo. (ahorra 2 bytes)

Export[#2,⌊Mean@Join[#,(r=Reverse)/@#]&@{#,r/@#}&@Import[#,"Data"]⌋~Image~"Byte"]&

El primer y segundo parámetro son las rutas a las imágenes de entrada y salida, respectivamente.


Casos de prueba

f=%; (assign the function to symbol f)
f["penguin.pnm","penguin2.pnm"]
f["quintopia.pnm","quintopia2.pnm"]
f["peter.pnm","peter2.pnm"]

Resultado

(Las versiones PNG de las imágenes se cargan a continuación)

Import["penguin2.pnm"]

Import["quintopia2.pnm"]

Import["peter2.pnm"]

njpipeorgan
fuente
Join[#,(r=Reverse)/@#]
DavidC
4

Julia, 157 bytes

using FileIO
s->(a=load(s);b=deepcopy(a);d=a.data;(n,m)=size(d);for i=1:n,j=1:m b.data[i,j]=mean([d[i,j];d[n-i+1,j];d[i,m-j+1];d[n-i+1,m-j+1]])end;save(s,b))

Esta es una función lambda que acepta una cadena que contiene la ruta completa a un archivo PPM y la sobrescribe con la imagen transformada. Para llamarlo, asígnelo a una variable.

Sin golf:

using FileIO

function f(s::AbstractString)
    # Load the input image
    a = load(s)

    # Create a copy (overwriting does bad things)
    b = deepcopy(a)

    # Extract the matrix of RGB triples from the input
    d = a.data

    # Store the size of the matrix
    n, m = size(d)

    # Apply the transformation
    # Note that we don't floor the mean; this is because the RGB values
    # aren't stored as integers, they're fixed point values in [0,1].
    # Simply taking the mean produces the desired output.
    for i = 1:n, j = 1:m
        b.data[i,j] = mean([d[i,j]; d[n-i+1,j]; d[i,m-j+1]; d[n-i+1,m-j+1]])
    end

    # Overwrite the input
    save(s, b)
end

Salidas de ejemplo:

pingüino quintapia Peter minibits

Alex A.
fuente
4

pitón 2 + PIL, 268

Ahora uso masivamente PIL, usando volteo de imagen y mezcla alfa

from PIL import Image
I=Image
B,T=I.blend,I.FLIP_TOP_BOTTOM
a=I.open(raw_input()).convert('RGB')
exec'[email protected]_LEFT_RIGHT);c=a@T);d=b@T)'.replace('@','.transpose(')
x,y=a.size
print'P3',x,y,255
for r,g,b in list(B(B(B(a,b,0.5),c,0.25),d,0.25).getdata()):print r,g,b

Las imágenes resultantes están disponibles aquí.

dieter
fuente
1
Incluya los resultados para los casos de prueba, según lo exijan las reglas.
Mego