@@ -168,10 +168,22 @@ static mp_float_t float_subscr(mp_obj_t o, int i) {
168
168
}
169
169
170
170
//| class ChannelScale:
171
- //| """A weight object to use with mix()"""
171
+ //| """A weight object to use with mix() that scales each channel independently
172
+ //|
173
+ //| This is useful for global contrast and brightness adjustment on a
174
+ //| per-component basis. For instance, to cut red contrast in half (while keeping the minimum value
175
+ //| as black or 0.0),
176
+ //|
177
+ //| .. code-block:: python
178
+ //|
179
+ //| reduce_red_contrast = bitmapfilter.ChannelScale(0.5, 1, 1)
180
+ //| """
172
181
//|
173
182
//| def __init__(self, r: float, g: float, b: float) -> None:
174
- //| """The parameters each give a scale to apply to the respective image component"""
183
+ //| """Construct a ChannelScale object
184
+ //|
185
+ //| The ``r`` parameter gives the scale factor for the red channel of
186
+ //| pixels, and so forth."""
175
187
//|
176
188
static const mp_obj_namedtuple_type_t bitmapfilter_channel_scale_type = {
177
189
NAMEDTUPLE_TYPE_BASE_AND_SLOTS (MP_QSTR_ChannelScale ),
@@ -183,16 +195,28 @@ static const mp_obj_namedtuple_type_t bitmapfilter_channel_scale_type = {
183
195
},
184
196
};
185
197
//| class ChannelScaleOffset:
186
- //| """A weight object to use with mix()"""
198
+ //| """A weight object to use with mix() that scales and offsets each channel independently
199
+ //|
200
+ //| The ``r``, ``g``, and ``b`` parameters give a scale factor for each color
201
+ //| component, while the ``r_add`, ``g_add`` and ``b_add`` give offset values
202
+ //| added to each component.
203
+ //|
204
+ //| This is useful for global contrast and brightness adjustment on a
205
+ //| per-component basis. For instance, to cut red contrast in half while adjusting the
206
+ //| brightness so that the middle value is still 0.5:
207
+ //|
208
+ //| .. code-block:: python
209
+ //|
210
+ //| reduce_red_contrast = bitmapfilter.ChannelScaleOffset(
211
+ //| 0.5, 0.25,
212
+ //| 1, 0,
213
+ //| 1, 0)
214
+ //| """
187
215
//|
188
216
//| def __init__(
189
217
//| self, r: float, r_add: float, g: float, g_add: float, b: float, b_add: float
190
218
//| ) -> None:
191
- //| """Scale and offset each channel independently.
192
- //|
193
- //| The ``r``, ``g``, and ``b`` parameters each give a scale to apply
194
- //| to the respective image component, while the ``r_add``,
195
- //| ``g_add``, and ``b_add`` parameters give an offset value to add."""
219
+ //| """Construct a ChannelScaleOffset object"""
196
220
//|
197
221
static const mp_obj_namedtuple_type_t bitmapfilter_channel_scale_offset_type = {
198
222
NAMEDTUPLE_TYPE_BASE_AND_SLOTS (MP_QSTR_ChannelScaleOffset ),
@@ -208,7 +232,32 @@ static const mp_obj_namedtuple_type_t bitmapfilter_channel_scale_offset_type = {
208
232
};
209
233
210
234
//| class ChannelMixer:
211
- //| """A weight object to use with mix()"""
235
+ //| """A weight object to use with mix() that mixes different channels together
236
+ //|
237
+ //| The parameters with names like ``rb`` give the fraction of
238
+ //| each channel to mix into every other channel. For instance,
239
+ //| ``rb`` gives the fraction of blue to mix into red, and ``gg``
240
+ //| gives the fraction of green to mix into green.
241
+ //|
242
+ //| Conversion to sepia is an example where a ChannelMixer is appropriate,
243
+ //| because the sepia conversion is defined as mixing a certain fraction of R,
244
+ //| G, and B input values into each output value:
245
+ //|
246
+ //| .. code-block:: python
247
+ //|
248
+ //| sepia_weights = bitmapfilter.ChannelMixer(
249
+ //| .393, .769, .189,
250
+ //| .349, .686, .168,
251
+ //| .272, .534, .131)
252
+ //|
253
+ //| def sepia(bitmap):
254
+ //| \"""Convert the bitmap to sepia\"""
255
+ //| bitmapfilter.mix(bitmap, sepia_weights)
256
+ //| mix_into_red = ChannelMixer(
257
+ //| 0.5, 0.25, 0.25,
258
+ //| 0, 1, 0,
259
+ //| 0, 1, 0)
260
+ //| """
212
261
//|
213
262
//| def __init__(
214
263
//| self,
@@ -222,12 +271,7 @@ static const mp_obj_namedtuple_type_t bitmapfilter_channel_scale_offset_type = {
222
271
//| bg: float,
223
272
//| bb: float,
224
273
//| ) -> None:
225
- //| """Perform a mixing operation where each channel can receive a fraction of every other channel.
226
- //|
227
- //| The parameters with names like ``rb`` give the fraction of
228
- //| each channel to mix into every other channel. For instance,
229
- //| ``rb`` gives the fraction of blue to mix into red, and ``gg``
230
- //| gives the fraction of green to mix into green."""
274
+ //| """Construct a ChannelMixer object"""
231
275
//|
232
276
static const mp_obj_namedtuple_type_t bitmapfilter_channel_mixer_type = {
233
277
NAMEDTUPLE_TYPE_BASE_AND_SLOTS (MP_QSTR_ChannelMixer ),
@@ -246,7 +290,23 @@ static const mp_obj_namedtuple_type_t bitmapfilter_channel_mixer_type = {
246
290
};
247
291
248
292
//| class ChannelMixerOffset:
249
- //| """A weight object to use with mix()"""
293
+ //| """A weight object to use with mix() that mixes different channels together, plus an offset value
294
+ //|
295
+ //| The parameters with names like ``rb`` give the fraction of
296
+ //| each channel to mix into every other channel. For instance,
297
+ //| ``rb`` gives the fraction of blue to mix into red, and ``gg``
298
+ //| gives the fraction of green to mix into green. The ``r_add``, ``g_add``
299
+ //| and ``b_add`` parameters give offsets applied to each component.
300
+ //|
301
+ //| For instance, to perform sepia conversion but also increase the overall brightness by 10%:
302
+ //|
303
+ //| .. code-block:: python
304
+ //|
305
+ //| sepia_weights_brighten = bitmapfilter.ChannelMixerOffset(
306
+ //| .393, .769, .189, .1
307
+ //| .349, .686, .168, .1
308
+ //| .272, .534, .131, .1)
309
+ //| """
250
310
//|
251
311
//| def __init__(
252
312
//| self,
@@ -263,13 +323,7 @@ static const mp_obj_namedtuple_type_t bitmapfilter_channel_mixer_type = {
263
323
//| bb: float,
264
324
//| b_add: float,
265
325
//| ) -> None:
266
- //| """Perform a mixing operation where each channel can receive a fraction of every other channel, plus an offset value.
267
- //|
268
- //| The parameters with names like ``rb`` give the fraction of
269
- //| each channel to mix into every other channel. For instance,
270
- //| ``rb`` gives the fraction of blue to mix into red, and ``gg``
271
- //| gives the fraction of green to mix into green. The ``_add``
272
- //| parameters give an offset value to add to the channel."""
326
+ //| """Construct a ChannelMixerOffset object"""
273
327
//|
274
328
static const mp_obj_namedtuple_type_t bitmapfilter_channel_mixer_offset_type = {
275
329
NAMEDTUPLE_TYPE_BASE_AND_SLOTS (MP_QSTR_ChannelMixerOffset ),
@@ -304,42 +358,17 @@ static const mp_obj_namedtuple_type_t bitmapfilter_channel_mixer_offset_type = {
304
358
//| The ``bitmap``, which must be in RGB565_SWAPPED format, is modified
305
359
//| according to the ``weights``.
306
360
//|
307
- //| If ``weights`` is a `ChannelScale`
308
- //| object, then each channel is scaled independently: The
309
- //| numbers are the red, green, and blue channel scales.
310
- //|
311
- //| If ``weights`` is a `ChannelScaleOffset`
312
- //| object, then each channel is scaled and offset independently:
313
- //| The first two numbers are applied to the red channel: scale and
314
- //| offset. The second two number are applied to the green channel,
315
- //| and the last two numbers to the blue channel.
316
- //|
317
- //| If ``weights`` is a `ChannelMixer`
318
- //| object, then channels are mixed. The first three
319
- //| numbers are the fraction of red, green and blue input channels
320
- //| mixed into the red output channel. The next 3 numbers are for
321
- //| green, and the final 3 are for blue.
361
+ //| The ``weights`` must be one of the above types: `ChannelScale`,
362
+ //| `ChannelScaleOffset`, `ChannelMixer`, or `ChannelMixerOffset`. For the
363
+ //| effect of each different kind of weights object, see the type
364
+ //| documentation.
322
365
//|
323
- //| If ``weights`` `ChannelMixerOffset`
324
- //| object, then channels are mixed with an offset.
325
- //| Every fourth value is the offset value.
366
+ //| After computation, any out of range values are clamped to the greatest or
367
+ //| smallest valid value.
326
368
//|
327
369
//| ``mask`` is another image to use as a pixel level mask for the operation.
328
370
//| The mask should be an image the same size as the image being operated on.
329
371
//| Only pixels set to a non-zero value in the mask are modified.
330
- //|
331
- //| For example, to perform a sepia conversion on an input image,
332
- //|
333
- //| .. code-block:: python
334
- //|
335
- //| sepia_weights = bitmapfilter.ChannelMixer(
336
- //| .393, .769, .189,
337
- //| .349, .686, .168,
338
- //| .272, .534, .131)
339
- //|
340
- //| def sepia(bitmap):
341
- //| \"""Convert the bitmap to sepia\"""
342
- //| bitmapfilter.mix(bitmap, sepia_weights)
343
372
//| """
344
373
//|
345
374
STATIC mp_obj_t bitmapfilter_mix (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
@@ -398,7 +427,7 @@ STATIC mp_obj_t bitmapfilter_mix(size_t n_args, const mp_obj_t *pos_args, mp_map
398
427
MP_DEFINE_CONST_FUN_OBJ_KW (bitmapfilter_mix_obj , 0 , bitmapfilter_mix );
399
428
400
429
//| def solarize(bitmap, threshold: float = 0.5, mask: displayio.Bitmap | None = None):
401
- //| """Creat a "solarization" effect on an image
430
+ //| """Create a "solarization" effect on an image
402
431
//|
403
432
//| This filter inverts pixels with brightness values above ``threshold``, while leaving
404
433
//| lower brightness pixels alone.
0 commit comments