Step by step: How to convert your image to pico-8 as map data
In detail, the process to convert your image into pico-8 can be divided in 3 steps: You’ll need ImageToPico8.
Download ImageToPico8
Convert your Image (or Preview and Convert)
On a Windows Command Prompt, type:
ImgToP8 -orange "D:\My folder\MyPhoto.jpg"
ImageToPico8 lets you preview the conversion of your image in the desired palette. For example -orange for an orange palette and -blue for a blue palette.
More palette presets or how to set your own palette are also made possible.
More palette presets or how to set your own palette are also made possible.
Copy and paste the result in your cartridge, as Pico-8 Map data tab
Basically you only need to locate your p8 cartridge, open it in your favorite text editor, and paste the result output by ImageToPico8. But first of all we’ll take some precaution and make some backups.
- In Pico-8 engine, press ctrl+S to save your cartridge —Let’s say it’s called “mygame”—, and close Pico-8 engine.
- Your game cartridge “mygame.p8” should be located in your Users folder. On Window the path where it’s located is: C:\Users\your_username\AppData\Roaming\pico-8\carts\mygame.p8
- Make a backup of this file, name it for example “mygame.p8.bak”. This will prevent you from breaking anything.
- Open “mygame.p8” in a text editor. Personally I use Notepad++. Keep this file opened.
- Now open the resulting file “MyImage_out.txt.p8” in the text editor as well. Select All and Copy the whole __map__ section.
- Then come back to your file “mygame.p8” (it should be in another tab of your text editor)
- Locate the __map__ section by searching "__map__" in this file (you can do this with “Ctrl+f” keyboard shortcut).
- Select the complete __map__ section you found including the 23 lines of data under this section, and Paste (Ctrl+V). This will replace the existing map data with the ones in the result of the image processing with ImageToPico8.
*Note:* If there is no "__map__" section in your p8 file, Paste at the end of the file. - In the text editor, save your "mygame.p8" (Ctrl+S).
- Finally run Pico-8 engine, type "load mygame.p8" and you will see that your map tab now contains new data (small dark blue dots). Check the other tabs (code, sprites, sfx, music) to verify that everything is still there.
Congrats! Your __map__ data has been copied! The last thing you need to do is use these data, by direct access to the memory. How to do this is explained step by step below.
Display the image
Since your image data is not in the sprite tab, you cannot use the Pico-8 SPR function to draw your image. You will have to access directly to the memory location where it is stored.
You’ll need PEEK and POKE functions.
An complete example of code to do this is:
bc={0,2,8,9} -- orange function _init() cls() -- map: 0x2000 to 0x2fff (4096 bytes) -- expand (1 byte = 4 pixels (col 0..3 each)) -- to display real colors (1 byte = 2 pixels) local addr_src=0x2000 local addr_dst=0x6000 local max_bytes=4096 local i, val_src8, val_dst8 for i=1,max_bytes do val_src8 = peek(addr_src) val_dst8 = addr_col(val_src8 ) + 16*addr_col(val_src8/4 ) poke(addr_dst, val_dst8) val_dst8 = addr_col(val_src8/16) + 16*addr_col(val_src8/64) poke(addr_dst+1, val_dst8) addr_src+=1 addr_dst+=2 end end function _update() end function _draw() end function addr_col(val8) return bc[band(flr(val8),0x03)+1] end
Why 0x2000 ? Because map data is located at this address in memory. Likewise, at 0x6000 you can directly access the display memory.
A complete explanation of the Pico-8 memory sections and addresses can be found here:
A more juicy example with wavy (cosine) animation and memory optimized in chunks.
The code to perform the example above is:
bc={5,3,11,10} -- green t=0 function addr_col(val8) return bc[band(flr(val8),0x03)+1] end function _init() -- cls() rectfill(0, 0,127, 88,bc[3]) rectfill(0,89,127,108,bc[1]) -- map: 0x2000 to 0x2fff (4096 bytes, truncated to 3496 bytes because of user_data size) -- expand (1 byte = 4 pixels (col 0..3 each)) -- to pico8 user_data real colors (1 byte = 2 pixels) -- first copy map_data to user_data -- then user_data will be used to paste on display memory local addr_src=0x2000 local addr_dst=0x4300 local max_bytes=3496 local i, val_src8, val_dst8 for i=1,max_bytes do val_src8 = peek(addr_src) val_dst8 = addr_col(val_src8 ) + 16*addr_col(val_src8/4 ) poke(addr_dst, val_dst8) val_dst8 = addr_col(val_src8/16) + 16*addr_col(val_src8/64) poke(addr_dst+1, val_dst8) addr_src+=1 addr_dst+=2 end end function _update() t+=1 end function _draw() -- process each line to display memory local x,y,vo,vn local addr_tmp=0x1f80 local addr_src=0x4300 local addr_dst=0x6000 for y=0,6991,64 do x=flr(2.5+2*sin(0.04*(t-0.6*y/64))) memcpy(addr_tmp,addr_src+y+flr(x/2),64) if x%2==1 then -- use temp address to shift only 1 pixel vn=peek(addr_tmp) for px=0,63 do vo=flr(vn/16) vn=peek(addr_tmp+px+1) vo+=16*band(vn,0x0f) poke(addr_tmp+px,vo) end end memcpy(addr_dst+y,addr_tmp,64-ceil(x/2)) end print("x="..x,0,1,0) print("x="..x,2,1,0) print("x="..x,1,2,0) print("x="..x,1,0,0) print("x="..x,1,1,7) end
Make a gif
You can use the flag -repeat to process the image several times and generate an animated GIF. For example, on a Windows Command Prompt, type:
ImgToP8 -orange -repeat32 "C:\my\path\myfile.jpg"
The example above will process the image 32 times (with the orange palette). Doing this will also create a animated GIF (made of 32 frames).
It is as well possible to generate multiple still images instead.
ImgToP8 -orange -repeat32 -still "C:\my\path\myfile.jpg"
...will generate 32 preview still images (PNG). That's useful if you post-process the image frames or if you prefer the preview images not to be animated.
Animate pixels in Pico8 code
Since may 2021 (version 1.7) Image-To-Pico8 also has a solution to “fake the GIF effect” (explained above) but in P8 code.
This new version now produces Pico8 lua code (in __lua__ section of the generated .p8 file)
which integrates a small program to display the image on Pico8 screen.
It includes a graphical jitter effect as a list of “changing pixels”: these are calculated by ImageToPico8 which will be finally drawn on Pico8 side.
The rendering of these innerstate noise pixels simulates the animation of the image.
This new feature takes “87+N” tokens: one token for each of the N “changing pixels” you want to draw and 87 tokens for the built-in program itself.
- You can adjust the number of tokens to allocate in your final p8 file (with the option -noisetokensNNNN : Allocate NNNN tokens of Pico-8 code) default is 2000 tokens = 1913 pixels.
- You can remove comments in Pico-8 code to reduce byte size (lines commented with “--”) with the option -nocommentsp8.
- You can remove comments in Pico-8 code to reduce byte size (lines commented with “--”) with the option -nocommentsp8.
Example code generated by ImgToPico8 for a 128x85 image:
bc={5,15,6,7} t=0 function _init() cls() pal(15,134,1) -- map: 0x2000 to 0x2fff (4096 bytes) -- expand (1 byte = 4 pixels (col 0..3 each)) -- to display real colors (1 byte = 2 pixels) local addr_src=0x2000 local addr_dst=0x6000 local max_bytes=2720 local i, val_src8, val_dst8 for i=1,max_bytes do val_src8 = peek(addr_src) val_dst8 = addr_col(val_src8 ) + 16*addr_col(val_src8/4 ) poke(addr_dst, val_dst8) val_dst8 = addr_col(val_src8/16) + 16*addr_col(val_src8/64) poke(addr_dst+1, val_dst8) addr_src+=1 addr_dst+=2 end end function _update() t+=1 end function _draw() draw_pts() end function addr_col(val8) return bc[band(flr(val8),0x03)+1] end function draw_pts() -- list of 1913 pixel addresses (generated by ImgToPico8) local xy={-1787,1281,1150,117,1421,640,............,1,28,91,7,124,2,3,1} local v,p,c,d,i=0,0,1 for i=1,#xy do d=xy[i] if d<0 then -- change pen, innerstate d=-d p+=1 if p>7 then p=1 c+=1 end end v+=d if v>10879 then -- cycle through screen address v-=10880 end pset(v%128,flr(v/128)%85,rndp(p,c)) end rectfill(0,86,100,91,0) print("n_pts="..#xy.." cpu="..flr(stat(1)*100).."%".." t="..t,0,86,7) end function rndp(p,c) if rnd(8)<p then c+=1 end return bc[c] end
About Pico-8
Please courteously note that Image-To-Pico8 (ImgToP8) is independent software, not affiliated with Pico-8 by Lexaloffle. Nevertheless Pico-8 is a marvelous engine to make, share and play tiny games and other computer programs (and even making music thanks to its built-in music tracker). Get Pico-8! - Full Pico-8 manual
See also