亚像素缩放


9

您的任务是拍摄24 BPP sRGB图像,并将同一图像放大3倍后输出为红色,绿色和蓝色子像素。生成的图像将完全由纯黑色,红色,绿色和蓝色像素组成。

源图像中的每个像素在缩放时都会产生9个子像素的排列,这些子像素可以打开或关闭(即它们各自的颜色或黑色)。具体安排使用红色,绿色和蓝色的三列,顺序如下:

RGB子像素

(请注意,这些“像素”上的边框仅用于演示。)

由于这9个子像素中的每一个只能打开或关闭,因此您将必须对输入图像进行量化,并使用不同的子像素图案来实现3级亮度。

对于图像中的每个子像素:

  • 对于0-74的色阶,所有子像素应为黑色。
  • 对于颜色级别75-134,中间子像素应为相应的颜色,其他两个应为黑色。
  • 对于135-179的色阶,中间的子像素应为黑色,而其他两个应为各自的颜色
  • 对于180-255的色阶,所有三个子像素应为各自的颜色

我选择这些级别范围是因为这些恰好看起来不错

将此变换应用于图像中的每个像素,然后输出子像素放大的图像。

单像素示例

rgb(40,130,175)将产生以下模式:

00B / 0G0 / 00B

rgb(160,240,100)将产生以下模式:

RG0 / 0GB / RG0

完整图片示例

蒙娜丽莎 蒙娜丽莎亚像素

星夜 星夜亚像素

鹦鹉 鹦鹉亚像素

图片来自维基百科

规则和注意事项

  • 输入和输出可以采用任何方便的格式,无论是实际的图像文件还是RGB值列表(可能是嵌套的)。
  • 您可以假设像素位于24BPP的sRGB色彩空间中。

打高尔夫球快乐!


2
最初的描述听起来像是非拜耳。事实证明,这并不是部分原因是因为使用了非常规的3x3蒙版,而是主要是由于量化,但是IMO仍比非像素分解更接近于非拜耳法(通过某种类型的边缘检测将其放大到反像素化)。别名)。
Peter Taylor

感谢您提供有趣的挑战。...这在现实生活中是否真的有用?
唐明亮

Answers:


4

JavaScript(Node,Chrome,Firefox),111字节

I / O格式:[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

我们将off编码为,on编码为,以最大化前导零的数量。10

我们得到:

  • 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

以下代码段处理了Mona Lisa(64x64)的头部。在Edge上不起作用。


3

果冻,27 个字节

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

单子链接接受列表(像素)列表(行)的列表(图片)。每个像素是在三个整数,其产生的结果相同的格式。[0,255][r, g, b]

在线尝试!此示例拍摄的是一个2 x 2图像,其中左上像素是第一个示例像素,右上像素是第二个示例像素,左下像素是黑色像素,右下像素是白色像素像素。

怎么样?

<“⁷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语言(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语言(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

“输入和输出可以采用任何方便的格式,无论是实际的图像文件...”。不,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关闭,但后来我看到了Arnauld的答案,我意识到使用0as on和1as off可以节省数字字节。TIO链接包含一个4 x 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提供

输出转换后图像的24位整数的2d矩阵。大多数代码都在处理输入和输出的格式。

示例:拍摄由样本像素组成的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}

这行功能可以应对挑战,但是它的输入实际上是paulbourke.net中描述的TGA文件格式的数据,以及预先解析的图像的宽度和高度(以像素为单位)。它以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()函数,可以通过从第一行调用函数z而不使用任何外部库,将名为i.tga的输入文件转换为名为o.tga的输出文件。它处理宽度/高度的解析,为输出文件创建头,以及文件读写。如果质询需要文件I / O,它将增加402字节,总共683个。对于测试非常有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.