Субпиксельное масштабирование


9

Ваша задача состоит в том, чтобы взять sRGB-изображение размером 24 BPP и вывести одно и то же изображение с 3-кратным увеличением в красный, зеленый и синий подпиксели. Полученное изображение будет полностью сделано из чисто черного, красного, зеленого и синего пикселей.

Каждый пиксель из исходного изображения при увеличении создает компоновку из 9 субпикселей, которые могут быть либо включены, либо выключены (т.е. их соответствующий цвет или черный). Конкретное расположение использует три столбца красного, зеленого и синего в следующем порядке:

Субпиксели RGB

(Обратите внимание, что границы этих «пикселей» предназначены только для демонстрации.)

Поскольку каждый из девяти субпикселей может быть только включен или выключен, вам придется квантовать входное изображение и использовать разные шаблоны субпикселей для достижения 3 уровней яркости.

Для каждого субпикселя в изображении:

  • Для уровней цвета 0-74 все подпиксели должны быть черными.
  • Для уровней цвета 75-134 средний подпиксель должен быть соответствующего цвета, а два других должны быть черного цвета.
  • Для уровней цвета 135-179 средний подпиксель должен быть черным, а два других должны быть соответствующего цвета
  • Для уровней цвета 180-255 все три подпикселя должны иметь свой соответствующий цвет

Я выбрал эти диапазоны уровней, потому что они выглядели хорошо

Примените это преобразование к каждому пикселю изображения и выведите изображение с субпиксельным увеличением.

Однопиксельные примеры

RGB (40, 130, 175) будет производить этот шаблон:

00B / 0G0 / 00B

RGB (160, 240, 100) будет производить этот шаблон:

RG0 / 0GB / RG0

Примеры полного изображения

Мона Лиза Мона Лиза Субпиксель

Звездная ночь Звездная ночь субпикселей

Попугай Попугай Субпиксели

Изображения получены из Википедии

Правила и примечания

  • Вход и выход могут быть в любом удобном формате, будь то фактические файлы изображений или (возможно, вложенные) списки значений RGB.
  • Вы можете предположить, что пиксели находятся в цветовом пространстве sRGB с 24BPP.

Удачного игры в гольф!


2
Первоначальное описание звучит как un-Bayering. Оказывается, что это не так, отчасти из-за нетрадиционной маски 3х3, но в основном из-за квантования, но ИМО все же ближе к небайерингу, чем к субпиксельному масштабированию (что было бы масштабированием с некоторым видом обнаружения краев до псевдоним).
Питер Тейлор

спасибо за интересный вызов .... это на самом деле используется для чего-либо в реальной жизни?
Дон Яркий

Ответы:


4

JavaScript (Node, Chrome, Firefox), 111 байт

Формат ввода / вывода: матрица [R,G,B]значений.

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

Попробуйте онлайн! (всего один пиксель)

Как?

Все пороговые значения кратны 15. Вместо проведения явных сравнительных тестов немного короче проверить битовую маску, где каждый бит представляет интервал из 15 значений (за исключением старшего значащего бита, который отображается на одно значение).

 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

Мы закодировать от , как1и в качестве0 чтобы максимизировать число ведущих нулей.

Мы получили:

  • 000000000111111111 для верхнего и нижнего пикселей (511 в десятичном виде)
  • 000000111000011111 для среднего пикселя (3615 в десятичном виде)

комментарии

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

пример

Следующий фрагмент кода обрабатывает голову Моны Лизы (64x64). Не работает на Edge.


3

Желе , 27 байт

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

Монадическая ссылка, принимающая список (изображение) списков (строк) списков (пикселей). Каждый пиксель состоит из трех целых[0,255], [r, g, 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

Я пытаюсь выяснить, где он кодирует [[1,0,0]. [0,1,0], [0,0,1]], и я сбит с толку.
Дон

@donbright 3⁼þ¤выполняет внешнее произведение с [1,2,3]=[1,2,3]получением [[1=1,2=1,3=1],[2=1,2=2,2=3],[3=1,3=2,3=3]]который [[1,0,0],[0,1,0],[0,0,1]].
Джонатан Аллан

2

Wolfram Language (Mathematica) , 186 байт

Вход и Выход - списки значений 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])&

Попробуйте онлайн!


Wolfram Language (Mathematica), 243 байта

этот второй код является функцией, которая принимает в качестве входного изображения и выводит изображение
(я не знаю, почему люди были смущены в комментариях)

Итак, если вы кормите это img

введите описание изображения здесь

в эту функцию

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


вы получите этот вывод

введите описание изображения здесь


2
Не будет ли это считаться жестко закодированным вводом?
attinat

Msgstr "Ввод и вывод могут быть в любом удобном формате, будь то фактические файлы изображений ...". Нет, iэто изображение.
J42161217

Я бы согласился с @attinat, это похоже на жесткое кодирование.
Джонатан Фрех

Я внес некоторые изменения и надеюсь, что теперь все ясно.
J42161217

1

C # (интерактивный компилятор Visual C #) , 157 байт

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

Печатает RGB вывода. Вывод разделен новой строкой и не выровнен. Первоначально я использовал битовую маску для 1включения и 0выключения, но затем я увидел ответ Арно и понял, 0что включение и 1выключение позволяют сохранять байты в числе. Ссылка TIO содержит образец изображения размером 4 на 2 пикселя.

Попробуйте онлайн!


0

APL + WIN, 102 байта

Запрашивает двумерную матрицу пикселей в виде 24-битных целых чисел так, как они выглядят на изображении

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

Попробуйте онлайн! Предоставлено Dyalog Classic

Выводит 2-мерную матрицу из 24-битных целых чисел преобразованного изображения. Большая часть кода обрабатывает форматирование ввода и вывода.

Пример: возьмите изображение 2 x 2, состоящее из образцов пикселей

Входные данные:

2654895 10547300
2654895 10547300

Вывод:.

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

0

Ржавчина - 281 байт

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}

Эта строка представляет собой функцию, которая отвечает этой задаче, однако ее ввод на самом деле представляет собой данные в формате файла TGA, как описано на paulbourke.net , вместе с предварительно проанализированной шириной и высотой изображения в пикселях. Он возвращает данные пикселей для вывода в виде байтов в векторе, в 9 раз превышающем размер входных данных пикселей.

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

Эта вторая строка является функцией main (), которая может преобразовать входной файл с именем i.tga в выходной файл с именем o.tga, вызвав функцию z из первой строки, без использования каких-либо внешних библиотек. Он обрабатывает разбор ширины / высоты, создает заголовок для выходного файла и чтение файла + запись. Это добавило бы 402 байта, если вызов требовал файлового ввода-вывода, в общей сложности 683. Это полезно для тестирования.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.