Giter VIP home page Giter VIP logo

dither's People

Contributors

deining avatar makew0rld avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

dither's Issues

Support images with alpha channel

Thanks to @/Shrinks99

This will not do dithering in the alpha channel, but it will properly handle images with non-opaque pixels.

  • Leave fully transparent pixels as they are
  • Partially transparent pixels (example)
    • I have a premult color, a=0.5
    • I take the RGB and dither it, and end up with a palette color (with implicit a=1)
    • I multiply the palette color by 0.5
    • I store the multiplied color with a=0.5

DitherPaletted wouldn't support this, as this would require breaking the guarantee that the returned image has the same palette as the Ditherer.

Support strength value for error diffusion

As demonstrated here, it's possible to have a strength value for error diffusion too. This can be added as a struct field in Ditherer, where the default value of 0 indicates 100% strength. This will not break compatibility.

Dithering with a grayscale palette has "unexpected" results with color image input

"unexpected" is in quotes because the math is sound, but the result is almost never what you want. This is a property of dithering, and is not related to the library code.

The bad output can be very severe with error diffusion dithering, but ordered dithering still can have issues too.

The solution is to always make an image grayscale before dithering with a grayscale palette. The library should have a convenience function for this, as well as explain it in the README. Should the library detect grayscale palettes and make the image grayscale automatically when dithering? Probably not, the user should still have the option to.

Example

Original image:

KodakTestImage

Original image but made to black and white:

KodakTestImage-gray

Floyd-Steinberg dithering the color image with an 8-bit sRGB grayscale palette of 0, 156, 213, 255. 100% strength:

fss

And the same, but dithering the black and white image:

fss-gray-before

High memory usage on bigger images

I've noticed recently that dither uses ~500MB of RAM when dithering an example 3414x1920 image and it doesn't appear to run through a garbage collection after dithering.

Is this an expected behavior? If yes, could it be somehow reduced?

Minimal reproducer:

package main

import (
	"fmt"
	"image"
	"image/color"
	"image/png"
	"os"

	"github.com/makeworld-the-better-one/dither/v2"
)

func Dither() {
	reader, err := os.Open("/home/tfuxc/Pictures/wallhaven-m9rqlk.png")
	if err != nil {
		panic(err)
	}
	defer reader.Close()

	img, _, err := image.Decode(reader)
	if err != nil {
		panic(fmt.Sprintln("decode err:", err))
	}

	palette := []color.Color{
		color.Black,
		color.White,
		color.RGBA{255, 0, 0, 255}, // Red
		color.RGBA{0, 255, 0, 255}, // Green
		color.RGBA{0, 0, 255, 255}, // Blue
	}

	d := dither.NewDitherer(palette)
	d.Matrix = dither.FloydSteinberg

	img = d.Dither(img)

	writer, err := os.Create("dithered.png")
	if err != nil {
		panic(err)
	}

	encode_err := png.Encode(writer, img)
	if encode_err != nil {
		writer.Close()
		return
	}

	if err := writer.Close(); err != nil {
		panic(err)
	}
}

func main() {
	for i := 0; i < 4; i++ {
		Dither()
	}

	var input string
	fmt.Println("Done! Press a key and enter to close.")
	fmt.Scan(&input)
}

Note

Minimal reproducer does a dithering operation four times to show that the allocated memory is exponentially higher in subsequent iterations.

Pigeon dithering

It's odd this type of dithering is referred to using a full name of its creator when all other dithering types are referred to only by the surname of the creator.

How about just Pigeon?

This is mentioned/proposed in the comments of the page that you link to.

Palette order affects output

This issue was originally made for the didder repo, so didder commands are referenced.


This is a strange and important bug.

These are the two commands:

didder -i input.png -o test.png  -p 'black red white' edm FloydSteinberg
didder -i input.png -o test2.png -p 'black white red' edm FloydSteinberg

input.png is this image:

table

Here are the respective outputs:

test
test2

Obviously, they should be exactly the same. This only occurs with edm and does not depend on the matrix used. This does not seem to occur with the upstream dither library, indicating the problem is with the didder code.

Update Bayer recommendations

From the Bayer docs:

As for color images, after my own experimentation, I've determined that everything I said above about grayscale images still applies. Stick to 1.0 and Bayer sizes above 4x4 if you can, and changing the strength still changes contrast as described above.

This is false.

For example, here is a color image:

KodakTestImage

Here is 16x16 Bayer with an 8-bit sRGB grayscale palette of 0, 156, 213, 255. 100% strength.

100

The second image is obviously being made lighter despite being above 4x4 in the recommendations.

Clustered-dot dithering matrix generation

Hi, I saw the post in your blog re dithering, where you asked if one know how to do clustered dithering to contact you. Dithering you mentioned is usally called halftone dithering and have long history in silk printing and offset printing. You can find many resources on it on the net, but what you have to do is sample your image withe some frequency in 256 levels of gray, and then replace each sample by 16x16 matrix of pixels representing 256 levels of gray. It can be also be done with lines instead of dots resulting in line raster, where you vary width of the line with intensity. It is also not bad idea to do bluring and unsharp masking before sampling which is equivalent of applying lowpas 2d filter before sampling as in Niquist theorem where you first filter the signal before sampling to avoid artifacts. If you want to do quick experiment, just replace each pixel with 8x8 pixels representing black dots on white background for levels below 50% and white dots on black background for leves above 50%. If you need any help feel free to contact me at robert.aleksic at gmail.com. cheers robby

p.s. if you want to do it in color, you separate your image to components like CMYK for ofset printing and then apply all four images one on on top of the other, with varying angles of raster to obtaine nice rosette like here: https://cdn2.hubspot.net/hubfs/2296165/Imported_Blog_Media/CMKdot-1.jpg. Black component is created to avoid usage of to much ink and preserve gray balance, but that is another topic - color calibration.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.