image_hdc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. #include <rtthread.h>
  2. #include <rtgui/dc_hw.h>
  3. #include <rtgui/image.h>
  4. #include <rtgui/rtgui_system.h>
  5. #include <rtgui/image_hdc.h>
  6. #include <rtgui/blit.h>
  7. #define HDC_MAGIC_LEN 4
  8. extern int fastlz_decompress(const void *input, int length, void *output, int maxout);
  9. struct rtgui_image_hdc
  10. {
  11. rt_bool_t is_loaded;
  12. /* hdc image information */
  13. rt_uint16_t byte_per_pixel;
  14. rt_uint16_t pitch;
  15. rt_uint8_t pixel_format;
  16. rt_size_t pixel_offset;
  17. rt_uint8_t *pixels;
  18. struct rtgui_filerw *filerw;
  19. };
  20. static rt_bool_t rtgui_image_hdc_check(struct rtgui_filerw *file);
  21. static rt_bool_t rtgui_image_hdc_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load);
  22. static void rtgui_image_hdc_unload(struct rtgui_image *image);
  23. static void rtgui_image_hdc_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect);
  24. static void rtgui_image_hdcmm_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *dst_rect);
  25. struct rtgui_image_engine rtgui_image_hdc_engine =
  26. {
  27. "hdc",
  28. { RT_NULL },
  29. rtgui_image_hdc_check,
  30. rtgui_image_hdc_load,
  31. rtgui_image_hdc_unload,
  32. rtgui_image_hdc_blit,
  33. };
  34. const struct rtgui_image_engine rtgui_image_hdcmm_engine =
  35. {
  36. "hdcmm",
  37. {RT_NULL},
  38. RT_NULL,
  39. RT_NULL,
  40. RT_NULL,
  41. rtgui_image_hdcmm_blit,
  42. };
  43. static rt_bool_t rtgui_image_hdc_check(struct rtgui_filerw *file)
  44. {
  45. int start;
  46. rt_bool_t is_HDC;
  47. rt_uint8_t magic[4];
  48. if (!file) return 0;
  49. start = rtgui_filerw_tell(file);
  50. /* move to the beginning of file */
  51. rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET);
  52. is_HDC = RT_FALSE;
  53. if (rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic))
  54. {
  55. if (magic[0] == 'H' &&
  56. magic[1] == 'D' &&
  57. magic[2] == 'C' &&
  58. magic[3] == '\0')
  59. {
  60. is_HDC = RT_TRUE;
  61. }
  62. }
  63. rtgui_filerw_seek(file, start, RTGUI_FILE_SEEK_SET);
  64. return (is_HDC);
  65. }
  66. static rt_bool_t rtgui_image_hdc_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
  67. {
  68. rt_uint32_t header[5];
  69. struct rtgui_image_hdc *hdc;
  70. hdc = (struct rtgui_image_hdc *) rtgui_malloc(sizeof(struct rtgui_image_hdc));
  71. if (hdc == RT_NULL) return RT_FALSE;
  72. rtgui_filerw_read(file, (char *)&header, 1, sizeof(header));
  73. /* set image information */
  74. image->w = (rt_uint16_t)header[1];
  75. image->h = (rt_uint16_t)header[2];
  76. image->engine = &rtgui_image_hdc_engine;
  77. image->data = hdc;
  78. hdc->pixel_format = header[3];
  79. hdc->filerw = file;
  80. if (header[3] == 0)
  81. {
  82. /* 0.x version */
  83. hdc->pixel_format = rtgui_graphic_driver_get_default()->pixel_format;
  84. }
  85. else if (header[3] == 1)
  86. {
  87. /* 1.x version */
  88. hdc->pixel_format = header[4];
  89. }
  90. else if (header[3] == 2)
  91. {
  92. /* 2.x version */
  93. hdc->pixel_format = header[4];
  94. }
  95. hdc->byte_per_pixel = rtgui_color_get_bpp(hdc->pixel_format);
  96. hdc->pitch = image->w * hdc->byte_per_pixel;
  97. hdc->pixel_offset = rtgui_filerw_tell(file);
  98. if (load == RT_TRUE)
  99. {
  100. if (header[3] == 2)
  101. {
  102. #if 0 /* TODO: add HDC with fastlz compressed */
  103. int data_length, dec_length;
  104. rt_uint8_t *data;
  105. data_length = rtgui_filerw_seek(hdc->filerw, 0, SEEK_END) - sizeof(header);
  106. rtgui_filerw_seek(hdc->filerw, sizeof(header), SEEK_SET);
  107. data = (rt_uint8_t *)rtgui_malloc(data_length);
  108. if (data == RT_NULL)
  109. {
  110. /* release data */
  111. rtgui_free(hdc);
  112. return RT_FALSE;
  113. }
  114. if (rtgui_filerw_read(hdc->filerw, data, 1, data_length) != data_length)
  115. {
  116. rtgui_filerw_close(hdc->filerw);
  117. /* release data */
  118. rtgui_free(hdc);
  119. return RT_FALSE;
  120. }
  121. rtgui_filerw_close(hdc->filerw);
  122. hdc->filerw = RT_NULL;
  123. hdc->pixels = (rt_uint8_t *)rtgui_malloc(image->h * hdc->pitch);
  124. if (hdc->pixels == RT_NULL)
  125. {
  126. /* release data */
  127. rtgui_free(hdc);
  128. rtgui_free(data);
  129. return RT_FALSE;
  130. }
  131. dec_length = fastlz_decompress(data, data_length, hdc->pixels, image->h * hdc->pitch);
  132. if (dec_length != image->h * hdc->pitch)
  133. {
  134. /* release data */
  135. rtgui_free(hdc->pixels);
  136. rtgui_free(hdc);
  137. rtgui_free(data);
  138. return RT_FALSE;
  139. }
  140. hdc->pixel_offset = 0;
  141. rtgui_free(data);
  142. #endif
  143. }
  144. else
  145. {
  146. /* load all pixels */
  147. hdc->pixels = rtgui_malloc(image->h * hdc->pitch);
  148. if (hdc->pixels == RT_NULL)
  149. {
  150. /* release data */
  151. rtgui_free(hdc);
  152. return RT_FALSE;
  153. }
  154. rtgui_filerw_read(hdc->filerw, hdc->pixels, 1, image->h * hdc->pitch);
  155. rtgui_filerw_close(hdc->filerw);
  156. hdc->filerw = RT_NULL;
  157. hdc->pixel_offset = 0;
  158. }
  159. }
  160. else
  161. {
  162. hdc->pixels = RT_NULL;
  163. }
  164. return RT_TRUE;
  165. }
  166. static void rtgui_image_hdc_unload(struct rtgui_image *image)
  167. {
  168. struct rtgui_image_hdc *hdc;
  169. if (image != RT_NULL)
  170. {
  171. hdc = (struct rtgui_image_hdc *) image->data;
  172. if (hdc->pixels != RT_NULL)
  173. rtgui_free(hdc->pixels);
  174. if (hdc->filerw != RT_NULL)
  175. rtgui_filerw_close(hdc->filerw);
  176. /* release data */
  177. rtgui_free(hdc);
  178. }
  179. }
  180. static void rtgui_image_hdc_blit(struct rtgui_image *image,
  181. struct rtgui_dc *dc,
  182. struct rtgui_rect *dst_rect)
  183. {
  184. rt_int16_t y, w, h, xoff, yoff;
  185. struct rtgui_image_hdc *hdc;
  186. RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL);
  187. /* this dc is not visible */
  188. if (rtgui_dc_get_visible(dc) != RT_TRUE)
  189. return;
  190. if (!image)
  191. return;
  192. hdc = (struct rtgui_image_hdc *) image->data;
  193. RT_ASSERT(hdc != RT_NULL);
  194. xoff = 0;
  195. if (dst_rect->x1 < 0)
  196. {
  197. xoff = -dst_rect->x1;
  198. dst_rect->x1 = 0;
  199. }
  200. yoff = 0;
  201. if (dst_rect->y1 < 0)
  202. {
  203. yoff = -dst_rect->y1;
  204. dst_rect->y1 = 0;
  205. }
  206. if (dst_rect->x2 <= 0 || dst_rect->y2 <= 0)
  207. return;
  208. if (xoff >= image->w || yoff >= image->h)
  209. return;
  210. /* the minimum rect */
  211. w = _UI_MIN(image->w - xoff, rtgui_rect_width(*dst_rect));
  212. h = _UI_MIN(image->h - yoff, rtgui_rect_height(*dst_rect));
  213. if (w == 0 || h == 0)
  214. return;
  215. if (hdc->pixels != RT_NULL)
  216. {
  217. rt_uint8_t *ptr;
  218. /* get pixel pointer */
  219. ptr = hdc->pixels + hdc->pitch * yoff + hdc->byte_per_pixel * xoff;
  220. if (hdc->pixel_format == rtgui_dc_get_pixel_format(dc) &&
  221. hdc->pixel_format != RTGRAPHIC_PIXEL_FORMAT_ARGB888)
  222. {
  223. for (y = 0; y < h; y ++)
  224. {
  225. dc->engine->blit_line(dc,
  226. dst_rect->x1,
  227. dst_rect->x1 + w,
  228. dst_rect->y1 + y,
  229. ptr);
  230. ptr += hdc->pitch;
  231. }
  232. }
  233. else if (dc->type == RTGUI_DC_CLIENT)
  234. {
  235. const struct rtgui_graphic_driver *hw_driver;
  236. struct rtgui_widget *owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
  237. hw_driver = rtgui_graphic_driver_get_default();
  238. if (hdc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888)
  239. {
  240. rt_uint8_t alpha;
  241. for (y = 0; y < h; y ++)
  242. {
  243. int x;
  244. rtgui_color_t *pixel = (rtgui_color_t *)(hdc->pixels + hdc->pitch * (yoff + y) + hdc->byte_per_pixel * xoff);
  245. for (x = 0; x < w; x ++)
  246. {
  247. alpha = RTGUI_RGB_A(*pixel);
  248. if (alpha == 0) { }
  249. if (alpha == 0xff)
  250. {
  251. rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, *pixel);
  252. }
  253. else
  254. {
  255. /* draw an alpha blending point */
  256. if (hw_driver->framebuffer != RT_NULL)
  257. rtgui_dc_blend_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, RTGUI_BLENDMODE_BLEND,
  258. RTGUI_RGB_R(*pixel), RTGUI_RGB_G(*pixel), RTGUI_RGB_B(*pixel), RTGUI_RGB_A(*pixel));
  259. }
  260. pixel ++;
  261. }
  262. }
  263. }
  264. }
  265. else
  266. {
  267. struct rtgui_blit_info info;
  268. info.a = 0;
  269. /* initialize source blit information */
  270. info.src = ptr;
  271. info.src_h = h;
  272. info.src_w = w;
  273. info.src_fmt = hdc->pixel_format;
  274. info.src_pitch = hdc->pitch;
  275. info.src_skip = hdc->pitch - w * rtgui_color_get_bpp(hdc->pixel_format);
  276. /* initialize destination blit information */
  277. if (dc->type == RTGUI_DC_BUFFER)
  278. {
  279. struct rtgui_dc_buffer *buffer;
  280. buffer = (struct rtgui_dc_buffer *)dc;
  281. info.dst = rtgui_dc_buffer_get_pixel(RTGUI_DC(buffer)) + dst_rect->y1 * buffer->pitch +
  282. dst_rect->x1 * rtgui_color_get_bpp(buffer->pixel_format);
  283. info.dst_h = h;
  284. info.dst_w = w;
  285. info.dst_fmt = buffer->pixel_format;
  286. info.dst_pitch = buffer->pitch;
  287. info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(buffer->pixel_format);
  288. }
  289. else if (dc->type == RTGUI_DC_HW)
  290. {
  291. struct rtgui_widget *owner;
  292. struct rtgui_rect r;
  293. struct rtgui_dc_hw *ddc = (struct rtgui_dc_hw *)dc;
  294. owner = ((struct rtgui_dc_hw *)dc)->owner;
  295. rtgui_graphic_driver_get_rect(RT_NULL, &r);
  296. /* blit destination */
  297. info.dst = (rt_uint8_t *)ddc->hw_driver->framebuffer;
  298. info.dst = info.dst + (owner->extent.y1 + dst_rect->y1) * ddc->hw_driver->pitch +
  299. (owner->extent.x1 + dst_rect->x1) * rtgui_color_get_bpp(ddc->hw_driver->pixel_format);
  300. info.dst_fmt = ddc->hw_driver->pixel_format;
  301. info.dst_h = h;
  302. info.dst_w = w;
  303. info.dst_pitch = ddc->hw_driver->pitch;
  304. info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(ddc->hw_driver->pixel_format);
  305. }
  306. rtgui_blit(&info);
  307. }
  308. }
  309. else
  310. {
  311. rt_uint8_t *ptr;
  312. ptr = rtgui_malloc(hdc->byte_per_pixel * w);
  313. if (ptr == RT_NULL)
  314. return; /* no memory */
  315. /* seek to the begin of pixel data */
  316. rtgui_filerw_seek(hdc->filerw,
  317. hdc->pixel_offset + hdc->pitch * yoff + hdc->byte_per_pixel * xoff,
  318. RTGUI_FILE_SEEK_SET);
  319. for (y = 0; y < h; y ++)
  320. {
  321. /* read pixel data */
  322. if (rtgui_filerw_read(hdc->filerw, ptr, 1,
  323. hdc->byte_per_pixel * w) != hdc->byte_per_pixel * w)
  324. break; /* read data failed */
  325. dc->engine->blit_line(dc,
  326. dst_rect->x1,
  327. dst_rect->x1 + w,
  328. dst_rect->y1 + y,
  329. ptr);
  330. rtgui_filerw_seek(hdc->filerw, hdc->byte_per_pixel * xoff, RTGUI_FILE_SEEK_CUR);
  331. }
  332. rtgui_free(ptr);
  333. }
  334. }
  335. static void rtgui_image_hdcmm_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *dst_rect)
  336. {
  337. rt_uint8_t *ptr;
  338. rt_uint16_t y, w, h, xoff, yoff;
  339. struct rtgui_image_hdcmm *hdc;
  340. RT_ASSERT(image != RT_NULL && dc != RT_NULL && dst_rect != RT_NULL);
  341. /* this dc is not visible */
  342. if (rtgui_dc_get_visible(dc) != RT_TRUE)
  343. return;
  344. hdc = (struct rtgui_image_hdcmm *) image;
  345. if (!hdc->pixels)
  346. return;
  347. xoff = 0;
  348. if (dst_rect->x1 < 0)
  349. {
  350. xoff = -dst_rect->x1;
  351. dst_rect->x1 = 0;
  352. }
  353. yoff = 0;
  354. if (dst_rect->y1 < 0)
  355. {
  356. yoff = -dst_rect->y1;
  357. dst_rect->y1 = 0;
  358. }
  359. if (xoff >= image->w || yoff >= image->h)
  360. return;
  361. /* the minimum rect */
  362. w = _UI_MIN(image->w - xoff, rtgui_rect_width(*dst_rect));
  363. h = _UI_MIN(image->h - yoff, rtgui_rect_height(*dst_rect));
  364. /* get pixel pointer */
  365. ptr = hdc->pixels + hdc->pitch * yoff + hdc->byte_per_pixel * xoff;
  366. for (y = 0; y < h; y++)
  367. {
  368. dc->engine->blit_line(dc, dst_rect->x1, dst_rect->x1 + w, dst_rect->y1 + y, ptr);
  369. ptr += hdc->pitch;
  370. }
  371. }
  372. void rtgui_image_hdc_init()
  373. {
  374. /* register hdc on image system */
  375. rtgui_image_register_engine(&rtgui_image_hdc_engine);
  376. }