Commit Graph

26 Commits

Author SHA1 Message Date
kris
0009ce8913 - allow reserving a number of colours which are to be shared across
all palettes.  This will be useful for Total Replay which does an
  animation effect when displaying the image (first set palettes, then
  transition in pixels)

- this requires us to go back to computing k-means ourself instead of
  using sklearn, since it can't keep some centroids fixed

- try to be more careful about //gs RGB values, which are in the
  Rec.601 colour space.  This isn't quite right yet - the issue seems
  to be that since we dither in linear RGB space but quantize in the
  nonlinear space, small differences may lead to a +/- 1 in the 4-bit
  //gs RGB value, which is quite noticeable.  Instead we need to be
  clustering and/or dithering with awareness of the quantized palette
  space.
2021-11-17 17:09:42 +00:00
kris
ee2229d0ea * Modify Floyd-Steinberg dithering to diffuse less error in the y
direction.  Otherwise, errors can accumulate in an RGB channel if
  there are no palette colours with an extremal value, and then when
  we introduce a new palette the error all suddenly discharges in a
  spurious horizontal line.  This now gives quite good results!

* Switch to using L1-norm for k-means, per suggestion of Lucas
  Scharenbroich: "A k-medians effectively uses an L1 distance metric
  instead of L2 for k-means.  Using a squared distance metric causes
  the fit to "fall off" too quickly and allows too many of the k
  centroids to cluster around areas of high density, which results in
  many similar colors being selected.  A linear cost function forces
  the centroids to spread out since the error influence has a broader
  range."
2021-11-11 11:10:22 +00:00
kris
80885aabf9 Working SHR version. Still just uses a single palette 2021-11-09 22:26:34 +00:00
kris
173c283369 First implementation of using k-means clustering in RGB space to dither a 320x200 SHR image. 2021-11-09 11:23:25 +00:00
kris
7e68847bfe nit 2021-11-04 14:31:33 +00:00
kris
b7174778e6 Oops, no that was wrong. I forgot to cross-check against OpenEmulator <o> 2021-11-03 12:40:22 +00:00
kris
bf76271d75 NTSC conversion should be using YIQ space instead of YUV, which seems
to explain several fudge factors I needed to include to match colours.
2021-11-02 23:28:58 +00:00
kris
52bd35e875 Update comment 2021-11-02 22:15:09 +00:00
kris
9dbf413733 Tidy 2021-11-02 15:45:20 +00:00
kris
b63fd81c07 Unify DHGRScreen implementations 2021-11-02 15:23:23 +00:00
kris
75a3c6bc48 Simplify image_to_rgb and remove the need for DOTS and DOTS_TO_INDEX 2021-11-02 15:14:22 +00:00
kris
809b975e6e Return a bitmap directly from dither_image. This removes the need to
deal with n-bit encodings at all in DHGRScreen
2021-11-02 14:42:00 +00:00
kris
8cfee55b1d Get rid of support for 140px mode, it was only useful as a demo of why
other converters have the wrong basic approach.
2021-11-02 13:40:32 +00:00
kris
e08f25e4cc Simplify 2021-07-19 12:55:50 +01:00
kris
508ce134aa Try to fix how we compute the next pixel palette for 8-bit mode.
Still not sure this is correct.
2021-07-19 09:58:22 +01:00
kris
527f6504f7 Add comments and tidy up some more 2021-03-15 17:22:14 +00:00
kris
e98116b276 Tidy up for merge 2021-03-15 14:01:14 +00:00
kris
467a0cd196 Tidy up a bit to prepare for merge 2021-03-15 10:45:33 +00:00
kris
e0b732cdaa Reimplement NTSC conversion to closely match openemulator output. I
can't figure out why contrast=2 is needed (openemulator uses a default
value of 1, so there must be a factor of 2x somewhere), or where the
slight hue rotation comes from - perhaps this is somehow introduced by
the more complex band-pass filtering that openemulator does?

I needed to also account for the DHGR timing difference that
introduces a phase offset of 1 pixel between the memory values and
displayed pixel timings.

Fix a last-minute bug with palette precomputation.
2021-02-17 21:29:43 +00:00
kris
ad9515dcf2 Implement NTSC emulation, using an 8 pixel window for chroma signal.
Use this to precompute a new ntsc palette with 256 entries (though
only 84 unique colours) that are available by appropriate pixel
sequences.  Unfortunately the precomputed distance matrix for this
palette is 4GB!

Optimize the precomputation to be less memory hungry, while also
making efficient use of the mmapped output file.

Add support for dithering images using this 8-bit palette depth,
i.e. to optimize for NTSC rendering.  This often gives better image
quality since more colours are available, especially when modulating
areas of similar colour.

Fix 140 pixel dithering and render the output including NTSC fringing
instead of the unrealistic 140px output that doesn't include it.

Add support for rendering output image using any target palette, which
is useful e.g. for comparing how an 8-pixel NTSC rendered image will
be displayed on an emulator using 4-pixel ntsc emulation (there is
usually some colour bias, because the 8 pixel chroma blending tends to
average away colours).

Switch the output binary format to write AUX memory first, which
matches the image format of other utilities.
2021-02-14 23:34:25 +00:00
kris
301ca2772b Checkpoint 2021-02-04 22:00:03 +00:00
kris
3ac5c284e9 Checkpoint NTSC emulation 2021-02-03 23:40:16 +00:00
kris
2bbd65a079 Add some comments and docstrings 2021-01-25 23:16:46 +00:00
kris
9f0cd870e7 In 140px resolution show the output image with and without NTSC fringing 2021-01-16 18:11:21 +00:00
kris
a061795022 Re-enable 140px mode 2021-01-15 22:58:01 +00:00
kris
31b565f22a Refactor a bit 2021-01-15 22:18:25 +00:00