Zoom subpíxel

9

Su tarea es tomar una imagen sRGB de 24 BPP y generar la misma imagen escalada 3x en subpíxeles rojo, verde y azul. La imagen resultante estará hecha completamente de píxeles negros, rojos, verdes y azules puros.

Cada píxel de la imagen de origen, cuando se amplía, produce una disposición de 9 subpíxeles que pueden estar activados o desactivados (es decir, su color respectivo o negro). La disposición específica utiliza tres columnas de rojo, verde y azul, en ese orden, así:

Subpíxeles RGB

(Tenga en cuenta que los bordes de estos "píxeles" son solo para demostración).

Dado que cada uno de los nueve subpíxeles solo puede activarse o desactivarse, tendrá que cuantificar la imagen de entrada y usar diferentes patrones de subpíxeles para lograr 3 niveles de brillo.

Para cada subpíxel en la imagen:

  • Para los niveles de color 0-74, todos los subpíxeles deben ser negros.
  • Para los niveles de color 75-134, el subpíxel medio debe ser el color respectivo y los otros dos deben ser negros.
  • Para los niveles de color 135-179, el subpíxel del medio debe ser negro y los otros dos deben ser del color respectivo
  • Para los niveles de color 180-255, los tres subpíxeles deben ser sus respectivos colores.

Elegí estos rangos de nivel porque es lo que pasó a verse bien

Aplique esta transformación a cada píxel en la imagen y genere la imagen subescalada.

Ejemplos de un solo píxel

rgb (40, 130, 175) producirá este patrón:

00B / 0G0 / 00B

rgb (160, 240, 100) producirá este patrón:

RG0 / 0GB / RG0

Ejemplos de imagen completa

Mona Lisa Mona Lisa Subpixels

Noche estrellada Noche estrellada subpíxeles

Loro Subpíxeles de loro

Imágenes procedentes de Wikipedia

Reglas y notas

  • La entrada y salida pueden estar en cualquier formato conveniente, ya sean archivos de imágenes reales o (posiblemente anidados) listas de valores RGB.
  • Puede suponer que los píxeles están en el espacio de color sRGB con 24BPP.

¡Feliz golf!

Carne de res
fuente
2
La descripción inicial suena como no Bayering. Resulta que no lo es, en parte debido a la máscara 3x3 no convencional, pero principalmente debido a la cuantización, pero IMO todavía está más cerca de la eliminación de Bayering que del zoom de subpíxeles (lo que sería un aumento de escala con algún tipo de detección de bordes para anti - alias).
Peter Taylor
gracias por un desafío interesante ... ¿se usa esto realmente para algo en la vida real?
Don brillante

Respuestas:

4

JavaScript (Nodo, Chrome, Firefox), 111 bytes

Formato de E / S: matriz de [R,G,B]valores.

a=>[...a,...a,...a].map((r,y)=>r.flat().map((_,x)=>a[y/3|0][x/3|0].map(v=>x--%3|511+y%3%2*3104>>v/15&1?0:255)))

Pruébalo en línea! (solo un píxel)

¿Cómo?

Todos los valores de umbral son múltiplos de 15. En lugar de hacer pruebas de comparación explícitas, es un poco más corto probar una máscara de bits donde cada bit representa un intervalo de 15 valores (excepto el bit más significativo que se asigna a un solo valor).

 bit | range   | top/bottom | middle
-----+---------+------------+--------
  0  |   0- 14 |     off    |   off
  1  |  15- 29 |     off    |   off
  2  |  30- 44 |     off    |   off
  3  |  45- 59 |     off    |   off
  4  |  60- 74 |     off    |   off
  5  |  75- 89 |     off    |    on
  6  |  90-104 |     off    |    on
  7  | 105-119 |     off    |    on
  8  | 120-134 |     off    |    on
  9  | 135-149 |      on    |   off
 10  | 150-164 |      on    |   off
 11  | 165-179 |      on    |   off
 12  | 180-194 |      on    |    on
 13  | 195-209 |      on    |    on
 14  | 210-224 |      on    |    on
 15  | 225-239 |      on    |    on
 16  | 240-254 |      on    |    on
 17  |   255   |      on    |    on

10 0

Obtenemos:

  • 000000000111111111511
  • 0000001110000111113615

Comentado

