-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Add support for high bit depth multichannel images #8224
base: main
Are you sure you want to change the base?
Changes from all commits
1c2d465
e0bb623
9cbb840
90840ae
03df357
936439b
a4fab13
76d336d
ed15ed9
fb7702f
86e7fc6
587bb98
0df0935
c4434df
c5ebc81
e0a5d81
44da8b6
5bdda4c
df98223
2426e57
3cf311b
b6ce6ab
d5053fb
d5844a9
bd2543e
0cbc265
a9e1dcf
282e7ec
605c408
e79b88e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -290,7 +290,7 @@ | |
int bands; | ||
|
||
/* FIXME: add primitive to libImaging to avoid extra allocation */ | ||
im = ImagingNew(mode, 0, 0); | ||
im = ImagingNew(mode, (ImagingNewParams){0, 0}); | ||
if (!im) { | ||
return -1; | ||
} | ||
|
@@ -414,6 +414,36 @@ | |
return out[0]; | ||
} | ||
|
||
static inline PyObject * | ||
getpixel_mb(Imaging im, ImagingAccess access, int x, int y) { | ||
UINT8 pixel[sizeof(INT32) * 6]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the 6 from here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This used to be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The C layer has to be internally safe, we can't be relying on inderict python restrictions for memory safety like that. If we can't do this statically, it's going to have to be dynamic, or there needs to be an arbitrary band limit constant somewhere in the code. (Which ultimately, may be a good idea, if only to prevent someone from creating an image with 2^32-1 bands) |
||
assert(im->pixelsize <= sizeof(pixel)); | ||
access->get_pixel(im, x, y, &pixel); | ||
|
||
PyObject *tuple = PyTuple_New(im->bands); | ||
if (tuple == NULL) { | ||
return NULL; | ||
} | ||
|
||
UINT8 *pos = pixel; | ||
for (int i = 0; i < im->bands; ++i) { | ||
switch (im->depth) { | ||
case CHAR_BIT: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style note - CHAR_BIT isn't used elsewhere here, We're just using 8 |
||
PyTuple_SET_ITEM(tuple, i, PyLong_FromLong(*pos)); | ||
break; | ||
case 2 * CHAR_BIT: | ||
PyTuple_SET_ITEM(tuple, i, PyLong_FromLong(*(UINT16 *)pos)); | ||
break; | ||
case 4 * CHAR_BIT: | ||
PyTuple_SET_ITEM(tuple, i, PyLong_FromLong(*(INT32 *)pos)); | ||
break; | ||
} | ||
pos += im->depth / CHAR_BIT; | ||
} | ||
|
||
return tuple; | ||
} | ||
|
||
static inline PyObject * | ||
getpixel(Imaging im, ImagingAccess access, int x, int y) { | ||
union { | ||
|
@@ -435,6 +465,10 @@ | |
return NULL; | ||
} | ||
|
||
if (im->type == IMAGING_TYPE_MB) { | ||
return getpixel_mb(im, access, x, y); | ||
} | ||
|
||
access->get_pixel(im, x, y, &pixel); | ||
|
||
switch (im->type) { | ||
|
@@ -649,7 +683,7 @@ | |
return NULL; | ||
} | ||
|
||
im = ImagingNewDirty(mode, xsize, ysize); | ||
im = ImagingNewDirty(mode, (ImagingNewParams){xsize, ysize}); | ||
if (!im) { | ||
return NULL; | ||
} | ||
|
@@ -670,13 +704,14 @@ | |
static PyObject * | ||
_new(PyObject *self, PyObject *args) { | ||
char *mode; | ||
int xsize, ysize; | ||
int xsize, ysize, depth = -1, bands = -1; | ||
|
||
if (!PyArg_ParseTuple(args, "s(ii)", &mode, &xsize, &ysize)) { | ||
if (!PyArg_ParseTuple(args, "s(ii)|ii", &mode, &xsize, &ysize, &depth, &bands)) { | ||
return NULL; | ||
} | ||
|
||
return PyImagingNew(ImagingNew(mode, xsize, ysize)); | ||
return PyImagingNew(ImagingNew(mode, (ImagingNewParams){xsize, ysize, depth, bands}) | ||
); | ||
} | ||
|
||
static PyObject * | ||
|
@@ -897,7 +932,9 @@ | |
return NULL; | ||
} | ||
|
||
imOut = ImagingNewDirty(mode, self->image->xsize, self->image->ysize); | ||
imOut = ImagingNewDirty( | ||
mode, (ImagingNewParams){self->image->xsize, self->image->ysize} | ||
); | ||
if (!imOut) { | ||
free(prepared_table); | ||
return NULL; | ||
|
@@ -1083,7 +1120,7 @@ | |
} | ||
|
||
imIn = self->image; | ||
imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize); | ||
imOut = ImagingNewDirty(imIn->mode, (ImagingNewParams){imIn->xsize, imIn->ysize}); | ||
if (!imOut) { | ||
return NULL; | ||
} | ||
|
@@ -1699,7 +1736,9 @@ | |
|
||
if (!self->image->xsize || !self->image->ysize) { | ||
/* no content; return an empty image */ | ||
return PyImagingNew(ImagingNew("P", self->image->xsize, self->image->ysize)); | ||
return PyImagingNew( | ||
ImagingNew("P", (ImagingNewParams){self->image->xsize, self->image->ysize}) | ||
); | ||
} | ||
|
||
return PyImagingNew(ImagingQuantize(self->image, colours, method, kmeans)); | ||
|
@@ -1905,7 +1944,7 @@ | |
a[2] = box[0]; | ||
a[5] = box[1]; | ||
|
||
imOut = ImagingNewDirty(imIn->mode, xsize, ysize); | ||
imOut = ImagingNewDirty(imIn->mode, (ImagingNewParams){xsize, ysize}); | ||
|
||
imOut = ImagingTransform( | ||
imOut, imIn, IMAGING_TRANSFORM_AFFINE, 0, 0, xsize, ysize, a, filter, 1 | ||
|
@@ -2087,13 +2126,19 @@ | |
case 0: /* flip left right */ | ||
case 1: /* flip top bottom */ | ||
case 3: /* rotate 180 */ | ||
imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize); | ||
imOut = ImagingNewDirty( | ||
imIn->mode, | ||
(ImagingNewParams){imIn->xsize, imIn->ysize, imIn->depth, imIn->bands} | ||
); | ||
break; | ||
case 2: /* rotate 90 */ | ||
case 4: /* rotate 270 */ | ||
case 5: /* transpose */ | ||
case 6: /* transverse */ | ||
imOut = ImagingNewDirty(imIn->mode, imIn->ysize, imIn->xsize); | ||
imOut = ImagingNewDirty( | ||
imIn->mode, | ||
(ImagingNewParams){imIn->ysize, imIn->xsize, imIn->depth, imIn->bands} | ||
); | ||
break; | ||
default: | ||
PyErr_SetString(PyExc_ValueError, "No such transpose operation"); | ||
|
@@ -2141,7 +2186,7 @@ | |
} | ||
|
||
imIn = self->image; | ||
imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize); | ||
imOut = ImagingNewDirty(imIn->mode, (ImagingNewParams){imIn->xsize, imIn->ysize}); | ||
if (!imOut) { | ||
return NULL; | ||
} | ||
|
@@ -2165,7 +2210,7 @@ | |
} | ||
|
||
imIn = self->image; | ||
imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize); | ||
imOut = ImagingNewDirty(imIn->mode, (ImagingNewParams){imIn->xsize, imIn->ysize}); | ||
if (!imOut) { | ||
return NULL; | ||
} | ||
|
@@ -2766,7 +2811,9 @@ | |
return NULL; | ||
} | ||
|
||
im = ImagingNew(self->bitmap->mode, textwidth(self, text), self->ysize); | ||
im = ImagingNew( | ||
self->bitmap->mode, (ImagingNewParams){textwidth(self, text), self->ysize} | ||
); | ||
if (!im) { | ||
free(text); | ||
return ImagingError_MemoryError(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This formatting is actively bad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's forced by
make lint
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well then,
make lint
is wrong. ;>This may just be my long term fight against minless conformity, but sometimes black's formatting obscures the code. And this is one of the cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest just
# noqa
around whatever you don't want formatted for now … also the kids are usingruff
these days 😄There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use
# fmt: off
+# fmt: on
or# fmt: skip
here:https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#ignoring-sections