golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.06k stars 17.55k forks source link

x/image/bmp: support 1-bit format #29711

Open cbrake opened 5 years ago

cbrake commented 5 years ago

Hi, I implemented support for 1-bit bmp files in the reader:

https://github.com/cbrake/golang.org-x-image/commit/25481fe1980277e4b3206c11a3fc15e2ec31eddc

Is there interest merging this (or an improved version)?

ALTree commented 5 years ago

cc @nigeltao

nigeltao commented 5 years ago

I'm open to merging 1-bit support, although if it's not too much extra work, it'd be nice to also get 2-bit and 4-bit support.

cbrake commented 5 years ago

I'll look into 2/4 bit.

Is writer support needed? It does not seem that the 1/2/4 bit formats are supported in the image pkg, but I may be missing something:

https://golang.org/pkg/image/color/#Model

nigeltao commented 5 years ago

Writer support is not needed.

When reading, decode to an image.Paletted or image.RGBA, even for 1/2/4 bits per pixel.

ljubomirb commented 5 years ago

But how to write to 1bit then? I'm also missing something. Is there any blog or example you can point us @nigeltao, please? Because, if using image filters like dithering, you will always get bw 1bit result. With my limiting knowledge, I always end up using image.Gray, and that is not what I need. Looking at image.Gray, I think I see it is defined as h.bpp = 8. How to get it to be 1?

nigeltao commented 5 years ago

If you really must write 1bpp images, then I think you're going to have to fork the bmp package, as the image package doesn't have a specific representation for 1bpp. Or write your own package. If your input is always going to be 1bpp, writing that particular subset of the BMP file format shouldn't be that complicated.

If you're talking about dithering, it's already possible (using Go's standard and x libraries) to dither to a 2-element palette (black and white). You can either encode that directly, or convert that to your own 1bpp representation.

ljubomirb commented 5 years ago

The thing is, 1bit bmp has its use and purpose. One such is for laser engraver machines. In particular, I wanted to write the Go variant of uploader/control software for one such, very common device. The same thing exists, thanks to community doing reverse engineering, in almost any language you can imagine, all on github, in Swift, C#, Qt, Python and so on... But not in Go. I'll simply use different language for this project now, but please, do consider implementing 1bit bmp support. Thank you.

yanolab commented 4 years ago

@ALTree @nigeltao I've created a 1/2/4bit bitmap writer. Can you review it when I sent a PR?

nigeltao commented 4 years ago

Can you review it when I sent a PR?

I could possibly be persuaded otherwise, but I'll repeat my earlier comment: "If you really must write 1bpp images, then I think you're going to have to fork the bmp package, as the image package doesn't have a specific representation for 1bpp."

Not every useful feature has to live in the Go standard library or the golang.org/x libraries.

yanolab commented 4 years ago

@nigeltao Thank you for your reply :)

Not every useful feature has to live in the Go standard library or the golang.org/x libraries. Could you tell me why you decline contributes? Is it for maintenance? I'm thinking 1bit support is not so big change.

IMO, I'm not sure if there's a demand for 2/4 bit bitmap support. However, there is a demand for 1bit bitmap support. Therefore, I thought this issue was created. Also the above comments say there must be some demands. Actually, I needed 1bit bitmap, therefore I wrote the writer. Recently, QR codes are being used everywhere. For example, payment, logistics management and so on. And sometime it's required 1bit bitmap by special devices. So there is a worth to support it as a library for golang community.

nigeltao commented 4 years ago

Could you tell me why you decline contributes? Is it for maintenance?

Partly maintenance, but partly because it's not obvious how to adapt or extend the encoding API in a backwards compatible way, that doesn't involve changes to the standard library (e.g. its image.Image concrete types), but also plays well with current and future encoding APIs and options (e.g. color spaces and other metadata, speed-quality trade-offs, multi-threadedness) for other standard-or-x image libraries, again noting their compatibility constraints.

there is a demand for 1bit bitmap support.

I'm not denying that 1-bit BMPs are a useful feature. To repeat myself, I'm saying that not every useful feature has to live in the Go standard library or the golang.org/x libraries.

yanolab commented 4 years ago

I see. Thank you for your reply.

erkie commented 3 years ago

Seems like this PR got stuck on the question of writing 1-bit files, but it does implement reading, which is great for our use case. Is it worth merging? Would love 2 and 4 bit support as well but this is a good start.

nigeltao commented 3 years ago

I'm OK with that but IIUC it's up to @cbrake to start a PR.

cbrake commented 3 years ago

I'm interested in getting this merged, but it would take me some time to get through all the steps to get set up as a Go contributor (review license CLA, set up accounts, etc) as I'm no longer working on this project and don't have funding to do this work. If anyone else is interested, please feel free to use my patch in any way helpful.