Description
The Gameboy stores tiles as 2 bit-per-pixel 8x8 images, thus 16 bytes. Every two bytes is a complete row with all of the Low-bits of each pixel in the first byte, and all of the High-bits of each pixel in the second.
Input
Input will be exactly 16 bytes, received through Standard IO in one of the following forms:
- Array of bytes or strings
- 16 byte string
Per the Standard IO, these may be in a language convenient form (Deliminated string, on the stack, etc.)
Output
An image, Rendered or Saved, of the Gameboy Tile.
Scale and Aspect Ratio of each pixel is not fixed.
Each 2 bit colour of the Pallet may be anything so long as the Manhattan Distance of the RGB256 representation is atleast 48. Eg. #FFFFFF, #AAAAAA, #555555, #000000. Traditionally, although not a requirement, 00 is the lightest colour, and 11 is the darkest.
Examples
[FF, 00, 7E, FF, 85, 81, 89, 83, 93, 85, A5, 8B, C9, 97, 7E, FF]
[7C, 7C, 00, C6, C6, 00, 00, FE, C6, C6, 00, C6, C6, 00, 00, 00]
Final Notes
- Standard Loopholes apply
- An online demo, and more in-depth explanation of the implementation can be found HERE
- This is code-golf, so fewest bytes wins! (The Gameboy only had 65536 bytes of Address Space, after all!)
- Have Fun!
25 Answers 25
Gameboy machine code, 257 bytes
00000000 f0 44 fe 90 38 fa 3e e4 e0 47 21 90 81 1a 22 13 |.D..8.>..G!...".|
00000010 1a 22 13 1a 22 13 1a 22 13 1a 22 13 1a 22 13 1a |."..".."..".."..|
00000020 22 13 1a 22 13 1a 22 13 1a 22 13 1a 22 13 1a 22 |".."..".."..".."|
00000030 13 1a 22 13 1a 22 13 1a 22 13 1a 22 18 fe 00 00 |..".."..".."....|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000000d0 00 00 00 00 00 00 00 00 ff 00 7e ff 85 81 89 83 |..........~.....|
000000e0 93 85 a5 8b c9 97 7e ff 00 00 00 00 00 00 00 00 |......~.........|
000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 c7 |.|
00000101
Generated by this RGBASM assembly:
DEF rLY EQU $ff44
DEF rBGP EQU $ff47
SECTION "0",ROM0[0]
WaitVBlank:
ldh a, [rLY]
cp 144
jr c, WaitVBlank
ld a, %11100100 ; set background palette
ldh [rBGP], a
ld hl, 8190ドル ; override the tile data for the (R) icon
REPT 15
ld a, [de]
ld [hli], a
inc de
ENDR
ld a, [de]
ld [hli], a
jr @
SECTION "Input Data",ROM0[$d8]
DB $ff, 00,ドル 7ドルe, $ff, 85,ドル 81,ドル 89,ドル 83,ドル 93,ドル 85,ドル $a5, 8ドルb, $c9, 97,ドル 7ドルe, $ff
SECTION "Entrypoint",ROM0[100ドル]
rst 0 ; jump to reset vector 0
You can compile this code with rgbds: rgbasm tile.asm -o - | rgblink - -o tile.gb.
A gameboy ROM is usually at least 16K, so some emulators don't support this, but sameboy executes it with no problem. The entrypoint of the ROM, after the boot ROM executed is 0x100, so I don't think it can be any smaller.
As per the IO rules, Assembly programs may read input from some specified memory location, in this case 0xd8, which is conveniently the value of the de register when the boot ROM exits.
-
2\$\begingroup\$ I'm not sure whether unmapped memory should be counted in assembly. Counting only payload data seems reasonable -- in which case you could have a 'hole' before the jump to the reset vector. You may want to ask about that on meta if it has not already been addressed. \$\endgroup\$Arnauld– Arnauld2023年02月17日 20:35:28 +00:00Commented Feb 17, 2023 at 20:35
-
3\$\begingroup\$ (Actually, I think neither the input data nor the
rst 0should be taken into account for the byte count.) \$\endgroup\$Arnauld– Arnauld2023年02月18日 09:15:20 +00:00Commented Feb 18, 2023 at 9:15
J, 41 bytes
load'viewmat'
[:viewmat 2#._2|:@|.\#:@dfh
Try it online - fails because TIO can't run viewmat
Working link that outputs a matrix of integers 0 thru 3
Takes input as an array of hex strings.
- Convert each hex string to a binary number
- Take then in rows of two, reverse and transpose and convert back decimal
- View the resulting matrix as an image
Image produced when running the function locally:
Shell + rgbds devkit, 16 bytes
rgbgfx -r1 -o- -
Takes raw bytes from stdin and outputs a png on stdout. rgbgfx is the graphics conversion program from the RGBDS Gameboy Development Kit, intended to convert PNGs to Gameboy tile data, and vice-versa.
-
1\$\begingroup\$ Right tool for the job \$\endgroup\$Jonah– Jonah2023年02月17日 16:55:40 +00:00Commented Feb 17, 2023 at 16:55
MATL, 13 bytes
8&B1L&Y)E+1YG
Inputs an array of bytes, and displays an image. The image consists of grey colours where 00 corresponds to black and 11 to white.
Try it at MATL Online!
How it works
8&B % Implicit input: ×ばつ16 array. Convert to binary with 8 bits.
% Gives a ×ばつ8 array
1L % Push [1 2 j]. As an index, this is interpreted as 1:2:end
&Y) % Two-ouput row indexing. This gives an ×ばつ8 subarray with the
% indicated rows, and an ×ばつ8 subarray with the remaining rows
E % Multiply by 2, element-wise
+ % Add. This gives an ×ばつ8 array with possible values 0, 1, 2, 3
1YG % Display as an image with scaled colors, using the default
% grey colormap
R, 65 bytes
\(a)image(t((b=outer(rev(a),2^(7:0),`%/%`)%%2)[!1:0,]+2*b[!0:1]))
Don't attempt This Online; instead, Try it at rdrr.io with graphical output (uses function instead of \ due to older version of R installed at rdrr.io).
Note that this could be 7 bytes shorter by omitting the image() call and outputting a matrix of bytes, but R has good graphical output so it seems more in the spirit of the challenge to actually draw the image.
QBasic, (削除) 100 (削除ここまで) 96 bytes
SCREEN 7
FOR r=0TO 7
INPUT a
INPUT b
FOR c=0TO 7
PSET(7-c,r),a2円^c MOD 2+(1AND b2円^c)*3
NEXT c,r
You can try it on Archive.org. Input the bytes one at a time as decimal integers (0 to 255). The image is displayed in the upper left corner of the screen, overwriting the ? prompt from the first INPUT statement. Each "pixel" is 2x2. The colors are:
- Black: rgb(0,0,0)
- Blue: rgb(0,0,170)
- Cyan: rgb(0,170,170)
- Red: rgb(170,0,0)
Example run of the golfed code
Ungolfed
With a less golfy formula for computing the color code, and drawing each pixel as a filled box rather than a single point, it turns out we can reproduce the grayscale images in the OP exactly.
SCREEN 7
' Each point in screen mode 7 is 2x2 pixels, so we draw 15x15 boxes to match
' the 30x30 pixel boxes in OP's image
size = 15
FOR row = 0 TO 7
INPUT lowbits
INPUT highbits
FOR col = 0 TO 7
place = 2 ^ (7 - col)
lowbit = (lowbits \ place) AND 1
highbit = (highbits \ place) AND 1
' 00 = color 15, white
' 01 = color 7, light gray
' 10 = color 8, dark gray
' 00 = color 0, black
colorcode = 15 - lowbit * 8 - highbit * 7
' Compute top and left coordinates of the box based on row and column
' (with the left shifted over to avoid drawing over the inputs)
top = row * size
left = 60 + col * size
' Draw the box using the LINE command with the BF (box filled) option
LINE (left, top)-(left + size - 1, top + size - 1), colorcode, BF
NEXT col
NEXT row
Japt -R, (削除) 17 25 (削除ここまで) 23 bytes
m¤ùT8 ò ®yÍ ̧Ãi"P2 8 8 3
Saved two bytes thanks to Shaggy
Previously, this answer outputted a string using differently shaded unicode characters to represent the different colors, but as OP has clarified that this is not allowed, it now outputs a Plain PGM file.
Takes input as byte array and outputs a string representing a PGM file.
m¤ùT8 ò ®yÍ ̧Ãi"P2 8 8 3 : implicit input of byte array
m¤ : convert each byte to binary
ùT8 : left-pad each binary string with 0s
ò ® : map each pair of lines to:
yÍ : transpose the pair, map each two-char string to a number
̧ : join by spaces
à : end map
i"P2 8 8 3 : prepend the start of a PGM file
: -R join by newlines
Japt -R, 11 bytes
Outputs a matrix of bytes.
m¤ùT8 ò ®yÍ
-
\$\begingroup\$ The character set
[9617,9618,9619,9608]works much better for me, but it may depend on the installed fonts. \$\endgroup\$Arnauld– Arnauld2023年02月17日 11:42:16 +00:00Commented Feb 17, 2023 at 11:42 -
\$\begingroup\$ @Arnauld Thanks, edited \$\endgroup\$noodle person– noodle person2023年02月17日 11:49:00 +00:00Commented Feb 17, 2023 at 11:49
-
1
-
1\$\begingroup\$ @Shaggy No, I thought that was generally accepted for graphical-output challenges--but maybe I'm wrong. I just posted a comment on the challenge \$\endgroup\$noodle person– noodle person2023年02月17日 17:45:56 +00:00Commented Feb 17, 2023 at 17:45
-
1\$\begingroup\$ Great shout on using
n2instead of indexing into an array; kicking myself that I didn't catch that! \$\endgroup\$Shaggy– Shaggy2023年02月17日 19:30:30 +00:00Commented Feb 17, 2023 at 19:30
JavaScript (ES6), 79 bytes
Expects a list of bytes and outputs a matrix of RGB tuples, using the greenish palette 00C000, 008000, 004000, 000000.
a=>(v=[...'01234567']).map(y=>v.map(x=>[0,~a[y*2]<<x>>1&64|~a[y-~y]<<x&128,0]))
73 bytes
Outputs a matrix of bytes.
a=>(v=[...'01234567']).map(y=>v.map(x=>~a[y*2]<<x>>1&64|~a[y-~y]<<x&128))
Rendering
f=
a=>(v=[...'01234567']).map(y=>v.map(x=>[0,~a[y*2]<<x>>1&64|~a[y-~y]<<x&128,0]))
F = (id, a) => { m = f(a); m.forEach(r => r.forEach(rgb => { div = document.createElement('div'); div.style.backgroundColor = '#' + rgb.map(v => v.toString(16).padStart(2, '0')).join(''); document.getElementById(id).appendChild(div); })) }
F('b0', [0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF])
F('b1', [0xFF, 0x00, 0x7E, 0xFF, 0x85, 0x81, 0x89, 0x83, 0x93, 0x85, 0xA5, 0x8B, 0xC9, 0x97, 0x7E, 0xFF])
F('b2', [0x7C, 0x7C, 0x00, 0xC6, 0xC6, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0x00, 0x00, 0x00])
F('b3', [0xFF, 0xFF, 0xFF, 0x81, 0xC3, 0x81, 0xDF, 0x85, 0xDF, 0x85, 0xFF, 0xBD, 0xFF, 0x81, 0xFF, 0xFF])
.box { float:left; margin-right:16px; width:128px; height:128px; } .box div { float:left; width:16px; height:16px; }
<div id="b0" class="box"></div><div id="b1" class="box"></div><div id="b2" class="box"></div><div id="b3" class="box"></div>
C, (削除) 108 (削除ここまで) (削除) 105 (削除ここまで) (削除) 95 (削除ここまで) (削除) 93 (削除ここまで) (削除) 89 (削除ここまで) 85 bytes
b;main(j){for(puts("P5 8 8 3");j=j-1?:read(0,&b,2)*4;b+=b)putchar(3^b>>14&2^b>>7&1);}
Reads raw bytes from stdin and outputs an image in the PGM format to stdout.
-17! thanks to @c--
-
\$\begingroup\$ Suggest
b+=binstead ofb<<=1and3^b>>14&2^b>>7&1instead of3-(b>>14&2|b>>7&1)\$\endgroup\$c--– c--2023年02月17日 16:57:52 +00:00Commented Feb 17, 2023 at 16:57 -
\$\begingroup\$ @c-- Thanks, I missed that. \$\endgroup\$pan– pan2023年02月17日 16:59:40 +00:00Commented Feb 17, 2023 at 16:59
-
1
-
1
-
1\$\begingroup\$ @c-- Thanks! I had noticed too, but it's a TIO thing. It works as expected locally. \$\endgroup\$pan– pan2023年02月18日 20:38:24 +00:00Commented Feb 18, 2023 at 20:38
K (ngn/k), 44 bytes
`0:"P2 8 8 3"
2/+,/+'0N 2#-8#'+(8#0),2\.0:`
Takes input as a space separated list of integers. Outputs a plain pgm to stdout.
Colors are inverted from the example.
Nibbles, 20.5 bytes (41 nibbles)
"P2 8 8 3 ".`/~.$``@hex:1$>>/$!@@~++
Input is an array of hex strings; output is a plain PGM image file (inspired by pan's answer).
"P2 8 8 3 " # prepend the string "P2 8 8 3 " onto:
. # map over
$ # the input:
:1$ # prepend a '1'
hex # then get the hex value
``@ # convert to bits
`/ # get chunks of 2
. # and map over these:
/$ # fold across each chunk of 2
!@@ # zipping-together the 2 elements
~+ # by adding together
+ # the first elements added to themselves
# and the second elements
>> # and remove the first element
enter image description here enter image description here
Note that if output as a matrix of bytes would be valid, we could drop the initial "P2 8 8 3 " header for the plain PGM format, for just 13 bytes.
JavaScript, 105 bytes
v=>{for(i=0;i<8;++i)for(j=0;j<8;++j)window['c'+i+(7-j)].className='wldb'[2*(b=n=>v[2*i+n]>>j&1)(0)+b(1)]}
Try it:
f=v=>{for(i=0;i<8;++i)for(j=0;j<8;++j)window['c'+i+(7-j)].className='wldb'[2*(b=n=>v[2*i+n]>>j&1)(0)+b(1)]}
button.addEventListener('click', _=>f(input.value.split` `.map(x=>+('0x'+x))));
.f {
border: 1px solid black;
width: fit-content;
}
.r {
display: flex;
}
[id^="c"] {
width: 40px;
height: 40px;
background-color: lightblue;
}
input {
width: 320px;
}
.w {
background-color: #fff;
}
.l {
background-color: #555;
}
.d {
background-color: #aaa;
}
.b {
background-color: #000;
}
<input id="input" value="7C 7C 00 C6 C6 00 00 FE C6 C6 00 C6 C6 00 00 00">
<button id='button'>Draw</button>
<br><br>
<div class="f">
<div class="r">
<div id="c00"></div><div id="c01"></div><div id="c02"></div><div id="c03"></div><div id="c04"></div><div id="c05"></div><div id="c06"></div><div id="c07"></div>
</div>
<div class="r">
<div id="c10"></div><div id="c11"></div><div id="c12"></div><div id="c13"></div><div id="c14"></div><div id="c15"></div><div id="c16"></div><div id="c17"></div>
</div>
<div class="r">
<div id="c20"></div><div id="c21"></div><div id="c22"></div><div id="c23"></div><div id="c24"></div><div id="c25"></div><div id="c26"></div><div id="c27"></div>
</div>
<div class="r">
<div id="c30"></div><div id="c31"></div><div id="c32"></div><div id="c33"></div><div id="c34"></div><div id="c35"></div><div id="c36"></div><div id="c37"></div>
</div>
<div class="r">
<div id="c40"></div><div id="c41"></div><div id="c42"></div><div id="c43"></div><div id="c44"></div><div id="c45"></div><div id="c46"></div><div id="c47"></div>
</div>
<div class="r">
<div id="c50"></div><div id="c51"></div><div id="c52"></div><div id="c53"></div><div id="c54"></div><div id="c55"></div><div id="c56"></div><div id="c57"></div>
</div>
<div class="r">
<div id="c60"></div><div id="c61"></div><div id="c62"></div><div id="c63"></div><div id="c64"></div><div id="c65"></div><div id="c66"></div><div id="c67"></div>
</div>
<div class="r">
<div id="c70"></div><div id="c71"></div><div id="c72"></div><div id="c73"></div><div id="c74"></div><div id="c75"></div><div id="c76"></div><div id="c77"></div>
</div>
</div>
-
5\$\begingroup\$ This is JavaScript+HTML+CSS, also I believe you have to include the CSS in the byte count since the JS wouldn't work without it \$\endgroup\$noodle person– noodle person2023年02月17日 17:47:55 +00:00Commented Feb 17, 2023 at 17:47
-
\$\begingroup\$ @Jacob I think of it this way: JS needs to correctly set the class names for the elements in order to get the correct image, and HTML and CSS just help to see it in a pretty way :) \$\endgroup\$EzioMercer– EzioMercer2023年02月17日 19:33:24 +00:00Commented Feb 17, 2023 at 19:33
Charcoal, 36 bytes
EE8⮌E2↨↧S16⮌⭆8§░▒▓█↨2%÷ιX2λ2
Try it online! Link is to verbose version of code. Now uses @Arnauld's output characters. Explanation:
8 Literal integer `8`
E Map over implicit range
2 Literal integer `2`
E Map over implicit range
S Next input hex digit pair
↧ Lowercased
↨ 16 Converted from base `16`
⮌ Reversed
E Map over each pair of hex values
8 Literal integer `8`
⭆ Map over implicit range and join
░▒▓█ Literal string
§ Indexed by
ι Current pair
÷ Vectorised divided by
2 Literal integer `2`
X Raised to power
λ Current value
% 2 Vectorised modulo `2`
↨2 Converted from base `2`
⮌ Reversed
Implicitly print
Note that the deverbosifier on TIO erroneously uselessly quotes the special characters inside "y and "; this is not actually necessary for correct operation of the program.
32 bytes by taking the input bytes with 0x prefix using the newer version of Charcoal on ATO:
EE8⮌E2N⮌⭆8§░▒▓█↨2%÷ιX2λ2
Attempt This Online! Link is to verbose version of code.
-
\$\begingroup\$ Could you save anything by taking input in decimal rather than hex? \$\endgroup\$Shaggy– Shaggy2023年02月17日 13:28:59 +00:00Commented Feb 17, 2023 at 13:28
-
\$\begingroup\$ @Shaggy I can save 4 bytes by using ATO. I could probably save another couple of bytes by making the input format even more convoluted. \$\endgroup\$Neil– Neil2023年02月17日 13:55:52 +00:00Commented Feb 17, 2023 at 13:55
C (GCC), (削除) 110 (削除ここまで) (削除) 109 (削除ここまで) 93 bytes
-16 bytes thanks to @c--
m;main(h){for(;m=m/2?:read(!puts(""),&h,2)*64;)printf("[%dm [m",(h&m?39:99)+(h>>8&m?1:8));}
Takes the input as a binary array from stdin, outputs spaces with different ANSI-colored background.
If the input is longer than 16 bytes, it continues displaying 8-pixel rows (which is incidentally useful for testing).
Befunge-with-graphics, 149 bytes
Takes raw bytes from stdin and creates a window which displays the result.
99*:sfcu88803v
v_v#!:-1\~<+p<
$ > ^
>802p>:2%2円/01円p\:2%2円/01円g2*+3\-89+5v
$ ^$p20_v#:-1g20-1g30\xg30g20f::**<
^$p30_v#:$ <
v-1z<u<
> #^_@
Test case:
Output image
-
\$\begingroup\$ Very cool extension to befunge! \$\endgroup\$noodle person– noodle person2023年05月21日 11:48:07 +00:00Commented May 21, 2023 at 11:48
SAS
136 - ascii art in Log
This solution uses the idea from Charcoal language with help of special characters: " ░▒▓" of "gradient dots", it is 11 bytes, the firs symbol is a space.
The Code:
data;input(a b)(:hex2.)@@;do x=1to 8;c=ksubstr(" ░▒▓",1+2*char(put(a,binary8.),x)+char(put(b,binary8.),x),1);put c+(-1)@;end;put;cards;;
Input goes between last two semicolons as a string e.g., FF 00 7E FF 85 81 89 83 93 85 A5 8B C9 97 7E FF
It allows to use multiple strings at once, so if there are any other test cases I gladly add then to display.
In human readable form it looks like:
data;
input (a b) (:hex2.) @@;
do x = 1 to 8;
c = ksubstr(" ░▒▓"
,1 + 2*char(put(a, binary8.), x) + char(put(b, binary8.), x)
,1);
put c +(-1) @;
end;
put;
cards;
FF 00 7E FF 85 81 89 83 93 85 A5 8B C9 97 7E FF
7C 7C 00 C6 C6 00 00 FE C6 C6 00 C6 C6 00 00 00
;
In the log you will see:
▒▒▒▒▒▒▒▒
░▓▓▓▓▓▓░
▓ ▒ ▓
▓ ▒ ░▓
▓ ▒ ░▒▓
▓ ▒ ░▒░▓
▓▒ ░▒░░▓
░▓▓▓▓▓▓░
▓▓▓▓▓
░░ ░░
▒▒ ▒▒
░░░░░░░
▓▓ ▓▓
░░ ░░
▒▒ ▒▒
180 = 113+67 - heatmap
Since SAS at its origin stand for Statistical Analysis System let's use "three dimensional" histogram i.e. HeatMap
The code
- part 1)
data;input(a b)(:hex2.)@@;y+(-1);do x=1to 8;c=2*char(put(a,binary8.),x)+char(put(b,binary8.),x);output;end;cards;
- part 2)
;proc sgplot;heatmap x=x y=y/colorresponse=c nxbins=8 nybins=8;run;
Input goes between past 1) and 2) as a string e.g., FF 00 7E FF 85 81 89 83 93 85 A5 8B C9 97 7E FF
Human readable form looks like:
data;
input (a b) (:hex2.) @@;
y + (-1);
do x = 1 to 8;
c = 2*char(put(a, binary8.), x) + char(put(b, binary8.), x);
output;
end;
cards;
FF 00 7E FF 85 81 89 83 93 85 A5 8B C9 97 7E FF
;
proc sgplot;
heatmap x=x y=y /
colorresponse=c nxbins=8 nybins=8
;
run;
The sgplot procedure uses its default setup and the output looks like:
enter image description here
Wit some "polishing"
proc sgplot noautolegend;
heatmap x=x y=y /
colorresponse=c nxbins=8 nybins=8
colormodel=(lightgrey black);
xaxis display=none;
yaxis display=none;
run;
the output looks like: enter image description here
and
Vyxal, (削除) 26 (削除ここまで) 21 bytes
bṅvṅ2ẇv∩vvB883f‛P2pp⁋
Uses roughly the same method as my Japt answer. I have tried a lot of different things but I can't find a 20-byter. With Vyncode this is 17 bytes but I'm not the biggest fan of that.
Takes input as a list of bytes, outputs a Plain PGM file.
Explanation:
bṅvṅ2ẇv∩vvB883f‛P2pp⁋
b # Convert to list of binary digits
ṅ # join each to a string
vṅ # pad each binary string to length 8 with zeroes
2ẇ # chunks of length 2
v∩ # transpose each pair to a list of two-bit binary strings
vvB # convert each from binary
883f # digits of 883
‛P2 # string literal "P2"
p # prepend this to digit list
p # prepend this header to the matrix
⁋ # join each item on spaces and then join the items on newlines
💎
Created with the help of Luminespire.
-
1\$\begingroup\$ I think you'll have to update this, like your Japt answer and my Thunno answer. \$\endgroup\$The Thonnu– The Thonnu2023年02月20日 16:57:54 +00:00Commented Feb 20, 2023 at 16:57
-
1\$\begingroup\$ @TheThonnu Yeah I'm just really lazy lol. I'll do it later today, shouldn't take more than a few minutes \$\endgroup\$noodle person– noodle person2023年02月20日 20:25:48 +00:00Commented Feb 20, 2023 at 20:25
-
\$\begingroup\$ @UndoneStudios done \$\endgroup\$noodle person– noodle person2023年02月23日 14:58:00 +00:00Commented Feb 23, 2023 at 14:58
-
\$\begingroup\$ Vyxal?! You traitor! :p Just as I was beginning to think you were my new Japt protégé! \$\endgroup\$Shaggy– Shaggy2023年02月23日 23:37:46 +00:00Commented Feb 23, 2023 at 23:37
-
1\$\begingroup\$ Been toying with the idea myself for years but, not having the first clue about language design, I never got around to it. But I'd absolutely pitch in with you to help out. ETH had a lot of ideas for v2 of Japt before he disappeared that would have made it so much better; things like a custom codepage and being able to omit closing spaces for methods with a fixed arity. \$\endgroup\$Shaggy– Shaggy2023年02月24日 14:35:22 +00:00Commented Feb 24, 2023 at 14:35
Go, (削除) 304 (削除ここまで) 302 bytes
import(."image";c"image/color";d"image/draw";p"image/png";."os")
func f(s[]byte){N,S,R,D,P:=NewUniform,d.Src,Rect,d.Draw,Point{0,0}
T:=NewGray(R(0,0,8,8))
for i:=0;i<8;i++{for l,h,j:=s[2*i],s[2*i+1],0;j<8;j++{D(T,R(j,i,j+1,i+1),N(c.Gray{255-85*(h&128>>6+l&128>>7)}),P,S)
h*=2
l*=2}}
p.Encode(Stdout,T)}
Prints the bytes of a PNG to STDOUT.
- -2 bytes by @The Thonnu
Slightly-Ungolfed Explanation
import(."image";c"image/color";d"image/draw";p"image/png";."os")
func f(s[]byte){
N,S,R,D,P:=NewUniform,d.Src,Rect,d.Draw,Point{0,0}
// various variables
T:=NewGray(R(0,0,8,8)) // new 8-bit grayscale, 8x8px
for i:=0;i<8;i++{ // for each row...
l,h:=s[2*i],s[2*i+1] // get the bytes for that row
for j:=0;j<8;j++{ // for each pixel...
C:=c.Gray{255-85*(h&128>>6+l&128>>7)} // calculate the color.
// yields an inverted color, so `255-x` is needed.
D(T,R(j,i,j+1,i+1),N(C),P,S) // draw the pixel to the tile
h<<=1;l<<=1}} // shift the bytes left to get the next pixel.
p.Encode(Stdout,T)} // print the PNG to STDOUT
-
\$\begingroup\$ Would doubling instead of left-shifting work for 302 bytes? \$\endgroup\$The Thonnu– The Thonnu2023年07月31日 16:51:29 +00:00Commented Jul 31, 2023 at 16:51
Python, (削除) 526 524 483 471 470 454 (削除ここまで) 447 bytes
I'm a turtle veteran. For fast results, use speed(0). Uses the given pallet.
def g(l,x=range(8)):
r=[int(i,16)for i in l];j=[[r[i+1],r[i]]for i in range(0,16,2)]
for i in x:j[i]=["".join([bin(j[i][0])[2:].zfill(8).replace(" ","0")[k],bin(j[i][1])[2:].zfill(8).replace(" ","0")[k]])for k in x]
for i in x:
for l in x:j[i][l]=int(j[i][l],2);j[i][l]="#"+"FA50"[j[i][l]]*6
for i in j:
for k in i:seth(0);color(k);begin_fill();exec('fd(9);rt(90);'*4);end_fill();fd(9)
pu();goto(0,ycor()-9);pd();ht()
from turtle import*
Test case 1:
enter image description here
Test case 2:
enter image description here
-
\$\begingroup\$ You can save 1 byte with a slightly more efficient color palet. This has a 64 contrast so plenty. \$\endgroup\$mousetail– mousetail2023年02月28日 09:15:32 +00:00Commented Feb 28, 2023 at 9:15
Thunno N, \$ 29 \log_{256}(96) \approx \$ 23.87 bytes
"P2 8 8 3"ZKb8zK2ApeZt.JBA_sj
Port of (削除) Jacob (削除ここまで) noodle man's Japt answer.
-4 characters thanks to noodle man
Explanation
# Implicit input
"..."ZK # Print this string without a trailing newline
b # Convert each number in the input to binary
8zK # Pad each binary string with zeros to length 8
2Ap # Split the list into pairs
e # Map over this list of pairs:
Zt # Transpose the pair
.J # And join each inner list into a string
B # Convert each string from binary
A_sj # And join this list of strings by spaces
# Implicit output, joined on newlines
-
\$\begingroup\$ Unfortunately the OP wrote after I posted my answer that it isn't allowed to output using a string like that, so this is invalid. See my updated Japt answer \$\endgroup\$noodle person– noodle person2023年02月18日 18:38:17 +00:00Commented Feb 18, 2023 at 18:38
-
\$\begingroup\$ @Jacob thanks for the heads-up. I've updated my answer. \$\endgroup\$The Thonnu– The Thonnu2023年02月18日 20:17:30 +00:00Commented Feb 18, 2023 at 20:17
-
\$\begingroup\$ Thunno
N, 30 characters:b8zK2ApeZt.JBA_sjE"P2 8 8 3"ZN\$\endgroup\$noodle person– noodle person2023年08月05日 18:48:44 +00:00Commented Aug 5, 2023 at 18:48 -
\$\begingroup\$ @noodleman nice! It's been so long since I last wrote a program in Thunno so it felt kinda cool writing the explanation. \$\endgroup\$The Thonnu– The Thonnu2023年08月05日 19:47:16 +00:00Commented Aug 5, 2023 at 19:47
-
\$\begingroup\$ Thunno
N, 29 chars (≈ 23.87 bytes if you're still doing that):"P2 8 8 3"ZKb8zK2ApeZt.JBA_sj\$\endgroup\$noodle person– noodle person2024年01月21日 03:52:58 +00:00Commented Jan 21, 2024 at 3:52
Uiua, (削除) 15 (削除ここまで) 14 bytes
÷3⍉⇌°⋯↯8_8_2⍉⋯
Just managed to squeeze out a byte, I don’t think this can get any shorter.
Explanation:
⍉⋯
Convert the input to binary, padding to 8 bits, and transpose. This gives an 8x16 array.
°⋯↯8_8_2
Reshape the array to 8x8x2, then convert each number back from binary. This gives us an 8x8 array of numbers 0-3, but it’s rotated 90 degrees.
⍉⇌
Reverse, then transpose, rotating the matrix to the correct orientation.
÷3
Divide each number by 3. This gives a matrix of numbers between 0 (black) and 1 (white), which is the format Uiua does images in.
Clojure, 316 bytes
(fn[i](doto(Frame.)(.add(proxy[Panel][](paint[g](dotimes[r 8](dotimes[c 8](.setColor g(((mapv(fn[[l h]](mapv #(Color.({0 0xFFFFFF 1 0xAAAAAA 2 5592405 3 0}(Long/parseLong(str % %2)2)))h l))(partition 2(map #(clojure.pprint/cl-format nil "~8,'0b"%)i)))r)c))(.fillRect g(* c 9)(* r 9)9 9)))))).pack(.setVisible true)))
Inputs:
[0xFF, 0x00, 0x7E, 0xFF, 0x85, 0x81, 0x89, 0x83, 0x93, 0x85, 0xA5, 0x8B, 0xC9, 0x97, 0x7E, 0xFF][0x7C, 0x7C, 0x00, 0xC6, 0xC6, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0x00, 0x00, 0x00]
Outputs:
Thunno 2 N, 22 bytes
ḃ8ṛ2ẇıṬ€JḂ;883`P2ƤƤðȷj
Port of noodle man's Japt answer.
Explanation
ḃ8ṛ2ẇıṬ€JḂ;883`P2ƤƤðȷj # Implicit input
ḃ8ṛ # Convert each to binary and pad with zeros to length 8
2ẇı ; # To each chunk of 2:
Ṭ€J # Transpose and join each
Ḃ # Then convert back from binary
883 # Push 883
`P2Ƥ # Prepend "P2"
Ƥ # And prepend this header
ðȷj # Join each inner list on spaces
# Implicit output, joined on newlines
-
\$\begingroup\$ I think it has to start with "P2 8 8 3" not "P2883" but I can’t check on my phone. (My vyxal answer pushes ["P2",8,8,3] and joins on spaces.) \$\endgroup\$noodle person– noodle person2023年07月31日 17:04:36 +00:00Commented Jul 31, 2023 at 17:04
-
\$\begingroup\$ @noodleman oh yeah, fixed. \$\endgroup\$The Thonnu– The Thonnu2023年07月31日 17:27:47 +00:00Commented Jul 31, 2023 at 17:27
-
\$\begingroup\$ Who’s Jacob, anyway? \$\endgroup\$noodle person– noodle person2023年07月31日 17:31:28 +00:00Commented Jul 31, 2023 at 17:31
-
\$\begingroup\$ For some reason, whenever I see your display name, I always think "Jacob" :p \$\endgroup\$The Thonnu– The Thonnu2023年07月31日 17:34:01 +00:00Commented Jul 31, 2023 at 17:34
-
\$\begingroup\$ Makes sense. I was thinking about changing it back (it gets confusing when my GitHub account has my real name) but I think I’ll keep it for a bit longer \$\endgroup\$noodle person– noodle person2023年07月31日 17:36:25 +00:00Commented Jul 31, 2023 at 17:36
Postscript (削除) 245 (削除ここまで) 168
Images in Postscript can have 2 bits per pixel, or, more specifically, 2 bits per color component and 1 component (e.g. Grayscale) per sample. However, interpreter expects bytes in data source to constitute a continuous bit stream, not low bits here, high bits there. We'll have to zip bits from each two bytes:
currentpagedevice /PageSize get aload pop scale
<FF 00 7E FF 85 81 89 83 93 85 A5 8B C9 97 7E FF>
% 16 byte string on stack here
{not} forall % 16 bytes
8 8 2 [8 0 0 8 0 0]
{ % consume by pairs (a, b)
0 % accumulator (x)
0 1 7 { % a b x s
dup dup % a b x s s s
1 exch bitshift % a b x s s m
dup 5 index and % a b x s s m bm
4 1 roll % a b x bm s s m
6 index and % a b x bm s s am
exch bitshift % a b x bm s ax
3 1 roll % a b x ax bm s
1 add bitshift % a b x ax bx
or or % a b x
} for
3 1 roll pop pop % x
dup 256 idiv
exch 255 and % 2 bytes
2 string dup 0 5 -1 roll put
dup 1 4 -1 roll put
}
image
I'll use "16 byte string already on stack" for simplicity as allowed in the OP, though it could have been read from file (e.g. STDIN) or command line. I think it's OK for program size byte count to begin after 1st comment, and then stripped of insignificant whitespace it would be:
{not}forall 8 8 2[8 0 0 8 0 0]{0 0 1 7{dup dup 1 exch bitshift dup 5 index and 4 1 roll 6 index and exch bitshift 3 1 roll 1 add bitshift or or}for 3 1 roll pop pop dup 256 idiv exch 255 and 2 string dup 0 5 -1 roll put dup 1 4 -1 roll put}image
The very 1st line was not included in count as it just serves to produce more "pleasing" output. Command (gs in Linux)
gswin64c -q -g200x200 source.ps
(again, image size on command line is only for better looking square tile, instead of scaled non-proportionately to A4 (or Letter) default page).
For golfing purposes, long repeatedly used operators could be re-defined as short-named procedures, or entire source compactly written as binary tokens, though result would be not very readable. I have better idea: to produce the same output, let's draw not one 2 ppx image, but three 1 ppx image masks to paint with 0.33, 0.66 and 1.0 ink, respectively. Then, e.g., if a bit is set in low-bits byte and I paint this pixel with light-gray, it won't interfere with painting later in dark-gray and/or black (if bit is set in high-bits byte).
currentpagedevice /PageSize get aload pop scale
<FF 00 7E FF 85 81 89 83 93 85 A5 8B C9 97 7E FF>
% 16 byte string on stack here
{} forall
16 -1 9 {
dup index
exch 1 sub index
and
} for
23 -1 16 {
-1 roll
} for
24 -8 roll
2 -1 0 {
3 div setgray
8 8 true [8 0 0 8 0 0]
{ 1 string dup 0 4 -1 roll put }
imagemask
} for
I.e.:
{}forall 16 -1 9{dup index exch 1 sub index and}for 23 -1 16{-1 roll}for 24 -8 roll 2 -1 0{3 div setgray 8 8 true[8 0 0 8 0 0]{1 string dup 0 4 3 roll put}imagemask}for
There is bytes moving around stack instead of bits juggling, which is significantly less cumbersome, and shorter.
Ruby, 101 bytes
Returns the lines of a PGM file. I'm sure that each_slice could be golfed out but I don't feel like it. Could be a byte shorter by removing the splat before a.map but I don't like returning a ragged array.
->a{["P2 8 8 3",*a.map{("%08b"%_1).chars}.each_slice(2).map{_1.transpose.map{|x|x.join.to_i 2}*" "}]}
7C 7C 00 C6 C6 00 00 FE C6 C6 00 C6 C6 00 00 00should look like a letter A as shown at the HERE link \$\endgroup\$