Merge pull request #927 from kwagyeman/kwabena/larry_scaling_code

Add new image scaling pipeline
This commit is contained in:
Ibrahim Abd Elkader 2020-10-19 03:37:20 +02:00 committed by GitHub
commit 32f8ef3172
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 3977 additions and 588 deletions

View File

@ -0,0 +1,71 @@
# Image Drawing Alpha Blending Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
hint = image.BICUBIC # image.BILINEAR image.BICUBIC
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
big_img = image.Image(128, 128, sensor.RGB565)
big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32, hint=hint)
#big_img.to_grayscale()
#big_img.to_bitmap()
alpha_div = 1
alpha_value = 0
alpha_step = 2
x_bounce = sensor.width()//2
x_bounce_toggle = 1
y_bounce = sensor.height()//2
y_bounce_toggle = 1
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
#img.to_grayscale()
#img.to_bitmap()
img.draw_image(big_img, x_bounce, y_bounce,
rgb_channel=-1, alpha=alpha_value//alpha_div,
hint=hint|image.CENTER)
x_bounce += x_bounce_toggle
if abs(x_bounce-(img.width()//2)) >= (img.width()//2): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce-(img.height()//2)) >= (img.height()//2): y_bounce_toggle = -y_bounce_toggle
alpha_value += alpha_step
if not alpha_value or alpha_value//alpha_div == 256: alpha_step = -alpha_step
print(clock.fps())

View File

@ -0,0 +1,81 @@
# Image Drawing Color Table with Alpha Blending Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
hint = image.BICUBIC # image.BILINEAR image.BICUBIC
# RGB channel extraction is done after scaling normally, this
# may produce false colors. Set this flag to do it before.
#
hint |= 0 # image.EXTRACT_RGB_CHANNEL_FIRST
# Color table application is done after scaling normally, this
# may produce false colors. Set this flag to do it before.
#
hint |= 0 # image.APPLY_COLOR_PALETTE_FIRST
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
big_img = image.Image(128, 128, sensor.RGB565)
big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32, hint=hint)
#big_img.to_grayscale()
#big_img.to_bitmap()
alpha_div = 1
alpha_value = 0
alpha_step = 2
x_bounce = sensor.width()//2
x_bounce_toggle = 1
y_bounce = sensor.height()//2
y_bounce_toggle = 1
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
#img.to_grayscale()
#img.to_bitmap()
img.draw_image(big_img, x_bounce, y_bounce,
rgb_channel=-1, alpha=alpha_value//alpha_div,
color_palette=sensor.PALETTE_IRONBOW, hint=hint|image.CENTER)
x_bounce += x_bounce_toggle
if abs(x_bounce-(img.width()//2)) >= (img.width()//2): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce-(img.height()//2)) >= (img.height()//2): y_bounce_toggle = -y_bounce_toggle
alpha_value += alpha_step
if not alpha_value or alpha_value//alpha_div == 256: alpha_step = -alpha_step
print(clock.fps())

View File

@ -0,0 +1,75 @@
# Image Drawing Alpha Table Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
hint = image.BICUBIC # image.BILINEAR image.BICUBIC
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
big_img = image.Image(128, 128, sensor.RGB565)
big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32, hint=hint)
#big_img.to_grayscale()
#big_img.to_bitmap()
alpha_lut = image.Image(256, 1, sensor.GRAYSCALE)
for i in range(256):
alpha_lut.set_pixel(i, 0, 255 if i > 127 else 0)
alpha_div = 1
alpha_value = 0
alpha_step = 2
x_bounce = sensor.width()//2
x_bounce_toggle = 1
y_bounce = sensor.height()//2
y_bounce_toggle = 1
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
#img.to_grayscale()
#img.to_bitmap()
img.draw_image(big_img, x_bounce, y_bounce,
rgb_channel=-1, alpha=alpha_value//alpha_div,
alpha_palette=alpha_lut, hint=hint|image.CENTER)
x_bounce += x_bounce_toggle
if abs(x_bounce-(img.width()//2)) >= (img.width()//2): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce-(img.height()//2)) >= (img.height()//2): y_bounce_toggle = -y_bounce_toggle
alpha_value += alpha_step
if not alpha_value or alpha_value//alpha_div == 256: alpha_step = -alpha_step
print(clock.fps())

View File

@ -0,0 +1,85 @@
# Image Drawing Color Table with Alpha Table Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
hint = image.BICUBIC # image.BILINEAR image.BICUBIC
# RGB channel extraction is done after scaling normally, this
# may produce false colors. Set this flag to do it before.
#
hint |= 0 # image.EXTRACT_RGB_CHANNEL_FIRST
# Color table application is done after scaling normally, this
# may produce false colors. Set this flag to do it before.
#
hint |= 0 # image.APPLY_COLOR_PALETTE_FIRST
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
big_img = image.Image(128, 128, sensor.RGB565)
big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32, hint=hint)
#big_img.to_grayscale()
#big_img.to_bitmap()
alpha_lut = image.Image(256, 1, sensor.GRAYSCALE)
for i in range(256):
alpha_lut.set_pixel(i, 0, 255 if i > 127 else 0)
alpha_div = 1
alpha_value = 0
alpha_step = 2
x_bounce = sensor.width()//2
x_bounce_toggle = 1
y_bounce = sensor.height()//2
y_bounce_toggle = 1
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
#img.to_grayscale()
#img.to_bitmap()
img.draw_image(big_img, x_bounce, y_bounce,
rgb_channel=-1, alpha=alpha_value//alpha_div,
color_palette=sensor.PALETTE_IRONBOW, alpha_palette=alpha_lut, hint=hint|image.CENTER)
x_bounce += x_bounce_toggle
if abs(x_bounce-(img.width()//2)) >= (img.width()//2): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce-(img.height()//2)) >= (img.height()//2): y_bounce_toggle = -y_bounce_toggle
alpha_value += alpha_step
if not alpha_value or alpha_value//alpha_div == 256: alpha_step = -alpha_step
print(clock.fps())

View File

@ -0,0 +1,69 @@
# Image Scaling Down Drawing Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
# DISABLE THE FRAME BUFFER TO SEE THE REAL FPS
import sensor, image, time
up_hint = 0 # image.BILINEAR image.BICUBIC
down_hint = image.AREA # image.BILINEAR image.BICUBIC image.AREA
bounce_div = 128
medium_img = image.Image(32, 32, sensor.RGB565, copy_to_fb=True)
#medium_img.to_grayscale()
#medium_img.to_bitmap()
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
big_img = image.Image(128, 128, sensor.RGB565)
big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32, hint=up_hint)
#big_img.to_grayscale()
#big_img.to_bitmap()
x_bounce = 0
x_bounce_toggle = 0
y_bounce = 0
y_bounce_toggle = 0
clock = time.clock()
while(True):
clock.tick()
medium_img.clear()
medium_img.draw_image(big_img,
x_bounce // bounce_div, y_bounce // bounce_div,
x_scale=0.25, y_scale=0.25,
hint=down_hint)
sensor.flush()
x_bounce += x_bounce_toggle
if abs(x_bounce // bounce_div) >= (medium_img.width()*1.1): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce // bounce_div) >= (medium_img.height()*1.1): y_bounce_toggle = -y_bounce_toggle
print(clock.fps())

View File

@ -0,0 +1,63 @@
# Image Scaling Up Drawing Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
# DISABLE THE FRAME BUFFER TO SEE THE REAL FPS
import sensor, image, time
hint = 0 # image.BILINEAR image.BICUBIC
bounce_div = 32
big_img = image.Image(128, 128, sensor.RGB565, copy_to_fb=True)
#big_img.to_grayscale()
#big_img.to_bitmap()
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
x_bounce = 0
x_bounce_toggle = 0
y_bounce = 0
y_bounce_toggle = 0
clock = time.clock()
while(True):
clock.tick()
big_img.clear()
big_img.draw_image(small_img,
x_bounce // bounce_div, y_bounce // bounce_div,
x_scale=32, y_scale=32,
hint=hint)
sensor.flush()
x_bounce += x_bounce_toggle
if abs(x_bounce // bounce_div) >= (big_img.width()*1.1): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce // bounce_div) >= (big_img.height()*1.1): y_bounce_toggle = -y_bounce_toggle
print(clock.fps())

View File

@ -46,9 +46,9 @@
#ifndef __STATIC_INLINE #ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline #define __STATIC_INLINE static inline
#endif #endif
#ifndef __STATIC_FORCEINLINE #ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
#endif #endif
#ifndef __NO_RETURN #ifndef __NO_RETURN
#define __NO_RETURN __attribute__((__noreturn__)) #define __NO_RETURN __attribute__((__noreturn__))
#endif #endif
@ -585,7 +585,7 @@ __STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask)
Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
Stack Pointer Limit register hence zero is returned always in non-secure Stack Pointer Limit register hence zero is returned always in non-secure
mode. mode.
\details Returns the current value of the Process Stack Pointer Limit (PSPLIM). \details Returns the current value of the Process Stack Pointer Limit (PSPLIM).
\return PSPLIM Register value \return PSPLIM Register value
*/ */
@ -630,7 +630,7 @@ __STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void)
Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
Stack Pointer Limit register hence the write is silently ignored in non-secure Stack Pointer Limit register hence the write is silently ignored in non-secure
mode. mode.
\details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM).
\param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
*/ */
@ -767,7 +767,7 @@ __STATIC_FORCEINLINE uint32_t __get_FPSCR(void)
{ {
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) ) (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
#if __has_builtin(__builtin_arm_get_fpscr) #if __has_builtin(__builtin_arm_get_fpscr)
// Re-enable using built-in when GCC has been fixed // Re-enable using built-in when GCC has been fixed
// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) // || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
/* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
@ -1159,6 +1159,23 @@ __extension__ \
}) })
/**
\brief Signed Saturate
\details Saturates a signed value.
\param [in] ARG1 Value to be saturated
\param [in] ARG2 Bit position to saturate to (1..32)
\param [in] ARG3 Right shift (0..31)
\return Saturated value
*/
#define __SSAT_ASR(ARG1,ARG2,ARG3) \
__extension__ \
({ \
int32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat %0, %1, %2, asr %3" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1), "I" (ARG3) ); \
__RES; \
})
/** /**
\brief Unsigned Saturate \brief Unsigned Saturate
\details Saturates an unsigned value. \details Saturates an unsigned value.
@ -1175,6 +1192,23 @@ __extension__ \
}) })
/**
\brief Unsigned Saturate
\details Saturates an unsigned value.
\param [in] ARG1 Value to be saturated
\param [in] ARG2 Bit position to saturate to (0..31)
\param [in] ARG3 Right shift (0..31)
\return Saturated value
*/
#define __USAT_ASR(ARG1,ARG2,ARG3) \
__extension__ \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat %0, %1, %2, asr %3" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1), "I" (ARG3) ); \
__RES; \
})
/** /**
\brief Rotate Right with Extend (32 bit) \brief Rotate Right with Extend (32 bit)
\details Moves each bit of a bitstring right by one bit. \details Moves each bit of a bitstring right by one bit.
@ -1863,6 +1897,14 @@ __STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1)
return(result); return(result);
} }
__STATIC_FORCEINLINE uint32_t __UXTB16_RORn(uint32_t op1, uint32_t rotate)
{
uint32_t result;
__ASM volatile ("uxtb16 %0, %1, ROR %2" : "=r" (result) : "r" (op1), "i" (rotate) );
return result;
}
__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) __STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
{ {
uint32_t result; uint32_t result;
@ -1871,6 +1913,14 @@ __STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
return(result); return(result);
} }
__STATIC_FORCEINLINE uint32_t __UXTAB_RORn(uint32_t op1, uint32_t op2, uint32_t rotate)
{
uint32_t result;
__ASM volatile ("uxtab %0, %1, %2, ROR %3" : "=r" (result) : "r" (op1), "r" (op2), "i" (rotate) );
return result;
}
__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1)
{ {
uint32_t result; uint32_t result;
@ -1879,6 +1929,14 @@ __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1)
return(result); return(result);
} }
__STATIC_FORCEINLINE uint32_t __SXTB16_RORn(uint32_t op1, uint32_t rotate)
{
uint32_t result;
__ASM volatile ("sxtb16 %0, %1, ROR %2" : "=r" (result) : "r" (op1), "i" (rotate) );
return result;
}
__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) __STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
{ {
uint32_t result; uint32_t result;
@ -1887,6 +1945,14 @@ __STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
return(result); return(result);
} }
__STATIC_FORCEINLINE uint32_t __SXTAB_RORn(uint32_t op1, uint32_t op2, uint32_t rotate)
{
uint32_t result;
__ASM volatile ("sxtab %0, %1, %2, ROR %3" : "=r" (result) : "r" (op1), "r" (op2), "i" (rotate) );
return result;
}
__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) __STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
{ {
uint32_t result; uint32_t result;
@ -2043,7 +2109,7 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2)
return(result); return(result);
} }
#if 0 #if 1
#define __PKHBT(ARG1,ARG2,ARG3) \ #define __PKHBT(ARG1,ARG2,ARG3) \
({ \ ({ \
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
@ -2061,13 +2127,13 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2)
__RES; \ __RES; \
}) })
#endif #endif
/*
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ #define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ #define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
*/
__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) __STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
{ {
int32_t result; int32_t result;

View File

@ -142,7 +142,7 @@
#endif #endif
// Enable FAST (20+ KBs). // Enable FAST (20+ KBs).
#define IMLIB_ENABLE_FAST // #define IMLIB_ENABLE_FAST
// Enable find_template() // Enable find_template()
#define IMLIB_FIND_TEMPLATE #define IMLIB_FIND_TEMPLATE

View File

@ -142,7 +142,7 @@
#endif #endif
// Enable FAST (20+ KBs). // Enable FAST (20+ KBs).
#define IMLIB_ENABLE_FAST // #define IMLIB_ENABLE_FAST
// Enable find_template() // Enable find_template()
#define IMLIB_FIND_TEMPLATE #define IMLIB_FIND_TEMPLATE

View File

@ -93,7 +93,7 @@
#endif #endif
// Enable get_similarity() // Enable get_similarity()
#define IMLIB_ENABLE_GET_SIMILARITY // #define IMLIB_ENABLE_GET_SIMILARITY
// Enable find_lines() // Enable find_lines()
#define IMLIB_ENABLE_FIND_LINES #define IMLIB_ENABLE_FIND_LINES

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,9 @@
#include "collections.h" #include "collections.h"
#include "imlib_config.h" #include "imlib_config.h"
extern void *unaligned_2_to_1_memcpy(void *dest, void *src, size_t n);
extern void *unaligned_memcpy(void *dest, void *src, size_t n);
#define IM_LOG2_2(x) (((x) & 0x2ULL) ? ( 2 ) : 1) // NO ({ ... }) ! #define IM_LOG2_2(x) (((x) & 0x2ULL) ? ( 2 ) : 1) // NO ({ ... }) !
#define IM_LOG2_4(x) (((x) & 0xCULL) ? ( 2 + IM_LOG2_2((x) >> 2)) : IM_LOG2_2(x)) // NO ({ ... }) ! #define IM_LOG2_4(x) (((x) & 0xCULL) ? ( 2 + IM_LOG2_2((x) >> 2)) : IM_LOG2_2(x)) // NO ({ ... }) !
#define IM_LOG2_8(x) (((x) & 0xF0ULL) ? ( 4 + IM_LOG2_4((x) >> 4)) : IM_LOG2_4(x)) // NO ({ ... }) ! #define IM_LOG2_8(x) (((x) & 0xF0ULL) ? ( 4 + IM_LOG2_4((x) >> 4)) : IM_LOG2_4(x)) // NO ({ ... }) !
@ -287,6 +290,50 @@ extern const int8_t yuv_table[196608];
#define COLOR_RGB565_TO_V(pixel) imlib_rgb565_to_v(pixel) #define COLOR_RGB565_TO_V(pixel) imlib_rgb565_to_v(pixel)
#endif #endif
#define RGB565_TO_R8_FAST(pixel) \
({ \
__typeof__ (pixel) __pixel = (pixel); \
__pixel = __pixel & 0xF8; /* RGB565 byte reversal fix */ \
__pixel | (__pixel >> 5); \
})
#define RGB565_TO_G8_FAST(pixel) \
({ \
__typeof__ (pixel) __pixel = (pixel); \
__pixel = (__REV16(__pixel) >> 3) & 0xFC; /* RGB565 byte reversal fix */ \
__pixel | (__pixel >> 6); \
})
#define RGB565_TO_B8_FAST(pixel) \
({ \
__typeof__ (pixel) __pixel = (pixel); \
__pixel = (__pixel >> 5) & 0xF8; /* RGB565 byte reversal fix */ \
__pixel | (__pixel >> 5); \
})
#define RGB565_TO_Y_FAST(rgb565) \
({ \
__typeof__ (rgb565) __rgb565 = (rgb565); \
int r = RGB565_TO_R8_FAST(__rgb565); \
int g = RGB565_TO_G8_FAST(__rgb565); \
int b = RGB565_TO_B8_FAST(__rgb565); \
((r * 38) + (g * 75) + (b * 15)) >> 7; /* 0.299R + 0.587G + 0.114B */ \
})
#define Y_TO_RGB565_FAST(pixel) \
({ \
__typeof__ (pixel) __pixel = (pixel); \
int __rb_pixel = (__pixel >> 3) & 0x3F; \
int __rgb_pixel = (__rb_pixel * 0x0801) + ((__pixel << 3) & 0x7E0); \
__REV16(__rgb_pixel); /* RGB565 byte reversal fix */ \
})
#define Y_TO_RGB888_FAST(pixel) \
({ \
__typeof__ (pixel) __pixel = (pixel); \
pixel * 0x010101; \
})
#define COLOR_LAB_TO_RGB565(l, a, b) imlib_lab_to_rgb(l, a, b) #define COLOR_LAB_TO_RGB565(l, a, b) imlib_lab_to_rgb(l, a, b)
#define COLOR_YUV_TO_RGB565(y, u, v) imlib_yuv_to_rgb((y) + 128, u, v) #define COLOR_YUV_TO_RGB565(y, u, v) imlib_yuv_to_rgb((y) + 128, u, v)
@ -560,9 +607,6 @@ float IMAGE_Y_RATIO = ((float) _source_rect->s.h) / ((float) _target_rect->s.h);
_row_ptr + ((_image->w + UINT32_T_MASK) >> UINT32_T_SHIFT); \ _row_ptr + ((_image->w + UINT32_T_MASK) >> UINT32_T_SHIFT); \
}) })
#define RGB565_TO_Y_FAST(pixel) \
(((pixel & 0x1f00) >> 5) + (pixel & 0xf8) + ((pixel & 0x7) << 6) + ((pixel & 0xe000) >> 10)) / 4;
#define IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x) \ #define IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x) \
({ \ ({ \
__typeof__ (row_ptr) _row_ptr = (row_ptr); \ __typeof__ (row_ptr) _row_ptr = (row_ptr); \
@ -1148,10 +1192,26 @@ typedef struct find_barcodes_list_lnk_data {
} find_barcodes_list_lnk_data_t; } find_barcodes_list_lnk_data_t;
typedef enum image_hint { typedef enum image_hint {
IMAGE_HINT_BILINEAR = 1, IMAGE_HINT_AREA = 1,
IMAGE_HINT_CENTER = 128 IMAGE_HINT_BILINEAR = 2,
IMAGE_HINT_BICUBIC = 4,
IMAGE_HINT_CENTER = 128,
IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST = 256,
IMAGE_HINT_APPLY_COLOR_PALETTE_FIRST = 512
} image_hint_t; } image_hint_t;
typedef struct imlib_draw_row_data {
image_t *dst_img; // user
int src_img_bpp; // user
int rgb_channel; // user
int alpha; // user
const uint16_t *color_palette; // user
const uint8_t *alpha_palette; // user
int toggle; // private
void *row_buffer[2]; // private
long smuad_alpha; // private
uint32_t *smuad_alpha_palette; // private
} imlib_draw_row_data_t;
/* Color space functions */ /* Color space functions */
int8_t imlib_rgb565_to_l(uint16_t pixel); int8_t imlib_rgb565_to_l(uint16_t pixel);
@ -1284,6 +1344,11 @@ void imlib_find_hog(image_t *src, rectangle_t *roi, int cell_size);
// Helper Functions // Helper Functions
void imlib_zero(image_t *img, image_t *mask, bool invert); void imlib_zero(image_t *img, image_t *mask, bool invert);
void imlib_draw_row_setup(imlib_draw_row_data_t *data);
void imlib_draw_row_teardown(imlib_draw_row_data_t *data);
void *imlib_draw_row_get_row_buffer(imlib_draw_row_data_t *data);
void imlib_draw_row_put_row_buffer(imlib_draw_row_data_t *data, void *row_buffer);
void imlib_draw_row(int x_start, int x_end, int y_row, imlib_draw_row_data_t *data);
void imlib_flood_fill_int(image_t *out, image_t *img, int x, int y, void imlib_flood_fill_int(image_t *out, image_t *img, int x, int y,
int seed_threshold, int floating_threshold, int seed_threshold, int floating_threshold,
flood_fill_call_back_t cb, void *data); flood_fill_call_back_t cb, void *data);
@ -1297,8 +1362,8 @@ void imlib_draw_circle(image_t *img, int cx, int cy, int r, int c, int thickness
void imlib_draw_ellipse(image_t *img, int cx, int cy, int rx, int ry, int rotation, int c, int thickness, bool fill); void imlib_draw_ellipse(image_t *img, int cx, int cy, int rx, int ry, int rotation, int c, int thickness, bool fill);
void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, float scale, int x_spacing, int y_spacing, bool mono_space, void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, float scale, int x_spacing, int y_spacing, bool mono_space,
int char_rotation, bool char_hmirror, bool char_vflip, int string_rotation, bool string_hmirror, bool string_hflip); int char_rotation, bool char_hmirror, bool char_vflip, int string_rotation, bool string_hmirror, bool string_hflip);
void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float x_scale, float y_scale, int alpha, image_t *mask, void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int dst_y_start, float x_scale, float y_scale, rectangle_t *roi,
const uint16_t *color_palette, const uint8_t *alpha_palette, image_hint_t hint); int rgb_channel, int alpha, const uint16_t *color_palette, const uint8_t *alpha_palette, image_hint_t hint);
void imlib_flood_fill(image_t *img, int x, int y, void imlib_flood_fill(image_t *img, int x, int y,
float seed_threshold, float floating_threshold, float seed_threshold, float floating_threshold,
int c, bool invert, bool clear_background, image_t *mask); int c, bool invert, bool clear_background, image_t *mask);

View File

@ -137,8 +137,8 @@ int py_helper_keyword_int(uint n_args, const mp_obj_t *args, uint arg_index,
return default_val; return default_val;
} }
int py_helper_keyword_int_maybe(uint n_args, const mp_obj_t *args, uint arg_index, bool py_helper_keyword_int_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int* value) mp_map_t *kw_args, mp_obj_t kw, int* value)
{ {
mp_map_elem_t *kw_arg = mp_map_lookup(kw_args, kw, MP_MAP_LOOKUP); mp_map_elem_t *kw_arg = mp_map_lookup(kw_args, kw, MP_MAP_LOOKUP);
@ -165,6 +165,20 @@ float py_helper_keyword_float(uint n_args, const mp_obj_t *args, uint arg_index,
return default_val; return default_val;
} }
bool py_helper_keyword_float_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, float *value)
{
mp_map_elem_t *kw_arg = mp_map_lookup(kw_args, kw, MP_MAP_LOOKUP);
if (kw_arg) {
return mp_obj_get_float_maybe(kw_arg->value, value);
} else if (n_args > arg_index) {
return mp_obj_get_float_maybe(args[arg_index], value);
}
return false;
}
void py_helper_keyword_int_array(uint n_args, const mp_obj_t *args, uint arg_index, void py_helper_keyword_int_array(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int *x, int size) mp_map_t *kw_args, mp_obj_t kw, int *x, int size)
{ {

View File

@ -31,10 +31,12 @@ void py_helper_keyword_rectangle_roi(image_t *img, uint n_args, const mp_obj_t *
mp_map_t *kw_args, rectangle_t *r); mp_map_t *kw_args, rectangle_t *r);
int py_helper_keyword_int(uint n_args, const mp_obj_t *args, uint arg_index, int py_helper_keyword_int(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int default_val); mp_map_t *kw_args, mp_obj_t kw, int default_val);
int py_helper_keyword_int_maybe(uint n_args, const mp_obj_t *args, uint arg_index, bool py_helper_keyword_int_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int* value); mp_map_t *kw_args, mp_obj_t kw, int* value);
float py_helper_keyword_float(uint n_args, const mp_obj_t *args, uint arg_index, float py_helper_keyword_float(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, float default_val); mp_map_t *kw_args, mp_obj_t kw, float default_val);
bool py_helper_keyword_float_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, float* value);
void py_helper_keyword_int_array(uint n_args, const mp_obj_t *args, uint arg_index, void py_helper_keyword_int_array(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int *x, int size); mp_map_t *kw_args, mp_obj_t kw, int *x, int size);
void py_helper_keyword_float_array(uint n_args, const mp_obj_t *args, uint arg_index, void py_helper_keyword_float_array(uint n_args, const mp_obj_t *args, uint arg_index,

View File

@ -1431,11 +1431,11 @@ static mp_obj_t py_image_copy_int(uint n_args, const mp_obj_t *args, mp_map_t *k
float arg_x_scale = float arg_x_scale =
py_helper_keyword_float(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_scale), 1.0f); py_helper_keyword_float(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_scale), 1.0f);
PY_ASSERT_TRUE_MSG((0.0f <= arg_x_scale), "Error: 0.0 <= x_scale!"); PY_ASSERT_TRUE_MSG((0.0f <= arg_x_scale), "Error: 0.0 <= x_scale!");
float arg_y_scale = float arg_y_scale =
py_helper_keyword_float(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_scale), 1.0f); py_helper_keyword_float(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_scale), 1.0f);
PY_ASSERT_TRUE_MSG((0.0f <= arg_y_scale), "Error: 0.0 <= y_scale!"); PY_ASSERT_TRUE_MSG((0.0f <= arg_y_scale), "Error: 0.0 <= y_scale!");
mp_obj_t copy_to_fb_obj = py_helper_keyword_object(n_args, args, 4, kw_args, MP_OBJ_NEW_QSTR(mode ? MP_QSTR_copy : MP_QSTR_copy_to_fb)); mp_obj_t copy_to_fb_obj = py_helper_keyword_object(n_args, args, 4, kw_args, MP_OBJ_NEW_QSTR(mode ? MP_QSTR_copy : MP_QSTR_copy_to_fb));
bool copy_to_fb = false; bool copy_to_fb = false;
@ -1847,87 +1847,79 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_edges_obj, 2, py_image_draw_edge
STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{ {
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]); image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
image_t *arg_other = py_helper_arg_to_image_mutable(args[1]);
image_t *arg_other =
py_helper_arg_to_image_mutable(args[1]);
const mp_obj_t *arg_vec; const mp_obj_t *arg_vec;
uint offset = py_helper_consume_array(n_args, args, 2, 2, &arg_vec); uint offset = py_helper_consume_array(n_args, args, 2, 2, &arg_vec);
int arg_cx = mp_obj_get_int(arg_vec[0]); int arg_x_off = mp_obj_get_int(arg_vec[0]);
int arg_cy = mp_obj_get_int(arg_vec[1]); int arg_y_off = mp_obj_get_int(arg_vec[1]);
float arg_x_scale = float arg_x_scale = 1.f;
py_helper_keyword_float(n_args, args, offset + 0, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_scale), 1.0f); bool got_x_scale = py_helper_keyword_float_maybe(n_args, args, offset + 0, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_scale), &arg_x_scale);
PY_ASSERT_TRUE_MSG((0.0f <= arg_x_scale), "Error: 0.0 <= x_scale!");
float arg_y_scale = float arg_y_scale = 1.f;
py_helper_keyword_float(n_args, args, offset + 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_scale), 1.0f); bool got_y_scale = py_helper_keyword_float_maybe(n_args, args, offset + 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_scale), &arg_y_scale);
PY_ASSERT_TRUE_MSG((0.0f <= arg_y_scale), "Error: 0.0 <= y_scale!");
int arg_alpha = rectangle_t arg_roi;
py_helper_keyword_int(n_args, args, offset + 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_alpha), 256); py_helper_keyword_rectangle_roi(arg_other, n_args, args, offset + 2, kw_args, &arg_roi);
PY_ASSERT_TRUE_MSG((0 <= arg_alpha) && (arg_alpha <= 256), "Error: 0 <= alpha <= 256!");
image_t *arg_msk = int arg_rgb_channel = py_helper_keyword_int(n_args, args, offset + 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_rgb_channel), -1);
py_helper_keyword_to_image_mutable_mask(n_args, args, offset + 3, kw_args); if ((arg_rgb_channel < -1) || (2 < arg_rgb_channel)) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "-1 <= rgb_channel <= 2!"));
int arg_alpha = py_helper_keyword_int(n_args, args, offset + 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_alpha), 256);
if ((arg_alpha < 0) || (256 < arg_alpha)) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "0 <= alpha <= 256!"));
const uint16_t *color_palette = NULL; const uint16_t *color_palette = NULL;
{ {
int palette; int palette;
if (py_helper_keyword_int_maybe(n_args, args, offset + 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_color_palette), &palette)) { if (py_helper_keyword_int_maybe(n_args, args, offset + 5, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_color_palette), &palette)) {
if (palette == COLOR_PALETTE_RAINBOW) { if (palette == COLOR_PALETTE_RAINBOW) color_palette = rainbow_table;
color_palette = rainbow_table; else if (palette == COLOR_PALETTE_IRONBOW) color_palette = ironbow_table;
} else if (palette == COLOR_PALETTE_IRONBOW) { else nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid pre-defined color palette!"));
color_palette = ironbow_table;
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid pre-defined color palette!"));
}
} else { } else {
image_t *arg_color_palette = py_helper_keyword_to_image_mutable_color_palette(n_args, args, offset + 4, kw_args); image_t *arg_color_palette = py_helper_keyword_to_image_mutable_color_palette(n_args, args, offset + 5, kw_args);
if (arg_color_palette) { if (arg_color_palette) {
if (arg_color_palette->bpp != IMAGE_BPP_RGB565) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palette must be an RGB565 format image!")); if (arg_color_palette->bpp != IMAGE_BPP_RGB565) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palette must be RGB565!"));
if ((arg_color_palette->w * arg_color_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palette image must have 256 pixels!")); if ((arg_color_palette->w * arg_color_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palette must be 256 pixels!"));
color_palette = (uint16_t *) arg_color_palette->data;
color_palette = (uint16_t*)arg_color_palette->data;
} }
} }
if (color_palette) {
if (arg_other->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Can only specify a color palette when passing a grayscale image!"));
}
}
if (color_palette && arg_img->bpp != IMAGE_BPP_RGB565) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palettes must be used with color images!"));
} }
const uint8_t *alpha_palette = NULL; const uint8_t *alpha_palette = NULL;
{ {
image_t *arg_alpha_palette = py_helper_keyword_to_image_mutable_alpha_palette(n_args, args, offset + 5, kw_args); image_t *arg_alpha_palette = py_helper_keyword_to_image_mutable_alpha_palette(n_args, args, offset + 6, kw_args);
if (arg_alpha_palette) { if (arg_alpha_palette) {
if (arg_other->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Can only specify an alpha palette when passing a grayscale image!")); if (arg_alpha_palette->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette must be GRAYSCALE!"));
if (arg_alpha_palette->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette must be an grayscale format image!")); if ((arg_alpha_palette->w * arg_alpha_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette must be 256 pixels!"));
if ((arg_alpha_palette->w * arg_alpha_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette image must have 256 pixels!")); alpha_palette = (uint8_t *) arg_alpha_palette->data;
if (arg_img->bpp != IMAGE_BPP_GRAYSCALE && arg_img->bpp != IMAGE_BPP_RGB565) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palettes must be used with color images!"));
alpha_palette = (uint8_t*)arg_alpha_palette->data;
} }
} }
image_hint_t hint = image_hint_t hint = py_helper_keyword_int(n_args, args, offset + 7, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_hint), 0);
py_helper_keyword_int(n_args, args, offset + 6, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_hint), 0);
if (hint && arg_msk) { int arg_x_size;
// This check is only performed if there is a hint for backwards compatiblity with old draw image where dimesions were not enforced. bool got_x_size = py_helper_keyword_int_maybe(n_args, args, offset + 8, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_size), &arg_x_size);
if (arg_msk->w != arg_other->w || arg_msk->h != arg_other->h) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Mask must have same dimensions as image"));
}
}
imlib_draw_image(arg_img, arg_other, arg_cx, arg_cy, arg_x_scale, arg_y_scale, arg_alpha, arg_msk, color_palette, alpha_palette, hint); int arg_y_size;
bool got_y_size = py_helper_keyword_int_maybe(n_args, args, offset + 9, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_size), &arg_y_size);
if (got_x_scale && got_x_size) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Choose either x_scale or x_size not both!"));
if (got_y_scale && got_y_size) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Choose either y_scale or y_size not both!"));
if (got_x_size) arg_x_scale = arg_x_size / ((float) arg_other->w);
if (got_y_size) arg_y_scale = arg_y_size / ((float) arg_other->h);
if ((!got_x_scale) && (!got_x_size) && got_y_size) arg_x_scale = arg_y_scale;
if ((!got_y_scale) && (!got_y_size) && got_x_size) arg_y_scale = arg_x_scale;
fb_alloc_mark();
imlib_draw_image(arg_img, arg_other, arg_x_off, arg_y_off, arg_x_scale, arg_y_scale, &arg_roi,
arg_rgb_channel, arg_alpha, color_palette, alpha_palette, hint);
fb_alloc_free_till_mark();
return args[0]; return args[0];
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_image_obj, 3, py_image_draw_image); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_image_obj, 3, py_image_draw_image);
@ -7506,6 +7498,12 @@ int py_image_descriptor_from_roi(image_t *img, const char *path, rectangle_t *ro
static const mp_rom_map_elem_t globals_dict_table[] = { static const mp_rom_map_elem_t globals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_image)}, {MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_image)},
{MP_ROM_QSTR(MP_QSTR_AREA), MP_ROM_INT(IMAGE_HINT_AREA)},
{MP_ROM_QSTR(MP_QSTR_BILINEAR), MP_ROM_INT(IMAGE_HINT_BILINEAR)},
{MP_ROM_QSTR(MP_QSTR_BICUBIC), MP_ROM_INT(IMAGE_HINT_BICUBIC)},
{MP_ROM_QSTR(MP_QSTR_CENTER), MP_ROM_INT(IMAGE_HINT_CENTER)},
{MP_ROM_QSTR(MP_QSTR_EXTRACT_RGB_CHANNEL_FIRST), MP_ROM_INT(IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST)},
{MP_ROM_QSTR(MP_QSTR_APPLY_COLOR_PALETTE_FIRST), MP_ROM_INT(IMAGE_HINT_APPLY_COLOR_PALETTE_FIRST)},
#ifdef IMLIB_FIND_TEMPLATE #ifdef IMLIB_FIND_TEMPLATE
{MP_ROM_QSTR(MP_QSTR_SEARCH_EX), MP_ROM_INT(SEARCH_EX)}, {MP_ROM_QSTR(MP_QSTR_SEARCH_EX), MP_ROM_INT(SEARCH_EX)},
{MP_ROM_QSTR(MP_QSTR_SEARCH_DS), MP_ROM_INT(SEARCH_DS)}, {MP_ROM_QSTR(MP_QSTR_SEARCH_DS), MP_ROM_INT(SEARCH_DS)},
@ -7540,8 +7538,6 @@ static const mp_rom_map_elem_t globals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_CODE93), MP_ROM_INT(BARCODE_CODE93)}, {MP_ROM_QSTR(MP_QSTR_CODE93), MP_ROM_INT(BARCODE_CODE93)},
{MP_ROM_QSTR(MP_QSTR_CODE128), MP_ROM_INT(BARCODE_CODE128)}, {MP_ROM_QSTR(MP_QSTR_CODE128), MP_ROM_INT(BARCODE_CODE128)},
#endif #endif
{MP_ROM_QSTR(MP_QSTR_IMAGE_HINT_BILINEAR),MP_ROM_INT(IMAGE_HINT_BILINEAR)},
{MP_ROM_QSTR(MP_QSTR_IMAGE_HINT_CENTER), MP_ROM_INT(IMAGE_HINT_CENTER)},
{MP_ROM_QSTR(MP_QSTR_ImageWriter), MP_ROM_PTR(&py_image_imagewriter_obj)}, {MP_ROM_QSTR(MP_QSTR_ImageWriter), MP_ROM_PTR(&py_image_imagewriter_obj)},
{MP_ROM_QSTR(MP_QSTR_ImageReader), MP_ROM_PTR(&py_image_imagereader_obj)}, {MP_ROM_QSTR(MP_QSTR_ImageReader), MP_ROM_PTR(&py_image_imagereader_obj)},
{MP_ROM_QSTR(MP_QSTR_binary_to_grayscale), MP_ROM_PTR(&py_image_binary_to_grayscale_obj)}, {MP_ROM_QSTR(MP_QSTR_binary_to_grayscale), MP_ROM_PTR(&py_image_binary_to_grayscale_obj)},

View File

@ -552,11 +552,20 @@ Q(draw_edges)
Q(draw_image) Q(draw_image)
// duplicate Q(x_scale) // duplicate Q(x_scale)
// duplicate Q(y_scale) // duplicate Q(y_scale)
// duplicate Q(roi)
// duplicate Q(rgb_channel)
Q(alpha) Q(alpha)
// duplicate Q(mask) // duplicate Q(color_palette)
// duplicate Q(alpha_palette)
Q(hint) Q(hint)
Q(IMAGE_HINT_BILINEAR) Q(AREA)
Q(IMAGE_HINT_CENTER) Q(BILINEAR)
Q(BICUBIC)
Q(CENTER)
Q(EXTRACT_RGB_CHANNEL_FIRST)
Q(APPLY_COLOR_PALETTE_FIRST)
Q(x_size)
Q(y_size)
// Draw Keypoints // Draw Keypoints
Q(draw_keypoints) Q(draw_keypoints)