luckfox-pico-sdk/sysdrv/source/mcu/rt-thread/applications/common/display/image_info.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

1034 lines
33 KiB
C

/**
* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <stdio.h>
#include <math.h>
#include "image_info.h"
#include "jbig2dec.h"
/*
**************************************************************************************************
*
* Image decompress.
*
**************************************************************************************************
*/
#define NULL_CODE -1 // indicates a NULL prefix
#define CLEAR_CODE 256 // code to flush dictionary and restart decoder
#define FIRST_STRING 257 // code of first dictionary string
static size_t read_count, write_count;
/**
* decompress read buffer.
*/
static int rt_decompress_read_buff(image_info_t *img_info)
{
int value = img_info->data[read_count++];
if (read_count == img_info->size)
{
value = EOF;
}
return value;
}
/**
* decompress write buffer.
*/
static void rt_decompress_write_buff(int value, rt_uint8_t *fb, rt_int32_t fbsize, rt_int32_t xVir, rt_int32_t xoffset, rt_int32_t yoffset, int width)
{
if (write_count < fbsize)
{
xoffset = xoffset + write_count % width;
yoffset = yoffset + write_count / width;
*((uint8_t *)((uint32_t)fb + (yoffset)* xVir + xoffset)) = value;
}
if (value == EOF)
{
return;
}
write_count++;
}
/**
* decompress sub function.
*/
static int rt_display_decompress(image_info_t *img_info, rt_uint8_t *fb, rt_int32_t xVir, rt_int32_t xoffset, rt_int32_t yoffset)
{
int read_byte, next = FIRST_STRING, prefix = CLEAR_CODE, bits = 0, total_codes;
unsigned char *terminators, *reverse_buffer;
unsigned long shifter = 0;
short *prefixes;
write_count = 0;
read_count = 0;
if ((read_byte = (rt_decompress_read_buff(img_info))) == EOF || (read_byte & 0xfc)) //sanitize first byte
{
//rt_kprintf("rt_display_decompress 111\n");
return RT_ERROR;
}
// based on the "maxbits" parameter, compute total codes and allocate dictionary storage
total_codes = 512 << (read_byte & 0x3);
reverse_buffer = malloc((total_codes - 256) * sizeof(reverse_buffer[0]));
prefixes = malloc((total_codes - 256) * sizeof(prefixes[0]));
terminators = malloc((total_codes - 256) * sizeof(terminators[0]));
if (!reverse_buffer || !prefixes || !terminators) // check for mallco() failure
{
if (reverse_buffer)
free(reverse_buffer);
if (prefixes)
free(prefixes);
if (terminators)
free(terminators);
//rt_kprintf("rt_display_decompress 222\n");
return RT_ERROR;
}
// This is the main loop where we read input symbols. The values range from 0 to the code value
// of the "next" string in the dictionary (although the actual "next" code cannot be used yet,
// and so we reserve that code for the END_CODE). Note that receiving an EOF from the input
// stream is actually an error because we should have gotten the END_CODE first.
while (1)
{
int code_bits = next < 1024 ? (next < 512 ? 8 : 9) : (next < 2048 ? 10 : 11), code;
int extras = (1 << (code_bits + 1)) - next - 1;
do
{
if ((read_byte = (rt_decompress_read_buff(img_info))) == EOF)
{
free(terminators);
free(prefixes);
free(reverse_buffer);
//rt_kprintf("rt_display_decompress 333\n");
//return RT_ERROR;
return RT_EOK;
}
shifter |= (long)read_byte << bits;
}
while ((bits += 8) < code_bits);
// first we assume the code will fit in the minimum number of required bits
code = (int)shifter & ((1 << code_bits) - 1);
shifter >>= code_bits;
bits -= code_bits;
// but if code >= extras, then we need to read another bit to calculate the real code
// (this is the "adjusted binary" part)
if (code >= extras)
{
if (!bits)
{
if ((read_byte = (rt_decompress_read_buff(img_info))) == EOF)
{
free(terminators);
free(prefixes);
free(reverse_buffer);
//rt_kprintf("rt_display_decompress 444\n");
//return RT_ERROR;
return RT_EOK;
}
shifter = (long)read_byte;
bits = 8;
}
code = (code << 1) - extras + (shifter & 1);
shifter >>= 1;
bits--;
}
if (code == next) // sending the maximum code is reserved for the end of the file
break;
else if (code == CLEAR_CODE) // otherwise check for a CLEAR_CODE to start over early
next = FIRST_STRING;
else if (prefix == CLEAR_CODE) // this only happens at the first symbol which is always sent
{
rt_decompress_write_buff(code, fb, img_info->w * img_info->h, xVir, xoffset, yoffset, img_info->w); // literally and becomes our initial prefix
next++;
}
// Otherwise we have a valid prefix so we step through the string from end to beginning storing the
// bytes in the "reverse_buffer", and then we send them out in the proper order. One corner-case
// we have to handle here is that the string might be the same one that is actually being defined
// now (code == next-1). Also, the first 256 entries of "terminators" and "prefixes" are fixed and
// not allocated, so that messes things up a bit.
else
{
int cti = (code == next - 1) ? prefix : code;
unsigned char *rbp = reverse_buffer, c;
do *rbp++ = cti < 256 ? cti : terminators[cti - 256]; // step backward through string...
while ((cti = (cti < 256) ? NULL_CODE : prefixes[cti - 256]) != NULL_CODE);
c = *--rbp; // the first byte in this string is the terminator for the last string, which is
// the one that we'll create a new dictionary entry for this time
do rt_decompress_write_buff(*rbp, fb, img_info->w * img_info->h, xVir, xoffset, yoffset, img_info->w); // send string in corrected order (except for the terminator
while (rbp-- != reverse_buffer); // which we don't know yet)
if (code == next - 1)
rt_decompress_write_buff(c, fb, img_info->w * img_info->h, xVir, xoffset, yoffset, img_info->w);
prefixes[next - 1 - 256] = prefix; // now update the next dictionary entry with the new string
terminators[next - 1 - 256] = c; // (but we're always one behind, so it's not the string just sent)
if (++next == total_codes) // check for full dictionary, which forces a reset (and, BTW,
next = FIRST_STRING; // means we'll never use the dictionary entry we just wrote)
}
prefix = code; // the code we just received becomes the prefix for the next dictionary string entry
// (which we'll create once we find out the terminator)
}
free(terminators);
free(prefixes);
free(reverse_buffer);
return RT_EOK;
}
/*
**************************************************************************************************
*
* Image rotate.
*
**************************************************************************************************
*/
#define PI 3.1415926535898
/**
* float angle : rotate angle
* int w
* int h :
* unsigned char *src :
* unsigned char *dst :
* int dst_str :
*/
static unsigned char rt_display_SegGradSelect_8bit(int x, int y, int w, int h, int x_res, int y_res, unsigned char *data, unsigned char *src)
{
unsigned char alpha = 0xff;
int pos = 0;
if (x == -1 && y == -1)
{
alpha = (x_res * y_res) >> 8;
pos = (y + 1) * w + (x + 1);
}
else if (x == w && y == -1)
{
alpha = ((255 - x_res) * y_res) >> 8;
pos = (y + 1) * w + (x - 1);
}
else if (x == -1 && y == h)
{
alpha = ((x_res) * (255 - y_res)) >> 8;
pos = (y - 1) * w + (x + 1);
}
else if (x == w && y == h)
{
alpha = ((255 - x_res) * (255 - y_res)) >> 8;
*data = src[(y - 1) * w + (x - 1)];
}
else if (x == -1 && y > -1 && y < h)
{
alpha = x_res;
pos = y * w + (x + 1);
}
else if (y == -1 && x > -1 && x < w)
{
alpha = y_res;
pos = (y + 1) * w + x;
}
else if (x == w && y > -1 && y < h)
{
alpha = 255 - x_res;
pos = y * w + x - 1;
}
else if (y == h && x > -1 && x < w)
{
alpha = 255 - y_res;
pos = (y - 1) * w + x;
}
*data = src[pos];
return alpha;
}
static unsigned char rt_display_SegGradSelect_16bit(int x, int y, int w, int h, int x_res, int y_res, unsigned short *data, unsigned short *src)
{
unsigned char alpha = 0xff;
int pos = 0;
if (x == -1 && y == -1)
{
alpha = (x_res * y_res) >> 8;
pos = (y + 1) * w + (x + 1);
}
else if (x == w && y == -1)
{
alpha = ((255 - x_res) * y_res) >> 8;
pos = (y + 1) * w + (x - 1);
}
else if (x == -1 && y == h)
{
alpha = ((x_res) * (255 - y_res)) >> 8;
pos = (y - 1) * w + (x + 1);
}
else if (x == w && y == h)
{
alpha = ((255 - x_res) * (255 - y_res)) >> 8;
*data = src[(y - 1) * w + (x - 1)];
}
else if (x == -1 && y > -1 && y < h)
{
alpha = x_res;
pos = y * w + (x + 1);
}
else if (y == -1 && x > -1 && x < w)
{
alpha = y_res;
pos = (y + 1) * w + x;
}
else if (x == w && y > -1 && y < h)
{
alpha = 255 - x_res;
pos = y * w + x - 1;
}
else if (y == h && x > -1 && x < w)
{
alpha = 255 - y_res;
pos = (y - 1) * w + x;
}
*data = src[pos];
return alpha;
}
static unsigned char rt_display_SegGradSelect_32bit(int x, int y, int w, int h, int x_res, int y_res, unsigned int *data, unsigned int *src)
{
unsigned char alpha = 0xff;
int pos = 0;
if (x == -1 && y == -1)
{
alpha = (x_res * y_res) >> 8;
pos = (y + 1) * w + (x + 1);
}
else if (x == w && y == -1)
{
alpha = ((255 - x_res) * y_res) >> 8;
pos = (y + 1) * w + (x - 1);
}
else if (x == -1 && y == h)
{
alpha = ((x_res) * (255 - y_res)) >> 8;
pos = (y - 1) * w + (x + 1);
}
else if (x == w && y == h)
{
alpha = ((255 - x_res) * (255 - y_res)) >> 8;
*data = src[(y - 1) * w + (x - 1)];
}
else if (x == -1 && y > -1 && y < h)
{
alpha = x_res;
pos = y * w + (x + 1);
}
else if (y == -1 && x > -1 && x < w)
{
alpha = y_res;
pos = (y + 1) * w + x;
}
else if (x == w && y > -1 && y < h)
{
alpha = 255 - x_res;
pos = y * w + x - 1;
}
else if (y == h && x > -1 && x < w)
{
alpha = 255 - y_res;
pos = (y - 1) * w + x;
}
*data = src[pos];
return alpha;
}
static unsigned char rt_display_SegGradSelect_4bit(int x, int y, int w, int h, int x_res, int y_res, unsigned char *data, unsigned char *src)
{
unsigned char alpha = 0xff;
int pos = 0;
if (x == -1 && y == -1)
{
alpha = (x_res * y_res) >> 8;
pos = (y + 1) * w + (x + 1);
}
else if (x == w && y == -1)
{
alpha = ((255 - x_res) * y_res) >> 8;
pos = (y + 1) * w + (x - 1);
}
else if (x == -1 && y == h)
{
alpha = ((x_res) * (255 - y_res)) >> 8;
pos = (y - 1) * w + (x + 1);
}
else if (x == w && y == h)
{
alpha = ((255 - x_res) * (255 - y_res)) >> 8;
*data = src[(y - 1) * w + (x - 1)];
}
else if (x == -1 && y > -1 && y < h)
{
alpha = x_res;
pos = y * w + (x + 1);
}
else if (y == -1 && x > -1 && x < w)
{
alpha = y_res;
pos = (y + 1) * w + x;
}
else if (x == w && y > -1 && y < h)
{
alpha = 255 - x_res;
pos = y * w + x - 1;
}
else if (y == h && x > -1 && x < w)
{
alpha = 255 - y_res;
pos = (y - 1) * w + x;
}
if ((pos & 1) == 0)
*data = src[pos];
return alpha;
}
/**
* display rotate.
*/
void rt_display_rotate_32bit(float angle, int w, int h, unsigned int *src, unsigned int *dst, int dst_str, int xcen, int ycen)
{
int x, y;
int xlt, xrt, xld, xrd;
int ylt, yrt, yld, yrd;
int xmin, xmax, ymin, ymax;
//rt_kprintf("angle = %d, w = %d, h = %d, src = 0x%08x, dst = 0x%08x, dst_str = %d, xcen = %d, ycen = %d\n",
// (int)angle, w, h, src, dst, dst_str, xcen, ycen);
float cosa = cos((angle * PI) / 180);
float sina = sin((angle * PI) / 180);
xlt = cosa * (-xcen) + -sina * (-ycen);
ylt = sina * (-xcen) + cosa * (-ycen);
xrt = cosa * (w - xcen) + -sina * (-ycen);
yrt = sina * (w - xcen) + cosa * (-ycen);
xld = cosa * (-xcen) + -sina * (h - ycen);
yld = sina * (-xcen) + cosa * (h - ycen);
xrd = cosa * (w - xcen) + -sina * (h - ycen);
yrd = sina * (w - xcen) + cosa * (h - ycen);
xmin = MIN(xrd, MIN(xld, MIN(xlt, xrt))) - 1;
xmax = MAX(xrd, MAX(xld, MAX(xlt, xrt))) + 1;
ymin = MIN(yrd, MIN(yld, MIN(ylt, yrt))) - 1;
ymax = MAX(yrd, MAX(yld, MAX(ylt, yrt))) + 1;
float x_pos, y_pos;
unsigned char alpha;
int m = ymin;
for (int j = ymin; j < ymax; j++)
{
int n = xmin;
for (int i = xmin; i < xmax; i++)
{
x_pos = (cosa * i + sina * j) + xcen;
y_pos = (-sina * i + cosa * j) + ycen;
x = floor(x_pos);
y = floor(y_pos);
if ((x_pos >= 0) && (x_pos < w) && (y_pos >= 0) && (y_pos < h))
{
dst[m * dst_str + n] = src[y * w + x];
}
else if ((x >= -1) && (y >= -1) && (x <= w) && (y <= h))
{
int x_res = (x_pos - x) * (1 << 8);
int y_res = (y_pos - y) * (1 << 8);
unsigned int data;
alpha = rt_display_SegGradSelect_32bit(x, y, w, h, x_res, y_res, &data, src);
unsigned char /*sa,*/ sr, sg, sb, da, dr, dg, db;
sr = (dst[m * dst_str + n]) & 0xff;
sg = (dst[m * dst_str + n] >> 8) & 0xff;
sb = (dst[m * dst_str + n] >> 16) & 0xff;
//sa = (dst[m*dst_str + n] >> 24) & 0xff;
dr = (data) & 0xff;
dg = (data >> 8) & 0xff;
db = (data >> 16) & 0xff;
da = (data >> 24) & 0xff;
alpha = (alpha * da) >> 8;
dr = (sr * (255 - alpha) + dr * alpha) >> 8;
dg = (sg * (255 - alpha) + dg * alpha) >> 8;
db = (sb * (255 - alpha) + db * alpha) >> 8;
dst[m * dst_str + n] = dr | (dg << 8) | (db << 16) | (da << 24);
}
n++;
}
m++;
}
}
void rt_display_rotate_24bit(float angle, int w, int h, unsigned char *src, unsigned char *dst, int dst_str, int xcen, int ycen)
{
int x, y;
int xlt, xrt, xld, xrd;
int ylt, yrt, yld, yrd;
int xmin, xmax, ymin, ymax;
float cosa = cos((angle * PI) / 180);
float sina = sin((angle * PI) / 180);
xlt = cosa * (-xcen) + -sina * (-ycen);
ylt = sina * (-xcen) + cosa * (-ycen);
xrt = cosa * (w - xcen) + -sina * (-ycen);
yrt = sina * (w - xcen) + cosa * (-ycen);
xld = cosa * (-xcen) + -sina * (h - ycen);
yld = sina * (-xcen) + cosa * (h - ycen);
xrd = cosa * (w - xcen) + -sina * (h - ycen);
yrd = sina * (w - xcen) + cosa * (h - ycen);
xmin = MIN(xrd, MIN(xld, MIN(xlt, xrt))) - 1;
xmax = MAX(xrd, MAX(xld, MAX(xlt, xrt))) + 1;
ymin = MIN(yrd, MIN(yld, MIN(ylt, yrt))) - 1;
ymax = MAX(yrd, MAX(yld, MAX(ylt, yrt))) + 1;
float x_pos, y_pos;
unsigned char alpha;
//int cur_x_pos;
//int cur_y_pos;
int m = ymin;
for (int j = ymin; j < ymax; j++)
{
int n = xmin;
for (int i = xmin; i < xmax; i++)
{
x_pos = (cosa * i + sina * j) + xcen;
y_pos = (-sina * i + cosa * j) + ycen;
x = floor(x_pos);
y = floor(y_pos);
if (x_pos >= 0 && x_pos < w && y_pos >= 0 && y_pos < h)
{
dst[m * dst_str + n] = src[y * w + x];
}
else if ((x >= -1) && (y >= -1) && (x <= w) && (y <= h))
{
int x_res = (x_pos - x) * (1 << 8);
int y_res = (y_pos - y) * (1 << 8);
unsigned char data;
alpha = rt_display_SegGradSelect_8bit(x, y, w, h, x_res, y_res, &data, src);
dst[m * dst_str + n] = (dst[m * dst_str + n] * (255 - alpha) + data * alpha) >> 8;
}
n++;
}
m++;
}
}
void rt_display_rotate_8bit(float angle, int w, int h, unsigned char *src, unsigned char *dst, int dst_str, int xcen, int ycen)
{
int x, y;
int xlt, xrt, xld, xrd;
int ylt, yrt, yld, yrd;
int xmin, xmax, ymin, ymax;
float cosa = cos((angle * PI) / 180);
float sina = sin((angle * PI) / 180);
xlt = cosa * (-xcen) + -sina * (-ycen);
ylt = sina * (-xcen) + cosa * (-ycen);
xrt = cosa * (w - xcen) + -sina * (-ycen);
yrt = sina * (w - xcen) + cosa * (-ycen);
xld = cosa * (-xcen) + -sina * (h - ycen);
yld = sina * (-xcen) + cosa * (h - ycen);
xrd = cosa * (w - xcen) + -sina * (h - ycen);
yrd = sina * (w - xcen) + cosa * (h - ycen);
xmin = MIN(xrd, MIN(xld, MIN(xlt, xrt))) - 1;
xmax = MAX(xrd, MAX(xld, MAX(xlt, xrt))) + 1;
ymin = MIN(yrd, MIN(yld, MIN(ylt, yrt))) - 1;
ymax = MAX(yrd, MAX(yld, MAX(ylt, yrt))) + 1;
float x_pos, y_pos;
unsigned char alpha;
int m = ymin;
for (int j = ymin; j < ymax; j++)
{
int n = xmin;
for (int i = xmin; i < xmax; i++)
{
x_pos = (cosa * i + sina * j) + xcen;
y_pos = (-sina * i + cosa * j) + ycen;
x = floor(x_pos);
y = floor(y_pos);
if (x_pos >= 0 && x_pos < w && y_pos >= 0 && y_pos < h)
{
dst[m * dst_str + n] = src[y * w + x];
}
else if ((x >= -1) && (y >= -1) && (x <= w) && (y <= h))
{
int x_res = (x_pos - x) * (1 << 8);
int y_res = (y_pos - y) * (1 << 8);
unsigned char data = 0;
alpha = rt_display_SegGradSelect_8bit(x, y, w, h, x_res, y_res, &data, src);
unsigned char sr, sg, sb, dr, dg, db;
sr = (dst[m * dst_str + n]) & 0x7;
sg = (dst[m * dst_str + n] >> 3) & 0x7;
sb = (dst[m * dst_str + n] >> 6) & 0x3;
dr = (data) & 0x7;
dg = (data >> 3) & 0x7;
db = (data >> 6) & 0x3;
dr = (sr * (255 - alpha) + dr * alpha) >> 8;
dg = (sg * (255 - alpha) + dg * alpha) >> 8;
db = (sb * (255 - alpha) + db * alpha) >> 8;
dst[m * dst_str + n] = dr | (dg << 3) | (db << 6);
}
n++;
}
m++;
}
}
void rt_display_rotate_16bit(float angle, int w, int h, unsigned short *src, unsigned short *dst, int dst_str, int xcen, int ycen)
{
int x, y;
int xlt, xrt, xld, xrd;
int ylt, yrt, yld, yrd;
int xmin, xmax, ymin, ymax;
float cosa = cos((angle * PI) / 180);
float sina = sin((angle * PI) / 180);
xlt = cosa * (-xcen) + -sina * (-ycen);
ylt = sina * (-xcen) + cosa * (-ycen);
xrt = cosa * (w - xcen) + -sina * (-ycen);
yrt = sina * (w - xcen) + cosa * (-ycen);
xld = cosa * (-xcen) + -sina * (h - ycen);
yld = sina * (-xcen) + cosa * (h - ycen);
xrd = cosa * (w - xcen) + -sina * (h - ycen);
yrd = sina * (w - xcen) + cosa * (h - ycen);
xmin = MIN(xrd, MIN(xld, MIN(xlt, xrt))) - 1;
xmax = MAX(xrd, MAX(xld, MAX(xlt, xrt))) + 1;
ymin = MIN(yrd, MIN(yld, MIN(ylt, yrt))) - 1;
ymax = MAX(yrd, MAX(yld, MAX(ylt, yrt))) + 1;
float x_pos, y_pos;
unsigned char alpha;
int m = ymin;
for (int j = ymin; j < ymax; j++)
{
int n = xmin;
for (int i = xmin; i < xmax; i++)
{
x_pos = (cosa * i + sina * j) + xcen;
y_pos = (-sina * i + cosa * j) + ycen;
x = floor(x_pos);
y = floor(y_pos);
if (x_pos >= 0 && x_pos < w && y_pos >= 0 && y_pos < h)
{
dst[m * dst_str + n] = src[y * w + x];
}
else if ((x >= -1) && (y >= -1) && (x <= w) && (y <= h))
{
int x_res = (x_pos - x) * (1 << 8);
int y_res = (y_pos - y) * (1 << 8);
unsigned short data = 0;
alpha = rt_display_SegGradSelect_16bit(x, y, w, h, x_res, y_res, &data, src);
unsigned char sr, sg, sb, dr, dg, db;
sr = (dst[m * dst_str + n]) & 0x1f;
sg = (dst[m * dst_str + n] >> 5) & 0x3f;
sb = (dst[m * dst_str + n] >> 11) & 0x1f;
dr = (data) & 0x1f;
dg = (data >> 5) & 0x3f;
db = (data >> 11) & 0x1f;
dr = (sr * (255 - alpha) + dr * alpha) >> 8;
dg = (sg * (255 - alpha) + dg * alpha) >> 8;
db = (sb * (255 - alpha) + db * alpha) >> 8;
dst[m * dst_str + n] = dr | (dg << 5) | (db << 11);
}
n++;
}
m++;
}
}
void rt_display_rotate_4bit(float angle, int w, int h, unsigned char *src, unsigned char *dst, int dst_str, int xcen, int ycen)
{
int x, y;
int xlt, xrt, xld, xrd;
int ylt, yrt, yld, yrd;
int xmin, xmax, ymin, ymax;
float cosa = cos((angle * PI) / 180);
float sina = sin((angle * PI) / 180);
xlt = cosa * (-xcen) + -sina * (-ycen);
ylt = sina * (-xcen) + cosa * (-ycen);
xrt = cosa * (w - xcen) + -sina * (-ycen);
yrt = sina * (w - xcen) + cosa * (-ycen);
xld = cosa * (-xcen) + -sina * (h - ycen);
yld = sina * (-xcen) + cosa * (h - ycen);
xrd = cosa * (w - xcen) + -sina * (h - ycen);
yrd = sina * (w - xcen) + cosa * (h - ycen);
xmin = MIN(xrd, MIN(xld, MIN(xlt, xrt))) - 1;
xmax = MAX(xrd, MAX(xld, MAX(xlt, xrt))) + 1;
ymin = MIN(yrd, MIN(yld, MIN(ylt, yrt))) - 1;
ymax = MAX(yrd, MAX(yld, MAX(ylt, yrt))) + 1;
float x_pos, y_pos;
unsigned char alpha;
int m = ymin;
for (int j = ymin; j < ymax; j++)
{
int n = xmin;
for (int i = xmin; i < xmax; i++)
{
x_pos = (cosa * i + sina * j) + xcen;
y_pos = (-sina * i + cosa * j) + ycen;
x = floor(x_pos);
y = floor(y_pos);
int dst_pos = ((m * dst_str) + n) >> 1;
int src_pos = ((y * w >> 1) + x) >> 1;
if (x_pos >= 0 && x_pos < w && y_pos >= 0 && y_pos < h)
{
if ((x & 1) == 0)
{
dst[dst_pos] = (dst[dst_pos] & 0xf0) | ((src[src_pos] & 0xf));
}
else
{
dst[dst_pos] = (dst[dst_pos] & 0x0f) | ((src[src_pos] & 0xf) << 4);
}
}
else if ((x >= -1) && (y >= -1) && (x <= w) && (y <= h))
{
int x_res = (x_pos - x) * (1 << 8);
int y_res = (y_pos - y) * (1 << 8);
unsigned char data = 0;
alpha = rt_display_SegGradSelect_4bit(x, y, w, h, x_res, y_res, &data, src);
unsigned char sr, sg, sb, dr, dg, db;
sr = (dst[m * dst_str + n]) & 0x7;
sg = (dst[m * dst_str + n] >> 3) & 0x7;
sb = (dst[m * dst_str + n] >> 6) & 0x3;
dr = (data) & 0x7;
dg = (data >> 3) & 0x7;
db = (data >> 6) & 0x3;
dr = (sr * (255 - alpha) + dr * alpha) >> 8;
dg = (sg * (255 - alpha) + dg * alpha) >> 8;
db = (sb * (255 - alpha) + db * alpha) >> 8;
dst[m * dst_str + n] = dr | (dg << 3) | (db << 6);
}
n++;
}
m++;
}
}
/*
**************************************************************************************************
*
* Image fill.
*
**************************************************************************************************
*/
/**
* fill image data to fb buffer
*/
void rt_display_img_fill(image_info_t *img_info, rt_uint8_t *fb, rt_int32_t xVir, rt_int32_t xoffset, rt_int32_t yoffset)
{
rt_err_t ret = RT_EOK;
rt_int32_t x, y, i;
rt_uint8_t bitval;
if (img_info->type == IMG_TYPE_COMPRESS)
{
if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_RGB332)
{
ret = rt_display_decompress(img_info, fb, xVir, xoffset, yoffset);
RT_ASSERT(ret == RT_EOK);
}
else if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_RGB565)
{
image_info_t info;
rt_memcpy(&info, img_info, sizeof(image_info_t));
info.x *= 2;
info.w *= 2;
xVir *= 2;
xoffset *= 2;
ret = rt_display_decompress(&info, fb, xVir, xoffset, yoffset);
RT_ASSERT(ret == RT_EOK);
}
else if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_ARGB888)
{
image_info_t info;
rt_memcpy(&info, img_info, sizeof(image_info_t));
info.x *= 4;
info.w *= 4;
xVir *= 4;
xoffset *= 4;
ret = rt_display_decompress(&info, fb, xVir, xoffset, yoffset);
RT_ASSERT(ret == RT_EOK);
}
else if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_GRAY16)
{
image_info_t info;
rt_memcpy(&info, img_info, sizeof(image_info_t));
info.x /= 2;
info.w /= 2;
xVir /= 2;
xoffset /= 2;
ret = rt_display_decompress(&info, fb, xVir, xoffset, yoffset);
RT_ASSERT(ret == RT_EOK);
}
else if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_GRAY4)
{
image_info_t info;
rt_memcpy(&info, img_info, sizeof(image_info_t));
info.x /= 4;
info.w /= 4;
xVir /= 4;
xoffset /= 4;
ret = rt_display_decompress(&info, fb, xVir, xoffset, yoffset);
RT_ASSERT(ret == RT_EOK);
}
else //if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_GRAY1)
{
ret = jbig2_decompression(img_info, fb, xVir, xoffset, yoffset);
RT_ASSERT(ret == 0);
}
}
else //if (img_info->type == IMG_TYPE_RAW)
{
if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_RGB332)
{
for (i = 0, y = yoffset; y < yoffset + img_info->h; y++)
{
for (x = xoffset; x < xoffset + img_info->w; x++)
{
fb[(y * xVir) + x] = img_info->data[i++];
}
}
}
else if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_RGB565)
{
for (i = 0, y = yoffset; y < yoffset + img_info->h; y++)
{
for (x = xoffset * 2; x < xoffset * 2 + img_info->w * 2; x++)
{
fb[(y * xVir * 2) + x] = img_info->data[i++];
}
}
}
else if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_RGB888)
{
for (i = 0, y = yoffset; y < yoffset + img_info->h; y++)
{
for (x = xoffset * 3; x < xoffset * 3 + img_info->w * 3; x++)
{
fb[(y * xVir * 3) + x] = img_info->data[i++];
}
}
}
else if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_ARGB888)
{
for (i = 0, y = yoffset; y < yoffset + img_info->h; y++)
{
for (x = xoffset * 4; x < xoffset * 4 + img_info->w * 4; x++)
{
fb[(y * xVir * 4) + x] = img_info->data[i++];
}
}
}
else if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_GRAY1)
{
RT_ASSERT((xVir % 8) == 0);
rt_uint8_t colorkey = (rt_uint8_t)(img_info->colorkey & 0xff);
if (((xoffset % 8) == 0) && ((img_info->colorkey & COLOR_KEY_EN) == 0))
{
for (y = yoffset; y < yoffset + img_info->h; y++)
{
i = (y - yoffset) * ((img_info->w + 7) / 8);
for (x = xoffset / 8; x < (xoffset + img_info->w) / 8; x++)
{
fb[y * (xVir / 8) + x] = img_info->data[i++];
}
if (((xoffset + img_info->w) % 8) != 0)
{
rt_uint8_t maskval = 0xff >> (img_info->w % 8);
fb[y * (xVir / 8) + x] &= maskval;
fb[y * (xVir / 8) + x] |= (img_info->data[i++] & (~maskval));
}
}
}
else
{
for (y = yoffset; y < yoffset + img_info->h; y++)
{
i = (y - yoffset) * ((img_info->w + 7) / 8) * 8;
for (x = xoffset; x < xoffset + img_info->w; x++)
{
bitval = (img_info->data[i / 8] << (i % 8)) & 0x80;
i++;
if (img_info->colorkey & COLOR_KEY_EN)
{
if (((colorkey != 0) && (bitval != 0)) ||
((colorkey == 0) && (bitval == 0)))
{
continue;
}
}
fb[y * (xVir / 8) + x / 8] &= ~(0x80 >> (x % 8));
fb[y * (xVir / 8) + x / 8] |= bitval >> (x % 8);
}
}
}
}
else if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_GRAY4)
{
RT_ASSERT((xVir % 4) == 0);
if ((xoffset % 4) == 0)
{
for (y = yoffset; y < yoffset + img_info->h; y++)
{
i = (y - yoffset) * ((img_info->w + 3) / 4);
for (x = xoffset / 4; x < (xoffset + img_info->w) / 4; x++)
{
fb[y * (xVir / 4) + x] = img_info->data[i++];
}
if (((xoffset + img_info->w) % 4) != 0)
{
rt_uint8_t maskval = 0xff >> (img_info->w % 4);
fb[y * (xVir / 4) + x] &= maskval;
fb[y * (xVir / 4) + x] |= (img_info->data[i++] & (~maskval));
}
}
}
else
{
for (y = yoffset; y < yoffset + img_info->h; y++)
{
i = (y - yoffset) * ((img_info->w + 3) / 4) * 4;
for (x = xoffset; x < xoffset + img_info->w; x++)
{
bitval = (img_info->data[i / 4] << (i % 4)) & 0xc0;
i++;
fb[y * (xVir / 4) + x / 4] &= ~(0xc0 >> (x % 4));
fb[y * (xVir / 4) + x / 4] |= bitval >> (x % 4);
}
}
}
}
else if (img_info->pixel == RTGRAPHIC_PIXEL_FORMAT_GRAY16)
{
RT_ASSERT((xVir % 2) == 0);
if ((xoffset % 2) == 0)
{
for (y = yoffset; y < yoffset + img_info->h; y++)
{
i = (y - yoffset) * ((img_info->w + 1) / 2);
for (x = xoffset / 2; x < (xoffset + img_info->w) / 2; x++)
{
fb[y * (xVir / 2) + x] = img_info->data[i++];
}
if (((xoffset + img_info->w) % 2) != 0)
{
rt_uint8_t maskval = 0xff >> (img_info->w % 2);
fb[y * (xVir / 2) + x] &= maskval;
fb[y * (xVir / 2) + x] |= (img_info->data[i++] & (~maskval));
}
}
}
else
{
for (y = yoffset; y < yoffset + img_info->h; y++)
{
i = (y - yoffset) * ((img_info->w + 1) / 2) * 2;
for (x = xoffset; x < xoffset + img_info->w; x++)
{
bitval = (img_info->data[i / 2] << (i % 2)) & 0xf0;
i++;
fb[y * (xVir / 2) + x / 2] &= ~(0xf0 >> (x % 2));
fb[y * (xVir / 2) + x / 2] |= bitval >> (x % 2);
}
}
}
}
}
}