a =>                      // a[] = input matrix
  [...a, ...a, ...a]      // create a new matrix with 3 times more rows
  .map((r, y) =>          // for each row r[] at position y:
    r.flat()              //   turn [[R,G,B],[R,G,B],...] into [R,G,B,R,G,B,...]
                          //   i.e. create a new list with 3 times more columns
    .map((_, x) =>        //   for each value at position x:
      a[y / 3 | 0]        //     get [R,G,B] from the original matrix
       [x / 3 | 0]        //     for the pixel at position (floor(x/3), floor(y/3))
      .map(v =>           //     for each component v:
        x-- % 3 |         //       1) yield a non-zero value if this is not the component
                          //          that we're interested in at this position
        511 +             //       2) use either 511 for top and bottom pixels
        y % 3 % 2 * 3104  //          or 3615 for the middle pixel (y mod 3 = 1)
        >> v / 15         //          divide v by 15
        & 1               //          and test the corresponding bit
        ?                 //       if either of the above tests is truthy:
          0               //         yield 0
        :                 //       else:
          255             //         yield 255
      )                   //     end of map() over RGB components
    )                     //   end of map() over columns
  )                       // end of map() over rows

Ejemplo

El siguiente fragmento de código procesa la cabeza de Mona Lisa (64x64). No funciona en Edge.

Arnauld
fuente
3

Jalea , 27 bytes

<“⁷KṆ‘‘Ḅœ?Ɗo⁹’)×€"3⁼þ¤)ẎZ)Ẏ

[0 0,255][r, g, b]

Pruébalo en línea! Este ejemplo toma una imagen de dos por dos donde el píxel superior izquierdo es el primer píxel de ejemplo, el píxel superior derecho es el segundo píxel de ejemplo, el píxel inferior izquierdo es un píxel negro y el píxel inferior derecho es un blanco píxel

¿Cómo?

<“⁷KṆ‘‘Ḅœ?Ɗo⁹’)×€"3⁼þ¤)ẎZ)Ẏ - Link: list of lists of lists of integers, I
                         )  - for each row, R, in I:
                      )     -   for each pixel, P, in R:
              )             -     for each integer, C, in P:
 “⁷KṆ‘                      -       list of code-page indices = [135,75,180]
<                           -       less than -> [C<135,C<75,C<180] 
          Ɗ                 -       last three links as a monad:
      ‘                     -         increment -> [1+(C<135),1+(C<75),1+(C<180)]
       Ḅ                    -         from binary -> 4*(1+(C<135))+2*(1+(C<75))+1+(C<180)
        œ?                  -         permutation at that index of [C<135,C<75,C<180]
                            -         when all permutations sorted lexicographically
                            -       ... a no-op for all but [0,0,1]->[0,1,0]
            ⁹               -       256
           o                -       logical OR  e.g. [0,1,0]->[256,1,256]
             ’              -       decrement               ->[255,0,255]
                     ¤      -     nilad followed by link(s) as a nilad:
                  3         -       three
                    þ       -       table with: (i.e. [1,2,3] . [1,2,3])
                   ⁼        -         equal?    -> [[1,0,0],[0,1,0],[0,0,1]]
                 "          -     zip with:
                €           -       for each:
               ×            -         multiply
                       Ẏ    -   tighten (reduce with concatenation)
                        Z   -   transpose
                          Ẏ - tighten
Jonathan Allan
fuente
Estoy tratando de averiguar dónde codifica [[1,0,0]. [0,1,0], [0,0,1]] y estoy desconcertado.
Don brillante
@donbright 3⁼þ¤realiza un producto externo de [1,2,3]=[1,2,3]rendimiento [[1=1,2=1,3=1],[2=1,2=2,2=3],[3=1,3=2,3=3]]que es [[1,0,0],[0,1,0],[0,0,1]].
Jonathan Allan el
2

Wolfram Language (Mathematica) , 186 bytes

Entrada y salida son listas de valores RGB

