-
-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
color divergence in sixel with fewer colors than color registers #2503
Comments
even more oddly, i only see 11 colors in |
yep that's why |
those deets entries look a bit askance, though maybe i'm forgetting something... |
yeah these hi/lo values are fubar:
|
ok the 56 is floor(0x90100/255). so that's sixel space. likewise floor(0x50100/255) == 31...though how we're ending up with different hi vs lo remains confusing. |
so is this all due to our preclumping, where we're applying that large mask?
differences of 40, 24, and 48. we start with a mask of 0xc0, aka two bits, aka enclumpenings of 64, so yeah, that's wide enough to take them. still, if we're storing with full precision, we ought be able to get them out losslessly. so it looks like that's where our breakage is. |
yeah we're always averaging in |
definite bug in |
alright, i think i've found one trick that wins us back a good bit of quality, testing for performance regression... |
yeah that seems to improve the visual a decent bit, though our average error changes very little... |
alright, bold new idea for the relaxation algorithm: initially, we take a 323 MSB liftup from the channels. use that as a key into a 256-element table. now the full extraction is O(1) per pixel (currently O(lgn)), at the cost of a possibly sparse color table. but use that same sparsity as a topological guide to our relaxation, relying on some locality. if need be at the end, compress the table down -- this can be delayed until encoding time, and done on the fly. this ought be a very substantial improvement, i think. |
I would really like to port your encoder sometime to Java for the vastly superior speed and quality over other sixel encoders. Do you have a planned milestone spot in the future that would be a good place to start from? |
progress thus far indicates about a 50% cut in sixel quantization runtime, fuckin' sweet |
righjt now the encoder's no good =] i'm bringing it up to at least libsixel territory now. libsixel uses straight-up maxmedian cut (as you do, iirc), of which i'm not a tremendous fan. i think octrees are likely the way to go, though i've been playing around with kohonen neural networks. my deep dislike for statistical/ML methods means i probably won't go that way, either. right now i'm experimenting with static octree preclustering + my own "relaxation" approach, and it is showing very positive results. #1452 then suggests getting rid of the final iteration of relaxation, which i think is a great idea, but we'll see. i'm down to a bit under 50% of my old rendering time with just the octree preclustering, but i've got a bug in there for images that are fewer than 256 colors. i should have it knocked out tonight, hopefully. on the left is current algorithm, running in .9s±.2s when coming from page cache. on the right is the new algorithm, running in .5s±.1s when coming from page cache. |
(of that .5s, about .35s is due to writing out to the terminal, and the terminal rendering, so we're talking about .4s vs .1s for actual quantization, so a bit more speedup than advertised) |
ok, i think i just got that bug resolved. things are looking very good... |
so we're seeing equal quality on most images now, while preserving nice speed pickups....except for |
likewise we're definitely slower and crappier on |
new algorithm:
old:
but then on
new:
new pastes old on AllRGB images:
old:
soooooooooo AllRGB is going to fill up the color table on the initial pass, causing the second pass to abort immediately (it's also going to be dominated by writing/processing time, as they're 64MB RGB). meanwhile, very few colors are going to likewise cause very little second phase, since most will get slotted out to different octets in the first phase. so that points to our first phase being good, and our second phase being ass. it doesn't explain why we look shittier in that case, though. maybe a remaining bug in the second phase? well, we ought be able to cut a chunk off that ass with the #1452 proposal. let's apply that and see where we get. if that doesn't win in all cases, i think we move to an all-octree solution, and call it a day. |
but yeah the original motivation for this bug, the divergence, is eliminated. |
alright, we're now functional on images with more leaves than color registers, though it's a first-order merge and tends to look like shit. that ends functional necessities; i'm going to clean out the diagnostics and start some fine-tuning and numeric comparison. i expect to merge this tonight. |
here's some crude xterm 80x61 (880x1403)new
current
contour is kinda unstable right now, and i'm not smart enough to copy-and-paste from xwayland into chrome on x so we only have xterm numbers. but alright! the only one where we would expect to see big timing changes is alright, this is looking good, performance-wise! let's get some detailed info from |
(from the same runs as above) currentBitmap emits:elides: 1420:306 (17.73%) 66.70MiB (59.70%) SuM: 0 (0.00%) newBitmap emits:elides: 1444:304 (17.39%) 44.32MiB (49.74%) SuM: 0 (0.00%) so it looks like we're emitting significantly smaller bitmaps, which surprises me. we'll want to look into that and determine why, i think. i mean, it's a good effect, but it needs to come from a righteous cause. |
alright, so we see a slight increase in accuracy on current
new
worldmap, as expected, looks worse (though it is slightly faster and smaller) current
new
time to run current
new
both current and new seem to generate a busted ncvisual on intake from sixel in
current
new
so current beats new on these pathological images. time to run new
current
|
ok, i'm thinking i'm gonna merge this, and work to improve the two cases that have regressed (smooth gradients result in more banding due to eliminating relaxation; large numbers of leaves lead to slowness and quality droppage). the causes of both problems are understood, and this is a much better foundation to work from going forward. the first problem will be easier to solve -- we just need to add fast relaxation. on the latter, we need better merging, but that's not going to give us any perf back, and we already have a perf deficit. we'll have to science up that bitch. |
i still don't understand why we're seeing such a high average diff on |
|
#0;2;44;28;9#1;2;56;28;16#2;2;44;19;9#3;2;69;41;28#4;2;85;53;44#5;2;94;75;63 |
44;28;9: 113 / 72 / 23 : 0x71 / 0x48 / 0x17 : 01110001 / 01001000 / 00010111 : 0100 1 ... wait. how is
WTF? we've got a 13-bit number there, with one bit undefined, you dumb chungus! no wait.... rrrr gggg gbbb ok it's fine i thought g was coming out. so back to above... key: 0111 0100 1000 (0x748 == 1864) which is indeed 0xff184870 -> 1864 0x714817 isn't that off from 0x704818, certainly not enough to yield that high an average difference...i think our tool might be fucked up. |
oh shit i wonder if we're counting transparent pixels or something |
yep!
|
much better =] |
I am just now realizing that the total sixel color space is (101)^3 a.k.a. 19.97 bits, not 24 bits. If your stats are looking at before/after differences in 24 bit space, you might actually be much closer to the best possible coverage. |
with
quantanal
improved in #2502, we're now seeing divergence on a more complex, but still simple, image:we're for some reason using 10 more colors, and missing by a wide 71.5 per. adding
NOINTERPOLATION
makes things worse:meanwhile, on another, we drastically reduce the number of colors:
The text was updated successfully, but these errors were encountered: