Skip to content
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

feat: Add XBM encoder #2341

Closed
wants to merge 2 commits into from
Closed

Conversation

sorairolake
Copy link
Contributor

@sorairolake sorairolake commented Oct 9, 2024

I license past and future contributions under the dual MIT/Apache-2.0 license,
allowing licensees to choose either at their option.

This is an initial encoder for XBM image file format (not XPM).

The following image (◻️ = 0, ◼️ = 1):

◻️◻️◻️◻️◻️◻️◻️◻️
◻️◻️◼️◼️◼️◻️◻️◻️
◻️◻️◼️◻️◻️◼️◻️◻️
◻️◻️◼️◼️◼️◻️◻️◻️
◻️◻️◼️◻️◻️◼️◻️◻️
◻️◻️◼️◼️◼️◻️◻️◻️
◻️◻️◻️◻️◻️◻️◻️◻️

Represent this as a Rust array like the following (represents a 8-bit grayscale image):

const PIXELS: [u8; 56] = [
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
    0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff,
    0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
    0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff,
    0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
];

Encode this array as follows:

let mut writer = [0; 132];
XbmEncoder::new(&mut writer[..]).write_image(&PIXELS, 8, 7, ExtendedColorType::L8).unwrap();

Result:

#define image_width 8
#define image_height 7
static unsigned char image_bits[] = {
    0x00, 0x1c, 0x24, 0x1c, 0x24, 0x1c, 0x00,
};

I checked the encoded XBM images using an image viewer and it seems to be generated as expected.

@fintelia
Copy link
Contributor

fintelia commented Oct 9, 2024

Are you using XBM for anything in particular? I'm not sure whether we support writing L1 images for any of our other encoders, but the PNG and TIFF file formats (and perhaps others) do support it. Adding new formats adds a small but non-zero amount of maintenance burden (if nothing else it adds one more feature combination to test in CI), so we should only be adding them if there is demand.

Also we should probably document this more clearly, but the L1 encoding is meant to be a packed encoding with each byte holding 8-pixels worth of data and rows padded to byte boundaries.

@sorairolake
Copy link
Contributor Author

sorairolake commented Oct 9, 2024

@fintelia This format is useful for generating a QR code. QR code can be converted from PNG or PBM images using ImageMagick, but it is more useful to be able to generate a XBM image directly. I'm developing a command to generate QR code (https://crates.io/crates/qrtool), and this change will allow me to add XBM as an output format.

If L1 is not the correct ExtendedColorType in this case, what is the correct ExtendedColorType? Is L8 better?

@sorairolake
Copy link
Contributor Author

sorairolake commented Oct 9, 2024

It might be better to do it like this:
  • XbmEncoder::encode takes &[bool] (because only 0 or 1 are valid).
  • XbmEncoder::write_image takes L8 pixels (0 to 255), converts it to black (true) or white (false), whichever is closer, and passes it to XbmEncoder::encode.

@fintelia
Copy link
Contributor

fintelia commented Oct 9, 2024

@fintelia This format is useful for generating a QR code. QR code can be converted from PNG or PBM images using ImageMagick, but it is more useful to be able to generate a XBM image directly.

I'm not sure I follow. QR codes are 2D barcodes, they aren't tied to any specific image format. Are you using some specific software that understands XBM files but not PNG?

@fintelia
Copy link
Contributor

fintelia commented Oct 9, 2024

If L1 is not the correct ExtendedColorType in this case, what is the correct ExtendedColorType? Is L8 better?

L1 is the correct format. The code just isn't extracting the individual pixel values properly

@sorairolake
Copy link
Contributor Author

@fintelia

Are you using some specific software that understands XBM files but not PNG?

No, I don't use such software.

XBM is old, so I think the demand for this format is low. In most cases, I think using ImageMagick to convert a PNG image to a XBM image will be enough. However, if you can generate XBM images directly, you can get XBM images even if you don't have ImageMagick (or commands which can convert any other image format to XBM) installed, so I think it would be somewhat convenient.

L1 is the correct format. The code just isn't extracting the individual pixel values properly

How can I fix the code?

@sorairolake
Copy link
Contributor Author

I suspect demand for this format is low, so rather than adding an encoder to this crate it might be better to create a separate crate for the format.

@sorairolake
Copy link
Contributor Author

I changed the methods to take a 8-bit grayscale image (L8). If the pixel value is less than 128 it's considered black (1), otherwise it's considered white (0).

@kornelski
Copy link
Contributor

I still don't understand relationship to qr codes. Does the QR spec use XBM somehow? Can you embed an image inside a QR code?

@sorairolake
Copy link
Contributor Author

@kornelski QR code and XBM are unrelated. First of all, QR code is a type of barcode and not an image. I mentioned QR code as an example of a binary image. Photos can also be represented as binary images, but I think they are usually represented as RGB images.

@sorairolake sorairolake marked this pull request as draft October 10, 2024 23:21
@sorairolake
Copy link
Contributor Author

I intend to develop a separate crate for encoding (and hopefully decoding) XBM. If possible, I would like to support XBM in this crate in a similar way to QOI.

@sorairolake
Copy link
Contributor Author

I'll open another PR once I create a crate for XBM.

@fintelia
Copy link
Contributor

You should totally publish your own crate for XBM encoding.

As far as adding support to image, that would take much more justification. XBM doesn't seem to be used much and it really isn't a very good format by modern standards.

@sorairolake
Copy link
Contributor Author

@fintelia I agree that XBM is lesser-known. Based on this discussion, even after an XBM implementation is developed, I don't intend to add support for XBM to this crate.

@sorairolake sorairolake deleted the xbm-encoder branch October 12, 2024 04:56
@sorairolake
Copy link
Contributor Author

https://crates.io/crates/xbm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants