image_hdc.c 6.1 KB
Newer Older
B
bernard.xiong 已提交
1
#include <rtthread.h>
B
bernard.xiong 已提交
2
#include <rtgui/image.h>
B
bernard.xiong 已提交
3 4 5 6 7 8 9 10 11
#include <rtgui/rtgui_system.h>

#define HDC_MAGIC_LEN       4

struct rtgui_image_hdc
{
	rt_bool_t is_loaded;

	struct rtgui_filerw* filerw;
B
bernard.xiong 已提交
12
	struct rtgui_graphic_driver* hw_driver;
B
bernard.xiong 已提交
13 14

	/* hdc image information */
B
bernard.xiong 已提交
15 16
	rt_uint16_t byte_per_pixel;
    rt_uint16_t pitch;
B
bernard.xiong 已提交
17

B
bernard.xiong 已提交
18
	rt_size_t   pixel_offset;
B
bernard.xiong 已提交
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
	rt_uint8_t *pixels;
};

static rt_bool_t rtgui_image_hdc_check(struct rtgui_filerw* file);
static rt_bool_t rtgui_image_hdc_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
static void rtgui_image_hdc_unload(struct rtgui_image* image);
static void rtgui_image_hdc_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);

struct rtgui_image_engine rtgui_image_hdc_engine =
{
	"hdc",
	{ RT_NULL },
	rtgui_image_hdc_check,
	rtgui_image_hdc_load,
	rtgui_image_hdc_unload,
	rtgui_image_hdc_blit
};

static rt_bool_t rtgui_image_hdc_check(struct rtgui_filerw* file)
{
	int start;
	rt_bool_t is_HDC;
	rt_uint8_t magic[4];

	if ( !file ) return 0;

	start = rtgui_filerw_tell(file);

B
bernard.xiong 已提交
47 48
	/* move to the beginning of file */
	rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET);
B
bernard.xiong 已提交
49 50 51 52 53 54 55 56 57 58 59 60

	is_HDC = RT_FALSE;
	if ( rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic) )
	{
		if ( magic[0] == 'H' &&
				magic[1] == 'D' &&
				magic[2] == 'C' &&
				magic[3] == '\0' )
		{
			is_HDC = RT_TRUE;
		}
	}
B
bernard.xiong 已提交
61
	rtgui_filerw_seek(file, start, RTGUI_FILE_SEEK_SET);
B
bernard.xiong 已提交
62 63 64 65 66 67 68 69 70 71 72 73

	return(is_HDC);
}

static rt_bool_t rtgui_image_hdc_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
{
    rt_uint32_t header[5];
    struct rtgui_image_hdc* hdc;

    hdc = (struct rtgui_image_hdc*) rtgui_malloc(sizeof(struct rtgui_image_hdc));
    if (hdc == RT_NULL) return RT_FALSE;

B
bernard.xiong 已提交
74 75 76
	hdc->hw_driver = rtgui_graphic_driver_get_default();
	if (hdc->hw_driver == RT_NULL) { rtgui_free(hdc); return RT_FALSE; }

B
bernard.xiong 已提交
77 78 79 80 81
    rtgui_filerw_read(file, (char*)&header, 1, sizeof(header));

	/* set image information */
	image->w = header[1]; image->h = header[2];
	image->engine = &rtgui_image_hdc_engine;
B
bernard.xiong 已提交
82 83 84 85 86
	image->data = hdc;
	hdc->filerw = file;
	hdc->byte_per_pixel = hdc->hw_driver->byte_per_pixel;
	hdc->pitch = image->w * hdc->byte_per_pixel;
	hdc->pixel_offset = rtgui_filerw_tell(file);
B
bernard.xiong 已提交
87 88 89 90

	if (load == RT_TRUE)
	{
		/* load all pixels */
B
bernard.xiong 已提交
91 92
		hdc->pixels = rtgui_malloc(image->h * hdc->pitch);
		if (hdc->pixels == RT_NULL)
B
bernard.xiong 已提交
93 94
		{
            /* release data */
B
bernard.xiong 已提交
95
            rtgui_free(hdc);
B
bernard.xiong 已提交
96 97 98
            return RT_FALSE;
		}

B
bernard.xiong 已提交
99 100 101 102
		rtgui_filerw_read(hdc->filerw, hdc->pixels, 1, image->h * hdc->pitch);
		rtgui_filerw_close(hdc->filerw);
		hdc->filerw = RT_NULL;
		hdc->pixel_offset = 0;
B
bernard.xiong 已提交
103 104 105
	}
	else
	{
B
bernard.xiong 已提交
106
		hdc->pixels = RT_NULL;
B
bernard.xiong 已提交
107 108 109 110 111 112 113
	}

	return RT_TRUE;
}

static void rtgui_image_hdc_unload(struct rtgui_image* image)
{
B
bernard.xiong 已提交
114
	struct rtgui_image_hdc* hdc;
B
bernard.xiong 已提交
115 116 117

	if (image != RT_NULL)
	{
B
bernard.xiong 已提交
118
		hdc = (struct rtgui_image_hdc*) image->data;
B
bernard.xiong 已提交
119

B
bernard.xiong 已提交
120 121 122 123 124 125
		if (hdc->pixels != RT_NULL) rtgui_free(hdc->pixels);
		if (hdc->filerw != RT_NULL)
		{
			rtgui_filerw_close(hdc->filerw);
			hdc->filerw = RT_NULL;
		}
B
bernard.xiong 已提交
126 127

		/* release data */
B
bernard.xiong 已提交
128
		rtgui_free(hdc);
B
bernard.xiong 已提交
129 130 131 132 133
	}
}

static void rtgui_image_hdc_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect)
{
B
bernard.xiong 已提交
134
	rt_uint16_t y, w, h;
B
bernard.xiong 已提交
135
	rtgui_color_t foreground;
B
bernard.xiong 已提交
136 137 138
	struct rtgui_image_hdc* hdc;
	rt_uint16_t rect_pitch, hw_pitch;
	rtgui_rect_t dc_rect;
B
bernard.xiong 已提交
139 140 141

	RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);

B
bernard.xiong 已提交
142 143 144 145 146 147 148 149 150 151 152 153 154 155
	/* this dc is not visible */
	if (dc->get_visible(dc) != RT_TRUE) return;

	hdc = (struct rtgui_image_hdc*) image->data;
	RT_ASSERT(hdc != RT_NULL);

	/* transfer logic coordinate to physical coordinate */
	if (dc->type == RTGUI_DC_HW)
	{
		struct rtgui_dc_hw *hw_dc = (struct rtgui_dc_hw*)dc;
		dc_rect = hw_dc->owner->extent;
	}
	else rtgui_dc_get_rect(dc, &dc_rect);
	rtgui_rect_moveto(rect, dc_rect.x1, dc_rect.y1);
B
bernard.xiong 已提交
156

B
bernard.xiong 已提交
157
	/* the minimum rect */
B
bernard.xiong 已提交
158 159 160 161 162
    if (image->w < rtgui_rect_width(*rect)) w = image->w;
    else w = rtgui_rect_width(*rect);
    if (image->h < rtgui_rect_height(*rect)) h = image->h;
    else h = rtgui_rect_height(*rect);

B
bernard.xiong 已提交
163 164 165 166
	/* get rect pitch */
	rect_pitch = w * hdc->byte_per_pixel;
	hw_pitch = hdc->hw_driver->width * hdc->hw_driver->byte_per_pixel;

B
bernard.xiong 已提交
167 168 169
	/* save foreground color */
	foreground = rtgui_dc_get_color(dc);

B
bernard.xiong 已提交
170
    if (hdc->pixels != RT_NULL)
B
bernard.xiong 已提交
171
    {
B
bernard.xiong 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
		if (hdc->hw_driver->get_framebuffer() != RT_NULL)
		{
			rt_uint8_t* rect_ptr;
			rt_uint8_t* hw_ptr;

			/* get pixel pointer */
			hw_ptr = hdc->hw_driver->get_framebuffer();
			rect_ptr = hdc->pixels;

			/* move hardware pixel pointer */
			hw_ptr += rect->y1 * hdc->pitch + rect->x1 * hdc->byte_per_pixel;

			for (y = 0; y < h; y ++)
			{
				rt_memcpy(hw_ptr, rect_ptr, rect_pitch);
				hw_ptr += hw_pitch;
				rect_ptr += rect_pitch;
			}
		}
		else
		{
			rt_uint8_t* rect_ptr;

			/* get pixel pointer */
			rect_ptr = hdc->pixels;

			for (y = 0; y < h; y ++)
			{
				hdc->hw_driver->draw_raw_hline(rect_ptr, rect->x1,  rect->x2, rect->y1 + y);
				rect_ptr += rect_pitch;
			}
		}
B
bernard.xiong 已提交
204 205 206
    }
    else
    {
B
bernard.xiong 已提交
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
		rt_uint8_t* rect_ptr;
		rect_ptr = rtgui_malloc(rect_pitch);
		if (rect_ptr == RT_NULL) return; /* no memory */

		/* seek to the begin of pixel data */
		rtgui_filerw_seek(hdc->filerw, hdc->pixel_offset, RTGUI_FILE_SEEK_SET);

		if (hdc->hw_driver->get_framebuffer() != RT_NULL)
		{
			rt_uint8_t* hw_ptr;

			/* get pixel pointer */
			hw_ptr = hdc->hw_driver->get_framebuffer();
			/* move hardware pixel pointer */
			hw_ptr += rect->y1 * hdc->pitch + rect->x1 * hdc->byte_per_pixel;

			for (y = 0; y < h; y ++)
			{
				/* read pixel data */
				if (rtgui_filerw_read(hdc->filerw, rect_ptr, 1, rect_pitch) != rect_pitch)
					break; /* read data failed */

				rt_memcpy(hw_ptr, rect_ptr, rect_pitch);
				hw_ptr += hw_pitch;
			}
		}
		else
		{
			for (y = 0; y < h; y ++)
			{
				/* read pixel data */
				if (rtgui_filerw_read(hdc->filerw, rect_ptr, 1, rect_pitch) != rect_pitch)
					break; /* read data failed */

				hdc->hw_driver->draw_raw_hline(rect_ptr, rect->x1,  rect->x2, rect->y1 + y);
			}
		}

		rtgui_free(rect_ptr);
B
bernard.xiong 已提交
246 247 248 249 250 251 252 253
    }

	/* restore foreground */
	rtgui_dc_set_color(dc, foreground);
}

void rtgui_image_hdc_init()
{
B
bernard.xiong 已提交
254
	/* register hdc on image system */
B
bernard.xiong 已提交
255 256
	rtgui_image_register_engine(&rtgui_image_hdc_engine);
}