Yet yet another NES palette capture

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Yet yet another NES palette capture
by on (#161642)
Just for fun, I decided to try what kind of an NES palette I would get by capturing from my el cheapo USB capture stick (Terratec Cinergy Hybrid T USB XS). I wrote a ROM to display all of the colors one after another, ran the ROM on my NTSC NES and PAL NES, captured a video with VirtualDub, and ran an AviSynth script to generate a palette picture.

Capture format was YUY2 (the stick doesn't support anything else), losslessly compressed with Lagarith (probably didn't help much). Settings (brightness/contrast/hue/saturation/sharpness) were at defaults.

ROM + source for ASM6 is attached (read the source header for usage instructions). The captured videos are pretty big (~50 MB) so I won't put them here.

Here are the palettes I got:
Attachment:
ntsc.png
ntsc.png [ 4.06 KiB | Viewed 7537 times ]

Attachment:
pal.png
pal.png [ 4.08 KiB | Viewed 7537 times ]

AviSynth script: (If somebody else wants to use this, you will need to tweak a thing or two.)
Code:
# c = AVISource( "ntsc-nes-full-palette.avi" )
c = AVISource( "pal-nes-full-palette.avi" )

# CONFIG: Use TFF or BFF depending on input video. If the colors aren't laid
# out properly, you picked the wrong one. "Properly" means gray in the upper
# left corner, then blue, and so on.
c = c.AssumeTFF()
# c = c.AssumeBFF()

# Remove bogus deinterlacing.
c = c.SeparateFields()

# Trim to only the relevant frames.
# CONFIG: Set the first (gray) frame.
# kFirstFrame = 47 # ntsc-nes-full-palette.avi
kFirstFrame = 48 # pal-nes-full-palette.avi
c = c.Trim( kFirstFrame, kFirstFrame+511 )

# Convert to RGB to have a common colorspace to work in independent of the
# input video format.
# \todo Not sure if there are downsides to doing this conversion?
c = c.ConvertToRGB()

# Crop to remove some crap from the borders.
kResultSize = 128
kCropHorz = (c.Width()  - kResultSize)/2
kCropVert = (c.Height() - kResultSize)/2
c = c.Crop( kCropHorz, kCropVert, -kCropHorz, -kCropVert )

# Average the result by resizing down.
# \note Resizing to less than 4x4 produces an error.
# \todo Not really sure how good of a job this really does of averaging
#       all the colors.
c = c.BicubicResize( 4, 4 )

# Crop to actually go down to 1x1.
c = c.Crop( 2, 2, -1, -1 )

# Convert to a single 16x32 frame.
c = c.WeaveColumns( 16 )
c = c.WeaveRows( 32 )

# Resize the palette elements up.
kPaletteElemSize = 24
c = c.PointResize( c.Width()*kPaletteElemSize, c.Height()*kPaletteElemSize )

c
Re: Yet yet another NES palette capture
by on (#161645)
I know this is off subject, sorry...but what's the deal with your website being down (fauxgame)?
Re: Yet yet another NES palette capture
by on (#161646)
dougeff wrote:
I know this is off subject, sorry...but what's the deal with your website being down (fauxgame)?

I used to have a VPS at LeaseWeb where I was hosting my sites. Through their amazing competency they managed to delete all of the data on my server without notice. I have some (fairly old) backups, but I can't bother to set up a new server, so I'll upload some of the old stuff to a new site when I get around to it.
Re: Yet yet another NES palette capture
by on (#161649)
If you don't need any server-side stuff, you can just put your web root on Amazon S3.
Re: Yet yet another NES palette capture
by on (#161732)
Github lets you host static websites for free.
Re: Yet yet another NES palette capture
by on (#161734)
Don't GitHub Pages have to be the documentation for associated open source projects also hosted by GitHub?

EDIT: Probably not, though they're not secure.
Re: Yet yet another NES palette capture
by on (#162402)
With the capture format set to YUY2, there are two colorspace conversions that led to the PNGs you posted: one from YIQ to YUV (in the capture hardware), and then another from YUV to RGB when the image was exported to RGB (in AviSynth, probably). The chroma subsampling in YUY2 (4:2:2) doesn't affect the results here, particularly if you are looking at the center of each rectangle.

I was going to ask which RGB primaries and white point you used, but with the intermediate YUV step, it gets even more complicated to produce the correct color.

As I pointed out here, the NTSC standard changed in 1987, AFTER the NES and Famicom were designed and released. The differences are a little bit subtle. If you're looking for what colors the designers saw when they made the PPU, not to mention what colors players saw on their own TVs before the late 1980s, then you should ensure that your NTSC captures use the right parameters.

As reported by Wikipedia, the correct primaries are:
Code:
Xr     Yr     Xg     Yg     Xb     Yb     Xw     Yw
0.67   0.33   0.21   0.71   0.14   0.08   0.31   0.316
I'd be curious if your capture software or AviSynth lets you adjust these values.
Re: Yet yet another NES palette capture
by on (#162403)
I thought YIQ was just a 33 degree phase rotation of YUV, because it was determined that the eye is more sensitive to chroma detail along the orange-teal axis than the green-magenta axis. The rotation from YIQ to YUV should be trivial to calculate in the card. In fact, all but the highest end devices decode NTSC as if it were YUV anyway because it's cheaper.
Re: Yet yet another NES palette capture
by on (#162406)
tepples wrote:
I thought YIQ was just a 33 degree phase rotation of YUV
I think that's right. I guess the same RGB primaries are plugged into the YUV->RGB equation as the YIQ->RGB equation, so it's just a question of whether AviSynth lets you change the primaries. ("c.ConvertToRGB()" almost certainly defaults to 1987 settings.)

The other reason a YUV capture might make determining the "true" palette more complicated is, if Wikipedia is to be believed, using a YUV filter instead of a YIQ filter is cheaper, but sacrifices some color accuracy.
Re: Yet yet another NES palette capture
by on (#162408)
My goal here was not to find the one true palette, but rather to provide one data point from the wild. That's why I tried my best to document the model of the capture stick and what processing was done to obtain the result.

EDIT: Here are the .PAL files. The ones ending with "-full" contain all 512 colors; ones without only have the 64 non-emphasized colors.
Attachment:
terratec-cinergy-hybrid-t-usb-xs-nes-palettes.zip [3.71 KiB]
Downloaded 244 times

(Protip: Easy way to make a .PAL file from a palette image like that in the first post is to scale the image down (nearest neighbor) so that each color is 1x1 px, and then save it as a "raw" image (just the pixels, color components interleaved, no header). This can be done in Photoshop, and probably many other image editors as well.)
Re: Yet yet another NES palette capture
by on (#162410)
LightStruk wrote:
if Wikipedia is to be believed, using a YUV filter instead of a YIQ filter is cheaper, but sacrifices some color accuracy.

It sacrifices accuracy on the edges of colored areas, but not in flat areas. If you're just making an "NES palette", flat areas matter. If you're trying to emulate edge artifacts, you'll need to implement the YUV or YIQ decoder in software or in a shader anyway.
Re: Yet yet another NES palette capture
by on (#171548)
...
Re: Yet yet another NES palette capture
by on (#171568)
...
Re: Yet yet another NES palette capture
by on (#171606)
Edit (removed)...reasons.