การซูมย่อยพิกเซล


9

งานของคุณคือถ่ายภาพ 24 BPP sRGB และส่งภาพเดียวกันที่มีการลดขนาด 3 เท่าลงในพิกเซลย่อยสีแดงสีเขียวและสีน้ำเงิน ภาพที่ได้จะเป็นพิกเซลสีดำบริสุทธิ์สีแดงสีเขียวและสีน้ำเงินทั้งหมด

แต่ละพิกเซลจากภาพต้นฉบับเมื่อซูมจะสร้างการจัดเรียงย่อยย่อย 9 พิกเซลที่สามารถเปิดหรือปิดได้ (เช่นสีหรือดำที่เกี่ยวข้อง) การจัดเรียงที่เฉพาะเจาะจงใช้คอลัมน์สามสีแดงเขียวและน้ำเงินตามลำดับดังนี้:

RGB subpixels

(โปรดทราบว่าเส้นขอบบน "พิกเซล" เหล่านี้ใช้สำหรับการสาธิตเท่านั้น)

เนื่องจากแต่ละ subpixels ทั้งเก้าสามารถเปิดหรือปิดได้คุณจะต้องทำการ quantize ภาพอินพุตและใช้รูปแบบ subpixel ที่แตกต่างกันเพื่อให้ได้ความสว่าง 3 ระดับ

สำหรับแต่ละพิกเซลย่อยในภาพ:

  • สำหรับระดับสี 0-74 เครื่องหมายย่อยทั้งหมดควรเป็นสีดำ
  • สำหรับระดับสี 75-134 พิกเซลย่อยกลางควรเป็นสีที่เกี่ยวข้องและอีกสองสีควรเป็นสีดำ
  • สำหรับระดับสี 135-179, subpixel กลางควรเป็นสีดำและอีกสองควรเป็นสีที่เกี่ยวข้อง
  • สำหรับระดับสี 180-255 ทั้งสาม subpixels ควรเป็นสีที่เกี่ยวข้อง

ฉันเลือกช่วงระดับเหล่านี้เพราะสิ่งเหล่านั้นเป็นสิ่งที่ดูดี

นำการแปลงนี้ไปใช้กับทุกพิกเซลในภาพและส่งออกภาพที่มีขนาดย่อยพิกเซล

ตัวอย่างพิกเซลเดี่ยว

rgb (40, 130, 175) จะสร้างรูปแบบนี้:

00B / 0G0 / 00B

rgb (160, 240, 100) จะสร้างรูปแบบนี้:

RG0 / 0GB / RG0

ตัวอย่างภาพเต็ม

Mona Lisa Mona Lisa Subpixels

สตาร์รี่ไนท์ ดาราย่อยกลางคืน

นกแก้ว Subpixels นกแก้ว

ภาพที่มาจาก Wikipedia

กฎและหมายเหตุ

  • อินพุตและเอาต์พุตอาจอยู่ในรูปแบบที่สะดวกไม่ว่าจะเป็นไฟล์รูปภาพจริงหรือรายการ (ค่าที่ซ้อนกัน) ของค่า RGB
  • คุณอาจคิดว่าพิกเซลอยู่ในพื้นที่สี sRGB ที่มี 24BPP

มีความสุขในการเล่นกอล์ฟ!


2
คำอธิบายเริ่มต้นดูเหมือนจะยกเลิกการเบเออร์ ปรากฎว่ามันไม่ใช่ส่วนหนึ่งเป็นเพราะหน้ากาก 3x3 ที่แปลกใหม่ แต่ส่วนใหญ่เป็นเพราะ quantisation แต่ IMO ยังคงใกล้กว่าการไม่เบเยอร์มากกว่าการซูม subpixel (ซึ่งน่าจะลดอัตราการสุ่มสัญญาณด้วยการตรวจจับขอบ นามแฝง)
ปีเตอร์เทย์เลอ

ขอบคุณสำหรับการท้าทายที่น่าสนใจ .... สิ่งนี้ใช้สำหรับชีวิตจริงหรือไม่?
ดอนสดใส

คำตอบ:


4

JavaScript (โหนด, 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 แทนที่จะทำการทดสอบเปรียบเทียบอย่างชัดเจนมันจะสั้นกว่าเล็กน้อยในการทดสอบ bitmask โดยที่แต่ละบิตแสดงช่วงเวลาของค่า 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

ตัวอย่าง

ข้อมูลโค้ดต่อไปนี้ประมวลผลส่วนหัวของ Mona Lisa (64x64) ไม่ทำงานบน Edge


3

เยลลี่ , 27 ไบต์

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

ลิงค์แบบ monadic ยอมรับรายการ (รูปภาพ) ของรายการ (แถว) ของรายการ (พิกเซล) แต่ละพิกเซลมีสามจำนวนเต็ม[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]]
Jonathan Allan

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 ดูเหมือนว่ารหัสนี้
Jonathan Frech

ฉันทำการเปลี่ยนแปลงบางอย่างและฉันหวังว่าทุกอย่างจะชัดเจนในขณะนี้
J42161217

1

C # (Visual C # Interactive คอมไพเลอร์) , 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 และฉันรู้ว่าการใช้0ทั้งเปิดและ1ปิดสามารถประหยัดจำนวนไบต์ได้ ลิงก์ TIO มี "รูปภาพ" ขนาด 4 x 2 ตัวอย่าง

ลองออนไลน์!


0

APL + WIN, 102 ไบต์

แสดงพร้อมต์สำหรับเมทริกซ์ 2d ของพิกเซลเป็นจำนวนเต็ม 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

เอาต์พุตเมทริกซ์ 2d ของจำนวนเต็ม 24 บิตของรูปภาพที่ถูกแปลง รหัสส่วนใหญ่จัดการการจัดรูปแบบของอินพุตและเอาต์พุต

ตัวอย่าง: ถ่ายภาพตัวอย่างขนาด 2x2 พิกเซล

การป้อนข้อมูล:

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 ไบต์ถ้าความท้าทายที่ต้องการไฟล์ I / O รวมเป็น 683 มันมีประโยชน์สำหรับการทดสอบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.