(g=#;Flatten[(T=Transpose)@Flatten[T/@{{#,v={0,0,0},v},{v,#2,v},{v,v,#3}}&@@(If[(l=Max@#)<75,v,If[74<l<135,{0,l,0},If[134<l<179,{l,0,l},{l,l,l}]]]&/@#)&/@g[[#]],1]&/@Range[Length@g],1])&

Pruébalo en línea!


Wolfram Language (Mathematica), 243 bytes

este segundo código es una función que toma como entrada una imagen y genera una imagen
(no sé por qué las personas se confundieron en los comentarios)

Entonces, si alimentas a este img

ingrese la descripción de la imagen aquí

en esta función

(i=#;Image[Flatten[(T=Transpose)@Flatten[T/@{{#,v={0,0,0},v},{v,#2,v},{v,v,#3}}&@@(If[(l=Max@#)<75,v,If[74<l<135,{0,l,0},If[134<l<179,{l,0,l},{l,l,l}]]]&/@#)&/@ImageData[i,"Byte"][[#]],1]&/@Range[Last@ImageDimensions@i],1],ColorSpace->"RGB"])&


obtendrás esta salida

ingrese la descripción de la imagen aquí

J42161217
fuente
2
¿No contaría esto como una entrada codificada?
attinat
"La entrada y la salida pueden estar en cualquier formato conveniente, ya sean archivos de imagen reales ...". No, ies una imagen.
J42161217
Estoy de acuerdo con @attinat, parece un hardcoding.
Jonathan Frech
Hice algunos cambios y espero que todo esté claro ahora.
J42161217
1

C # (compilador interactivo de Visual C #) , 157 bytes

n=>{int i=0,j=n[0].Length;for(;;Write(z(0)+",0,0|0,"+z(1)+",0|0,0,"+z(2)+"\n|"[++i%j&1]));int z(int k)=>(((511^i/j%3%2*4064)>>n[i/j/3][i%j][k]/15)&1^1)*255;}

Imprime el RGB de la salida. La salida está separada por una nueva línea y no está alineada. Originalmente, usaba una máscara de bits para 1estar encendido y 0apagado, pero luego vi la respuesta de Arnauld, y me di cuenta de que usarlo 0como encendido y 1apagado podría ahorrar bytes en el número. El enlace TIO contiene una "imagen" de muestra de 4 por 2 píxeles.

Pruébalo en línea!

Encarnación de la ignorancia
fuente
0

APL + WIN, 102 bytes

Solicita una matriz 2D de píxeles como números enteros de 24 bits como aparecerían en la imagen

((⍴a)⍴,3 3⍴255*⍳3)×a←(3 1×⍴m)⍴∊⍉((1↓⍴m)/⍳↑⍴m)⊂n←(-+⌿n)⊖n←1 0↓0 75 135 180∘.≤,m←(1 3×⍴m)⍴,⍉(3⍴256)⊤,m←⎕

Pruébalo en línea! Cortesía de Dyalog Classic.

Emite una matriz 2D de enteros de 24 bits de la imagen transformada. La mayor parte del código maneja el formato de la entrada y salida.

Ejemplo: tome una imagen de 2 x 2 compuesta por los píxeles de muestra

Entrada:

2654895 10547300
2654895 10547300

Salida:.

0     0 16581375 255 65025        0
0 65025        0   0 65025 16581375
0     0 16581375 255 65025        0
0     0 16581375 255 65025        0
0 65025        0   0 65025 16581375
0     0 16581375 255 65025        0
Graham
fuente
0

Óxido - 281 bytes

fn z(p:Vec<u8>,wh:[usize;2])->Vec<u8>{let mut o=vec![0;wh[0]*wh[1]*27];for m in 0..wh[0]{for n in 0..wh[1]{for i in 1..=3{for j in 0..3{o[m*9+n*wh[0]*27+j*wh[0]*9+i*2]=match p[18+m*3+n*wh[0]*3+3-i]{75..=134=>[0,1,0],135..=179=>[1,0,1],180..=255=>[1,1,1],_=>[0,0,0],}[j]*255;}}}}o}

Esta línea es una función que cumple con el desafío, sin embargo, su entrada es en realidad datos en el formato de archivo TGA como se describe en paulbourke.net , junto con el ancho y la altura previamente analizados, en píxeles, de la imagen. Devuelve datos de píxeles para la salida, como bytes, en un vector 9 veces el tamaño de los datos de píxeles de entrada.

use std::fs::File;use std::io::{Read,Write};fn main(){let mut p=vec![];let mut o=vec![0u8;18];File::open("i.tga").unwrap().read_to_end(&mut p).unwrap();let mut wh=[0;2];let h=|x|p[x] as usize;let g=|x|(3*x/256) as u8;for i in 0..2{wh[i]=h(12+i*2)+256*h(13+i*2);o[12+i*2]=g(wh[i]*256);o[13+i*2]=g(wh[i]);}let mut f=File::create("o.tga").unwrap();o[2]=2;o[16]=24;o.extend(z(p,wh));f.write(&o).unwrap();}

Esta segunda línea es una función main () que puede transformar un archivo de entrada llamado i.tga en un archivo de salida llamado o.tga, llamando a la función z desde la primera línea, sin usar ninguna biblioteca externa. Maneja el análisis de ancho / alto, creando un encabezado para el archivo de salida y lectura + escritura de archivos. Agregaría 402 bytes si el desafío requiere E / S de archivo, para un total de 683. Es útil para las pruebas.

don brillante
fuente