python-pillow / python-pillow/Pillow

Change pixel size of "LA", "La", and "PA" from 4 to 2

Open
#6,503 8 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
13.8k
Forks
2.5k
Avg merge
2d 8h
Merged PRs (30d)
89

Description

These image modes currently use 4 bytes for each pixel, but they only need two. I've started looking into this, but there are a lot more changes than I expected, so I'm creating this issue for documentation. The files I've found that need to be changed are:

  • /src/libImaging/Access.c
    • ImagingAccessInit() contains a mapping to three functions (also defined in this file) for each of these modes.
  • /src/libImaging/Bands.c
    • Lots of special casing for "LXXA", and some functions assume an image with 2 bands uses 4 bytes per pixel.
  • /src/libImaging/Convert.c
    • All of the conversion functions for these modes.
  • /src/libImaging/Geometry.c
    • bicubic_filter32LA() and bilinear_filter32LA().
  • /src/libImaging/GetBBox.c
    • ImagingGetBBox() creates a bit mask for the alpha channel.
  • /src/libImaging/Imaging.h
    • IMAGING_PIXEL_LA and IMAGING_PIXEL_PA are defined in this file, though they aren't used anywhere.
  • /src/libImaging/Jpeg2KDecode.c
    • j2ku_graya_la() is currently used for both "LA" and "RGBA", so it will first have to be duplicated and renamed for "RGBA", and then the original can be modified.
  • /src/libImaging/Jpeg2KEncode.c
    • j2k_pack_la().
  • /src/libImaging/Pack.c
    • The references to packLA() can be replaced with copy2(), and packLAL() needs to be modified. packLA() is no longer used after this change, so it can be removed.
  • /src/libImaging/Paste.c
    • fill_mask_L() uses a mask for the alpha channel, and ImagingPaste() calls the same function for "LA" and "RGBA".
  • /src/libImaging/Storage.c
    • The image pixel size and line size are set in ImagingNewPrologueSubtype().
  • /src/libImaging/Unpack.c
    • unpackLA() and unpackLAL().
  • /src/PIL/PyAccess.py
    • The mode_map uses _PyAccess32_2() for these modes.

Changing im->pixelsize from 4 to 2 also means the image data will be stored in im->image8 instead of im->image32. im->image also exists and always holds the image data. The only difference between these pointers is their type: image is char, image8 is UINT8, and image32 is INT32. Some functions check for im->image8 being set and do different things based on that.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing ImagingNewPrologueSubtype() in src/libImaging/Storage.c and ImagingAccessInit() in src/libImaging/Access.c, then follow the listed LA, La, and PA handling across the C files and src/PIL/PyAccess.py. Confirm that the modes use a two-byte pixel size, image8 storage, and correct access, conversion, geometry, JPEG 2000, packing, pasting, and unpacking behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, python
Domain
computer-graphics
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.