Zoom subpikselowy

9

Twoim zadaniem jest zrobienie zdjęcia sRGB 24 BPP i przesłanie tego samego obrazu w 3-krotnym powiększeniu do subpikseli czerwonych, zielonych i niebieskich. Powstały obraz zostanie w całości wykonany z czystych czarnych, czerwonych, zielonych i niebieskich pikseli.

Każdy piksel z obrazu źródłowego po powiększeniu tworzy układ 9 subpikseli, które można włączyć lub wyłączyć (tj. Ich odpowiedni kolor lub czerń). Konkretne ustawienie wykorzystuje trzy kolumny: czerwony, zielony i niebieski, w tej kolejności, w następujący sposób:

Subpiksele RGB

(Pamiętaj, że obramowania tych „pikseli” służą wyłącznie do celów demonstracyjnych).

Ponieważ każdy z dziewięciu subpikseli może być włączony lub wyłączony, będziesz musiał skwantyzować obraz wejściowy i użyć różnych wzorów subpikseli, aby osiągnąć 3 poziomy jasności.

Dla każdego podpiksela na obrazie:

  • W przypadku poziomów kolorów 0–74 wszystkie subpiksele powinny być czarne.
  • Dla poziomów koloru 75-134 środkowy podpiksel powinien mieć odpowiedni kolor, a pozostałe dwa powinny być czarne.
  • Dla poziomów koloru 135-179 środkowy podpiksel powinien być czarny, a pozostałe dwa powinny mieć odpowiedni kolor
  • Dla poziomów kolorów 180–255 wszystkie trzy subpiksele powinny mieć odpowiedni kolor

Wybrałem te zakresy poziomów, ponieważ wyglądały dobrze

Zastosuj tę transformację do każdego piksela w obrazie i wyślij obraz w powiększeniu subpikseli.

Przykłady pojedynczych pikseli

rgb (40, 130, 175) wygeneruje ten wzór:

00B / 0G0 / 00B

rgb (160, 240, 100) wygeneruje ten wzór:

RG0 / 0GB / RG0

Przykłady pełnego obrazu

Mona Lisa Mona Lisa Subpixels

Gwieździsta noc Gwiaździsta noc Subpiksele

Papuga Papugi Subpiksele

Obrazy pochodzą z Wikipedii

Zasady i notatki

  • Dane wejściowe i wyjściowe mogą być w dowolnym dogodnym formacie, niezależnie od tego, czy są to rzeczywiste pliki obrazów, czy (ewentualnie zagnieżdżone) listy wartości RGB.
  • Możesz założyć, że piksele znajdują się w przestrzeni kolorów sRGB z 24BPP.

Miłej gry w golfa!

Wołowina
źródło
2
Początkowy opis brzmi jak nie-Bayering. Okazuje się, że nie jest tak, częściowo ze względu na niekonwencjonalną maskę 3x3, ale głównie ze względu na kwantyzację, ale IMO jest jeszcze bliżej odblokowania Bayera niż powiększania subpikseli (co byłoby przeskalowaniem z pewnego rodzaju wykrywaniem krawędzi do anty- Alias).
Peter Taylor
dzięki za interesujące wyzwanie .... czy to jest rzeczywiście wykorzystywane do czegokolwiek w prawdziwym życiu?
don bright

Odpowiedzi:

4

JavaScript (Node, Chrome, Firefox), 111 bajtów

Format I / O: macierz [R,G,B]wartości.

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)))

Wypróbuj online! (tylko jeden piksel)

W jaki sposób?

Wszystkie wartości progowe są wielokrotności 15. Zamiast przeprowadzać jawne testy porównawcze, testowanie maski bitowej, w której każdy bit reprezentuje przedział 15 wartości, jest nieco krótszy (z wyjątkiem najbardziej znaczącego bitu, który jest odwzorowany na pojedynczą wartość).

 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

Kodujemy off jako1i na jak0 w celu maksymalizacji liczby zer wiodących.

Otrzymujemy:

  • 000000000111111111 dla górnych i dolnych pikseli (511 dziesiętnie)
  • 000000111000011111 dla środkowego piksela (3615 dziesiętnie)

Skomentował

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

Przykład

Poniższy fragment kodu przetwarza nagłówek Mona Lisa (64x64). Nie działa na Edge.

Arnauld
źródło
3

Galaretka , 27 bajtów

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

Monadyczny link akceptujący listę (obraz) list (wierszy) list (pikseli). Każdy piksel ma trzy liczby całkowite[0,255], [r, g, b]co daje wynik w tym samym formacie.

Wypróbuj online! W tym przykładzie wykonano zdjęcie dwa na dwa, w którym lewy górny piksel to pierwszy przykładowy piksel, prawy górny piksel to drugi przykładowy piksel, dolny lewy piksel to czarny piksel, a dolny prawy piksel to biały piksel.

W jaki sposób?

<“⁷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
źródło
Próbuję dowiedzieć się, gdzie to koduje [[1,0,0]. [0,1,0], [0,0,1]] i jestem zaskoczony.
don bright
@donbright 3⁼þ¤wykonuje zewnętrzny iloczyn [1,2,3]=[1,2,3]uzyskując [[1=1,2=1,3=1],[2=1,2=2,2=3],[3=1,3=2,3=3]]co [[1,0,0],[0,1,0],[0,0,1]].
Jonathan Allan
2

Wolfram Language (Mathematica) , 186 bajtów

Dane wejściowe i wyjściowe są listami wartości 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])&

Wypróbuj online!


Wolfram Language (Mathematica), 243 bajty

ten drugi kod jest funkcją, która pobiera jako obraz wejściowy i wyprowadza obraz
(nie wiem, dlaczego ludzie byli zdezorientowani w komentarzach)

Więc jeśli nakarmisz to img

wprowadź opis zdjęcia tutaj

do tej funkcji

(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"])&


dostaniesz ten wynik

wprowadź opis zdjęcia tutaj

J42161217
źródło
2
Czy nie byłoby to liczone jako zakodowane na stałe?
attinat
„Dane wejściowe i wyjściowe mogą być w dowolnym dogodnym formacie, niezależnie od tego, czy są to rzeczywiste pliki obrazów ...”. Nie, ito obraz.
J42161217,
Zgodziłbym się z @attinat, to wygląda na kodowanie.
Jonathan Frech
Wprowadziłem kilka zmian i mam nadzieję, że teraz wszystko jest jasne.
J42161217,
1

C # (interaktywny kompilator Visual C #) , 157 bajtów

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;}

Drukuje RGB wyniku. Wyjście jest oddzielone znakiem nowej linii i nie jest wyrównane. Początkowo używałem maski bitowej do włączania 1i 0wyłączania, ale potem zobaczyłem odpowiedź Arnaulda i zdałem sobie sprawę, że użycie włączania 0i 1wyłączania może zaoszczędzić bajty w liczbie. Łącze TIO zawiera przykładowy „obraz” o wymiarach 4 na 2 piksele.

Wypróbuj online!

Wcielenie ignorancji
źródło
0

APL + WIN, 102 bajty

Monituje o matrycę 2d pikseli jako 24-bitowe liczby całkowite, tak jak wyglądałyby na obrazie

((⍴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←⎕

Wypróbuj online! Dzięki uprzejmości Dyalog Classic

Wysyła 2d macierz 24-bitowych liczb całkowitych transformowanego obrazu. Większość kodu obsługuje formatowanie danych wejściowych i wyjściowych.

Przykład: Zrób zdjęcie 2 x 2 złożone z przykładowych pikseli

Wejście:

2654895 10547300
2654895 10547300

Wynik:.

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
źródło
0

Rdza - 281 bajtów

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}

Ta linia jest funkcją, która spełnia to wyzwanie, jednak jej dane wejściowe to w rzeczywistości dane w formacie pliku TGA, jak opisano na paulbourke.net , wraz ze wstępnie przeanalizowaną szerokością i wysokością obrazu (w pikselach). Zwraca dane pikselowe dla danych wyjściowych jako bajty w wektorze 9 razy większym niż rozmiar danych wejściowych w pikselach.

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();}

Ten drugi wiersz jest funkcją main (), która może przekształcić plik wejściowy o nazwie i.tga w plik wyjściowy o nazwie o.tga, wywołując funkcję z z pierwszego wiersza, bez użycia zewnętrznych bibliotek. Obsługuje parsowanie szerokości / wysokości, tworzenie nagłówka dla pliku wyjściowego oraz odczyt i zapis pliku. Dodałby 402 bajtów, gdyby wyzwanie wymagało We / Wy pliku, w sumie 683. Jest to przydatne do testowania.

Don Bright
źródło