image_bmp.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306
  1. /*
  2. * Change Logs:
  3. * Date Author Notes
  4. * 2012-01-24 onelife Reimplement to improve efficiency and add
  5. * features. The new decoder uses configurable fixed size working buffer and
  6. * provides scaledown function.
  7. */
  8. #include <rtthread.h>
  9. #include <rtgui/dc_hw.h>
  10. #include <rtgui/image.h>
  11. #include <rtgui/rtgui_system.h>
  12. #include <rtgui/image_bmp.h>
  13. #include <rtgui/blit.h>
  14. #ifdef RTGUI_USING_DFS_FILERW
  15. #include <dfs_posix.h>
  16. #endif
  17. #ifdef RTGUI_IMAGE_BMP
  18. /* Compression encodings for BMP files */
  19. #ifndef BI_RGB
  20. #define BI_RGB 0
  21. #define BI_RLE8 1
  22. #define BI_RLE4 2
  23. #define BI_BITFIELDS 3
  24. #endif
  25. #define BMP_WORKING_BUFFER_SIZE (384) /* In multiple of 12 and bigger than 48 */
  26. #define BMP_MAX_SCALING_FACTOR (10) // TODO: find the max value!
  27. #define hw_driver (rtgui_graphic_driver_get_default())
  28. struct rtgui_image_bmp
  29. {
  30. rt_bool_t is_loaded;
  31. rt_uint8_t *pixels;
  32. struct rtgui_filerw *filerw;
  33. rt_uint32_t w, h;
  34. rt_uint32_t pixel_offset;
  35. rt_uint32_t pitch;
  36. rt_uint8_t scale;
  37. rt_uint8_t bit_per_pixel;
  38. rt_uint8_t pad;
  39. };
  40. static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw *file);
  41. static rt_bool_t rtgui_image_bmp_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load);
  42. static void rtgui_image_bmp_unload(struct rtgui_image *image);
  43. static void rtgui_image_bmp_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect);
  44. static struct rtgui_image *rtgui_image_bmp_zoom(struct rtgui_image *image,
  45. float scalew, float scaleh, rt_uint32_t mode);
  46. static struct rtgui_image *rtgui_image_bmp_rotate(struct rtgui_image *image, float angle);
  47. struct rtgui_image_engine rtgui_image_bmp_engine =
  48. {
  49. "bmp",
  50. { RT_NULL },
  51. rtgui_image_bmp_check,
  52. rtgui_image_bmp_load,
  53. rtgui_image_bmp_unload,
  54. rtgui_image_bmp_blit,
  55. rtgui_image_bmp_zoom,
  56. rtgui_image_bmp_rotate
  57. };
  58. static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw *file)
  59. {
  60. rt_uint8_t buffer[18];
  61. rt_bool_t is_bmp = RT_FALSE;
  62. do
  63. {
  64. if (!file)
  65. {
  66. break;
  67. }
  68. /* Prepare to decode */
  69. if (rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET) < 0)
  70. {
  71. break;
  72. }
  73. if (rtgui_filerw_read(file, (void *)buffer, 18, 1) != 18)
  74. {
  75. break;
  76. }
  77. /* Read file type */
  78. if (buffer[0] != 'B' || buffer[1] != 'M')
  79. {
  80. break;
  81. }
  82. /* Read BMP header size */
  83. if (*(rt_uint32_t *)&buffer[14] == 12)
  84. {
  85. /* Bitmap Header Version 2.x */
  86. if (rtgui_filerw_read(file, (void *)buffer, 8, 1) != 8)
  87. {
  88. break;
  89. }
  90. /* Read image size */
  91. is_bmp = RT_TRUE;
  92. }
  93. else
  94. {
  95. /* Bitmap Header Version bigger than 2.x */
  96. if (rtgui_filerw_read(file, (void *)buffer, 8, 1) != 8)
  97. {
  98. break;
  99. }
  100. /* Read image size */
  101. is_bmp = RT_TRUE;
  102. }
  103. }
  104. while (0);
  105. return is_bmp;
  106. }
  107. static struct rtgui_image_palette *rtgui_image_bmp_load_palette(
  108. struct rtgui_filerw *file,
  109. rt_uint32_t colorsUsed,
  110. rt_bool_t alpha)
  111. {
  112. /* Load the palette, if any */
  113. rt_uint32_t i;
  114. struct rtgui_image_palette *palette;
  115. palette = rtgui_image_palette_create(colorsUsed);
  116. if (palette == RT_NULL)
  117. {
  118. return RT_NULL;
  119. }
  120. if (alpha)
  121. {
  122. rt_uint8_t temp[4];
  123. for (i = 0; i < colorsUsed; i++)
  124. {
  125. if (rtgui_filerw_read(file, (void *)&temp, 1, 4) != 4)
  126. {
  127. rtgui_free(palette);
  128. return RT_NULL;
  129. }
  130. palette->colors[i] = RTGUI_ARGB(temp[3], temp[2], temp[1], temp[0]);
  131. }
  132. }
  133. else
  134. {
  135. rt_uint8_t temp[3];
  136. for (i = 0; i < colorsUsed; i++)
  137. {
  138. if (rtgui_filerw_read(file, (void *)&temp, 1, 3) != 3)
  139. {
  140. rtgui_free(palette);
  141. return RT_NULL;
  142. }
  143. palette->colors[i] = RTGUI_RGB(temp[2], temp[1], temp[0]);
  144. }
  145. }
  146. return palette;
  147. }
  148. static rt_bool_t rtgui_image_bmp_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
  149. {
  150. rt_uint8_t scale = 0;
  151. rt_uint8_t *wrkBuffer;
  152. struct rtgui_image_bmp *bmp;
  153. rt_uint32_t bmpHeaderSize;
  154. rt_uint32_t colorsUsed;
  155. if (scale > BMP_MAX_SCALING_FACTOR)
  156. {
  157. return RT_FALSE;
  158. }
  159. do
  160. {
  161. wrkBuffer = (rt_uint8_t *)rtgui_malloc(BMP_WORKING_BUFFER_SIZE);
  162. if (wrkBuffer == RT_NULL)
  163. {
  164. rt_kprintf("BMP err: no mem\n");
  165. break;
  166. }
  167. bmp = (struct rtgui_image_bmp *)rtgui_malloc(sizeof(struct rtgui_image_bmp));
  168. if (bmp == RT_NULL)
  169. {
  170. break;
  171. }
  172. /* Prepare to decode */
  173. if (rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET) < 0)
  174. {
  175. break;
  176. }
  177. if (rtgui_filerw_read(file, (void *)wrkBuffer, 18, 1) != 18)
  178. {
  179. break;
  180. }
  181. /* Read file type */
  182. if (wrkBuffer[0] != 'B' || wrkBuffer[1] != 'M')
  183. {
  184. break;
  185. }
  186. // rt_kprintf("BMP: format ok\n");
  187. /* Read pixel array offset */
  188. bmp->pixel_offset = *(rt_uint32_t *)&wrkBuffer[10];
  189. // rt_kprintf("BMP: bmp->pixel_offset %d\n", bmp->pixel_offset);
  190. /* Read BMP header size */
  191. bmpHeaderSize = *(rt_uint32_t *)&wrkBuffer[14];
  192. // rt_kprintf("BMP: bmpHeaderSize %d\n", bmpHeaderSize);
  193. colorsUsed = 0;
  194. if (bmpHeaderSize == 12)
  195. {
  196. /* Bitmap Header Version 2.x */
  197. if (rtgui_filerw_read(file, (void *)wrkBuffer, 8, 1) != 8)
  198. {
  199. break;
  200. }
  201. /* Read image size */
  202. bmp->w = (rt_uint32_t) * (rt_uint16_t *)&wrkBuffer[0];
  203. bmp->h = (rt_uint32_t) * (rt_uint16_t *)&wrkBuffer[2];
  204. /* Read bits per pixel */
  205. bmp->bit_per_pixel = (rt_uint8_t) * (rt_uint16_t *)&wrkBuffer[6];
  206. }
  207. else
  208. {
  209. /* Bitmap Header Version bigger than 2.x */
  210. rt_uint32_t compression;
  211. if (rtgui_filerw_read(file, (void *)wrkBuffer, 36, 1) != 36)
  212. {
  213. break;
  214. }
  215. /* Read image size */
  216. bmp->w = *(rt_uint32_t *)&wrkBuffer[0];
  217. bmp->h = *(rt_uint32_t *)&wrkBuffer[4];
  218. /* Read bits per pixel */
  219. bmp->bit_per_pixel = (rt_uint8_t) * (rt_uint16_t *)&wrkBuffer[10];
  220. if (bmp->bit_per_pixel > 32)
  221. {
  222. rt_kprintf("BMP err: unsupported format\n");
  223. break;
  224. }
  225. /* Read compression method */
  226. compression = *(rt_uint32_t *)&wrkBuffer[12];
  227. if (compression != BI_RGB && compression != BI_BITFIELDS)
  228. {
  229. rt_kprintf("BMP err: unsupported format\n");
  230. break;
  231. }
  232. /* Read number of colors */
  233. colorsUsed = *(rt_uint32_t *)&wrkBuffer[28];
  234. }
  235. if (!colorsUsed)
  236. {
  237. colorsUsed = 1 << bmp->bit_per_pixel;
  238. }
  239. /* Load palette */
  240. if (bmp->bit_per_pixel <= 8)
  241. {
  242. if (rtgui_filerw_seek(file, 14 + bmpHeaderSize, RTGUI_FILE_SEEK_SET) < 0)
  243. {
  244. break;
  245. }
  246. image->palette = rtgui_image_bmp_load_palette(file, colorsUsed,
  247. bmpHeaderSize > 12 ? RT_TRUE : RT_FALSE);
  248. if (image->palette == RT_NULL)
  249. {
  250. break;
  251. }
  252. }
  253. /* Set image information */
  254. bmp->is_loaded = RT_FALSE;
  255. bmp->scale = scale;
  256. if (bmp->bit_per_pixel == 1)
  257. {
  258. bmp->pitch = (bmp->w + 7) >> 3;
  259. }
  260. else if (bmp->bit_per_pixel == 4)
  261. {
  262. bmp->pitch = (bmp->w + 1) >> 1;
  263. }
  264. else
  265. {
  266. bmp->pitch = bmp->w * (bmp->bit_per_pixel >> 3);
  267. }
  268. bmp->pad = ((bmp->pitch % 4) ? (4 - (bmp->pitch % 4)) : 0);
  269. bmp->pixels = RT_NULL;
  270. bmp->filerw = file;
  271. image->w = (rt_uint16_t)bmp->w >> bmp->scale;
  272. image->h = (rt_uint16_t)bmp->h >> bmp->scale;
  273. image->engine = &rtgui_image_bmp_engine;
  274. image->data = bmp;
  275. /* Start to decode */
  276. if (load == RT_TRUE)
  277. {
  278. rt_bool_t error = RT_FALSE;
  279. rt_uint8_t *dst;
  280. rt_uint32_t imageWidth;
  281. rt_uint16_t readLength, readIndex, loadIndex;
  282. rt_uint8_t skipLength;
  283. rt_uint16_t y;
  284. rt_uint8_t bytePerPixel;
  285. rt_int8_t scale1, scale2;
  286. bytePerPixel = bmp->bit_per_pixel / 8;
  287. if (!bytePerPixel)
  288. {
  289. bytePerPixel = 1;
  290. }
  291. imageWidth = image->w * bytePerPixel; /* Scaled width in byte */
  292. bmp->pixels = rtgui_malloc(image->h * imageWidth);
  293. if (bmp->pixels == RT_NULL)
  294. {
  295. rt_kprintf("BMP err: no mem to load (%d)\n", image->h * imageWidth);
  296. break;
  297. }
  298. /* Read the pixels. Note that the bmp image is upside down */
  299. if (rtgui_filerw_seek(file, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
  300. {
  301. break;
  302. }
  303. if (bmp->bit_per_pixel == 1)
  304. {
  305. if (bmp->scale > 3)
  306. {
  307. scale1 = bmp->scale - 3;
  308. scale2 = 3;
  309. }
  310. else
  311. {
  312. scale1 = 0;
  313. scale2 = bmp->scale;
  314. }
  315. }
  316. else if (bmp->bit_per_pixel == 4)
  317. {
  318. if (bmp->scale > 1)
  319. {
  320. scale1 = bmp->scale - 1;
  321. scale2 = 1;
  322. }
  323. else
  324. {
  325. scale1 = 0;
  326. scale2 = bmp->scale;
  327. }
  328. }
  329. /* Process whole image */
  330. y = 0;
  331. while (y < image->h)
  332. {
  333. dst = bmp->pixels + (image->h - y - 1) * imageWidth;
  334. readIndex = 0;
  335. skipLength = 0;
  336. /* Process a line */
  337. while (readIndex < bmp->pitch)
  338. {
  339. /* Put progress indicator */
  340. rt_kprintf("\r%lu%%", y * 100UL / image->h);
  341. /* Read data to buffer */
  342. readLength = (BMP_WORKING_BUFFER_SIZE > ((rt_uint16_t)bmp->pitch - readIndex)) ? \
  343. ((rt_uint16_t)bmp->pitch - readIndex) : BMP_WORKING_BUFFER_SIZE;
  344. if (rtgui_filerw_read(file, (void *)wrkBuffer, 1, readLength) != readLength)
  345. {
  346. rt_kprintf("BMP err: read failed\n");
  347. error = RT_TRUE;
  348. break;
  349. }
  350. readIndex += readLength;
  351. /* Process read buffer */
  352. if (bmp->bit_per_pixel == 1)
  353. {
  354. rt_uint8_t j;
  355. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
  356. {
  357. for (j = 0; j < 8; j += 1 << scale2)
  358. {
  359. *(dst++) = (wrkBuffer[loadIndex] & (1 << (7 - j))) >> (7 - j);
  360. }
  361. }
  362. if (scale1 && (readLength % (1 << scale1)))
  363. {
  364. skipLength = (1 << scale1) - readLength % (1 << scale1);
  365. }
  366. }
  367. else if (bmp->bit_per_pixel == 4)
  368. {
  369. rt_uint8_t j;
  370. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
  371. {
  372. for (j = 0; j < 8; j += 1 << (2 + scale2))
  373. {
  374. *(dst++) = (wrkBuffer[loadIndex] & (0x0F << (4 - j))) >> (4 - j);
  375. }
  376. }
  377. if (scale1 && (readLength % (1 << scale1)))
  378. {
  379. skipLength = (1 << scale1) - readLength % (1 << scale1);
  380. }
  381. }
  382. else
  383. {
  384. if (bmp->scale == 0)
  385. {
  386. rt_memcpy((void *)dst, (void *)wrkBuffer, readLength);
  387. dst += readLength;
  388. }
  389. else
  390. {
  391. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += bytePerPixel << bmp->scale)
  392. {
  393. rt_memcpy((void *)dst, (void *)&wrkBuffer[loadIndex], bytePerPixel);
  394. dst += bytePerPixel;
  395. }
  396. if (readLength % (1 << bmp->scale))
  397. {
  398. skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
  399. }
  400. }
  401. }
  402. }
  403. if (error)
  404. {
  405. break;
  406. }
  407. y++;
  408. /* Skip padding bytes */
  409. if (bmp->pad)
  410. {
  411. if (rtgui_filerw_seek(file, bmp->pad, RTGUI_FILE_SEEK_CUR) < 0)
  412. {
  413. error = RT_TRUE;
  414. break;
  415. }
  416. }
  417. /* Height scale down */
  418. if (bmp->scale)
  419. {
  420. if (rtgui_filerw_seek(file, (bmp->pitch + bmp->pad) * ((1 << bmp->scale) - 1),
  421. RTGUI_FILE_SEEK_CUR) < 0)
  422. {
  423. error = RT_TRUE;
  424. break;
  425. }
  426. }
  427. }
  428. if (error)
  429. {
  430. break;
  431. }
  432. /* Close file */
  433. rtgui_filerw_close(bmp->filerw);
  434. bmp->filerw = RT_NULL;
  435. bmp->is_loaded = RT_TRUE;
  436. // rt_kprintf("BMP: load to RAM\n");
  437. }
  438. /* Release memory */
  439. rtgui_free(wrkBuffer);
  440. return RT_TRUE;
  441. }
  442. while (0);
  443. /* Release memory */
  444. rtgui_free(wrkBuffer);
  445. rtgui_free(image->palette);
  446. rtgui_free(bmp->pixels);
  447. rtgui_free(bmp);
  448. return RT_FALSE;
  449. }
  450. static void rtgui_image_bmp_unload(struct rtgui_image *image)
  451. {
  452. struct rtgui_image_bmp *bmp;
  453. if (image != RT_NULL)
  454. {
  455. bmp = (struct rtgui_image_bmp *)image->data;
  456. /* Release memory */
  457. rtgui_free(bmp->pixels);
  458. if (bmp->filerw != RT_NULL)
  459. {
  460. /* Close file */
  461. rtgui_filerw_close(bmp->filerw);
  462. bmp->filerw = RT_NULL;
  463. }
  464. rtgui_free(bmp);
  465. }
  466. }
  467. static void rtgui_image_bmp_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *dst_rect)
  468. {
  469. rt_uint16_t w, h;
  470. struct rtgui_image_bmp *bmp;
  471. rt_uint8_t bytePerPixel;
  472. rt_uint32_t imageWidth;
  473. rt_bool_t error;
  474. bmp = (struct rtgui_image_bmp *)image->data;
  475. RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL || bmp != RT_NULL);
  476. bytePerPixel = bmp->bit_per_pixel / 8;
  477. if (!bytePerPixel)
  478. {
  479. bytePerPixel = 1;
  480. }
  481. imageWidth = image->w * bytePerPixel; /* Scaled width in byte */
  482. error = RT_FALSE;
  483. do
  484. {
  485. /* this dc is not visible */
  486. if (rtgui_dc_get_visible(dc) != RT_TRUE)
  487. {
  488. break;
  489. }
  490. /* the minimum rect */
  491. if (image->w < rtgui_rect_width(*dst_rect))
  492. {
  493. w = image->w;
  494. }
  495. else
  496. {
  497. w = rtgui_rect_width(*dst_rect);
  498. }
  499. if (image->h < rtgui_rect_height(*dst_rect))
  500. {
  501. h = image->h;
  502. }
  503. else
  504. {
  505. h = rtgui_rect_height(*dst_rect);
  506. }
  507. if (!bmp->is_loaded)
  508. {
  509. rt_uint8_t *wrkBuffer;
  510. rt_uint16_t readLength, readIndex, loadIndex;
  511. rt_uint8_t skipLength;
  512. rt_uint16_t x, y;
  513. rt_int8_t scale1, scale2;
  514. rt_uint16_t y_start = dst_rect->y1 + h - 1;
  515. /* Read the pixels. Note that the bmp image is upside down */
  516. if (rtgui_filerw_seek(bmp->filerw, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
  517. {
  518. break;
  519. }
  520. /* the image is upside down. So we need to start from middle if the
  521. * image is higher than the dst_rect. */
  522. if (image->h > rtgui_rect_height(*dst_rect))
  523. {
  524. int hdelta = image->h - rtgui_rect_height(*dst_rect);
  525. if (rtgui_filerw_seek(bmp->filerw, hdelta * (bmp->pitch + bmp->pad) * (1 << bmp->scale),
  526. RTGUI_FILE_SEEK_CUR) < 0)
  527. {
  528. error = RT_TRUE;
  529. break;
  530. }
  531. }
  532. if (bmp->bit_per_pixel == 1)
  533. {
  534. if (bmp->scale > 3)
  535. {
  536. scale1 = bmp->scale - 3;
  537. scale2 = 3;
  538. }
  539. else
  540. {
  541. scale1 = 0;
  542. scale2 = bmp->scale;
  543. }
  544. }
  545. else if (bmp->bit_per_pixel == 4)
  546. {
  547. if (bmp->scale > 1)
  548. {
  549. scale1 = bmp->scale - 1;
  550. scale2 = 1;
  551. }
  552. else
  553. {
  554. scale1 = 0;
  555. scale2 = bmp->scale;
  556. }
  557. }
  558. wrkBuffer = (rt_uint8_t *)rtgui_malloc(
  559. (BMP_WORKING_BUFFER_SIZE > bmp->pitch) ? \
  560. bmp->pitch : BMP_WORKING_BUFFER_SIZE);
  561. if (wrkBuffer == RT_NULL)
  562. {
  563. rt_kprintf("BMP err: no mem (%d)\n", BMP_WORKING_BUFFER_SIZE);
  564. break;
  565. }
  566. /* Process whole image */
  567. y = 0;
  568. while (y < h)
  569. {
  570. x = 0;
  571. readIndex = 0;
  572. skipLength = 0;
  573. /* Process a line */
  574. while (readIndex < bmp->pitch)
  575. {
  576. /* Put progress indicator */
  577. rt_kprintf("\r%lu%%", y * 100UL / h);
  578. /* Read data to buffer */
  579. readLength = (BMP_WORKING_BUFFER_SIZE > ((rt_uint16_t)bmp->pitch - readIndex)) ? \
  580. ((rt_uint16_t)bmp->pitch - readIndex) : BMP_WORKING_BUFFER_SIZE;
  581. if (rtgui_filerw_read(bmp->filerw, (void *)wrkBuffer, 1, readLength) != readLength)
  582. {
  583. rt_kprintf("BMP err: read failed\n");
  584. error = RT_TRUE;
  585. break;
  586. }
  587. readIndex += readLength;
  588. /* Process read buffer */
  589. if (bmp->bit_per_pixel == 1)
  590. {
  591. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
  592. {
  593. rt_uint8_t j;
  594. for (j = 0; j < 8; j += 1 << scale2)
  595. {
  596. rtgui_color_t color;
  597. color = image->palette->colors[(wrkBuffer[loadIndex] & (1 << (7 - j))) >> (7 - j)];
  598. rtgui_dc_draw_color_point(dc,
  599. dst_rect->x1 + x++,
  600. y_start - y,
  601. color);
  602. if (x >= w)
  603. break;
  604. }
  605. if (scale1 && (readLength % (1 << scale1)))
  606. {
  607. skipLength = (1 << scale1) - readLength % (1 << scale1);
  608. }
  609. }
  610. }
  611. else if (bmp->bit_per_pixel == 4)
  612. {
  613. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
  614. {
  615. rt_uint8_t j;
  616. for (j = 0; j < 8; j += 1 << (2 + scale2))
  617. {
  618. rtgui_color_t color;
  619. color = image->palette->colors[(wrkBuffer[loadIndex] & (0x0F << (4 - j))) >> (4 - j)];
  620. rtgui_dc_draw_color_point(dc,
  621. dst_rect->x1 + x++,
  622. y_start - y,
  623. color);
  624. if (x >= w)
  625. break;
  626. }
  627. }
  628. if (scale1 && (readLength % (1 << scale1)))
  629. {
  630. skipLength = (1 << scale1) - readLength % (1 << scale1);
  631. }
  632. }
  633. else if (bmp->bit_per_pixel == 8)
  634. {
  635. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << bmp->scale)
  636. {
  637. rtgui_color_t color;
  638. color = image->palette->colors[wrkBuffer[loadIndex]];
  639. rtgui_dc_draw_color_point(dc,
  640. dst_rect->x1 + x++,
  641. y_start - y,
  642. color);
  643. if (x >= w)
  644. break;
  645. }
  646. if (readLength % (1 << bmp->scale))
  647. {
  648. skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
  649. }
  650. }
  651. else
  652. {
  653. rtgui_blit_line_func blit_line;
  654. rt_uint8_t hw_bytePerPixel = hw_driver->bits_per_pixel / 8;
  655. rt_uint8_t temp[4] = {0};
  656. if (!hw_bytePerPixel)
  657. {
  658. hw_bytePerPixel = 1;
  659. }
  660. if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
  661. {
  662. blit_line = rtgui_blit_line_get_inv(hw_bytePerPixel, bytePerPixel);
  663. }
  664. else
  665. {
  666. blit_line = rtgui_blit_line_get(hw_bytePerPixel, bytePerPixel);
  667. }
  668. for (loadIndex = skipLength;
  669. loadIndex < readLength;
  670. loadIndex += bytePerPixel << bmp->scale)
  671. {
  672. blit_line(temp, &wrkBuffer[loadIndex], bytePerPixel);
  673. dc->engine->blit_line(dc,
  674. dst_rect->x1 + x, dst_rect->x1 + x + 1,
  675. y_start - y,
  676. temp);
  677. x++;
  678. if (x >= w)
  679. break;
  680. }
  681. if (readLength % (1 << bmp->scale))
  682. {
  683. skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
  684. }
  685. }
  686. }
  687. if (error)
  688. {
  689. break;
  690. }
  691. y++;
  692. /* Skip padding bytes */
  693. if (bmp->pad)
  694. {
  695. if (rtgui_filerw_seek(bmp->filerw, bmp->pad, RTGUI_FILE_SEEK_CUR) < 0)
  696. {
  697. error = RT_TRUE;
  698. break;
  699. }
  700. }
  701. /* Height scale down */
  702. if (bmp->scale)
  703. {
  704. if (rtgui_filerw_seek(bmp->filerw, (bmp->pitch + bmp->pad) * ((1 << bmp->scale) - 1),
  705. RTGUI_FILE_SEEK_CUR) < 0)
  706. {
  707. error = RT_TRUE;
  708. break;
  709. }
  710. }
  711. }
  712. if (error)
  713. {
  714. break;
  715. }
  716. /* Release memory */
  717. rtgui_free(wrkBuffer);
  718. // rt_kprintf("BMP: load to display\n");
  719. }
  720. else
  721. {
  722. rt_uint16_t x, y;
  723. rt_uint8_t *ptr;
  724. for (y = 0; y < h; y ++)
  725. {
  726. ptr = bmp->pixels + (y * imageWidth);
  727. if (bmp->bit_per_pixel <= 8)
  728. {
  729. rtgui_color_t color;
  730. /* Using palette */
  731. for (x = 0; x < w; x ++)
  732. {
  733. color = image->palette->colors[*(ptr++)];
  734. rtgui_dc_draw_color_point(dc,
  735. dst_rect->x1 + x,
  736. dst_rect->y1 + y,
  737. color);
  738. }
  739. }
  740. else
  741. {
  742. rtgui_blit_line_func blit_line;
  743. rt_uint8_t hw_bytePerPixel = hw_driver->bits_per_pixel / 8;
  744. rt_uint8_t temp[4] = {0};
  745. if (!hw_bytePerPixel)
  746. {
  747. hw_bytePerPixel = 1;
  748. }
  749. if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
  750. {
  751. blit_line = rtgui_blit_line_get_inv(hw_bytePerPixel, bytePerPixel);
  752. }
  753. else
  754. {
  755. blit_line = rtgui_blit_line_get(hw_bytePerPixel, bytePerPixel);
  756. }
  757. for (x = 0; x < w; x ++)
  758. {
  759. blit_line(temp, ptr, bytePerPixel);
  760. ptr += bytePerPixel;
  761. dc->engine->blit_line(dc,
  762. dst_rect->x1 + x, dst_rect->x1 + x + 1,
  763. dst_rect->y1 + y,
  764. temp);
  765. }
  766. }
  767. }
  768. }
  769. // rt_kprintf("BMP: blit ok\n");
  770. }
  771. while (0);
  772. }
  773. /*
  774. * config bitmap header.
  775. */
  776. void rtgui_image_bmp_header_cfg(struct rtgui_image_bmp_header *bhr, rt_int32_t w, rt_int32_t h, rt_uint16_t bits_per_pixel)
  777. {
  778. int image_size = w * h * bits_per_pixel / 8;
  779. int header_size = sizeof(struct rtgui_image_bmp_header);
  780. bhr->bfType = 0x4d42; /* BM */
  781. bhr->bfSize = header_size + image_size; /* data size */
  782. bhr->bfReserved1 = 0;
  783. bhr->bfReserved2 = 0;
  784. bhr->bfOffBits = header_size;
  785. bhr->biSize = 40; /* sizeof BITMAPINFOHEADER */
  786. bhr->biWidth = w;
  787. bhr->biHeight = h;
  788. bhr->biPlanes = 1;
  789. bhr->biBitCount = bits_per_pixel;
  790. bhr->biCompression = BI_BITFIELDS;
  791. bhr->biSizeImage = image_size;
  792. bhr->biXPelsPerMeter = 0;
  793. bhr->biYPelsPerMeter = 0;
  794. bhr->biClrUsed = 0;
  795. bhr->biClrImportant = 0;
  796. if (bhr->biBitCount == 16 && bhr->biCompression == BI_BITFIELDS)
  797. {
  798. bhr->bfSize += 12;
  799. bhr->bfOffBits += 12;
  800. }
  801. }
  802. #ifdef RTGUI_USING_DFS_FILERW
  803. #define WRITE_CLUSTER_SIZE 2048
  804. void bmp_align_write(struct rtgui_filerw *file, char *dest, char *src, rt_int32_t len, rt_int32_t *count)
  805. {
  806. rt_int32_t len_bak = len;
  807. while (len)
  808. {
  809. if (*count >= WRITE_CLUSTER_SIZE)
  810. {
  811. rtgui_filerw_write(file, dest, WRITE_CLUSTER_SIZE, 1);
  812. *count = 0;
  813. }
  814. *(dest + *count) = *(src + (len_bak - len));
  815. len --;
  816. (*count) ++;
  817. }
  818. }
  819. /*
  820. * Grab screen and save as a BMP file
  821. * MACRO RGB_CONVERT_TO_BGR: If the pixel of colors is BGR mode, defined it.
  822. */
  823. void screenshot(const char *filename)
  824. {
  825. struct rtgui_filerw *file;
  826. int w, h, i, pitch;
  827. rt_uint16_t *src;
  828. rt_uint32_t mask;
  829. struct rtgui_image_bmp_header bhr;
  830. struct rtgui_graphic_driver *grp = hw_driver;
  831. #ifdef RGB_CONVERT_TO_BGR
  832. int j;
  833. rt_uint16_t *line_buf;
  834. rt_uint16_t color, tmp;
  835. #endif
  836. char *pixel_buf;
  837. rt_int32_t write_count = 0;
  838. file = rtgui_filerw_create_file(filename, "wb");
  839. if (file == RT_NULL)
  840. {
  841. rt_kprintf("create file failed\n");
  842. return;
  843. }
  844. w = grp->width;
  845. h = grp->height;
  846. pitch = w * sizeof(rt_uint16_t);
  847. #ifdef RGB_CONVERT_TO_BGR
  848. line_buf = rt_malloc(pitch);
  849. if (line_buf == RT_NULL)
  850. {
  851. rt_kprintf("no memory!\n");
  852. return;
  853. }
  854. #endif
  855. pixel_buf = rt_malloc(WRITE_CLUSTER_SIZE);
  856. if (pixel_buf == RT_NULL)
  857. {
  858. rt_kprintf("no memory!\n");
  859. #ifdef RGB_CONVERT_TO_BGR
  860. rt_free(line_buf);
  861. #endif
  862. return;
  863. }
  864. rtgui_image_bmp_header_cfg(&bhr, w, h, grp->bits_per_pixel);
  865. bmp_align_write(file, pixel_buf, (char *)&bhr,
  866. sizeof(struct rtgui_image_bmp_header), &write_count);
  867. if (bhr.biCompression == BI_BITFIELDS)
  868. {
  869. mask = 0xF800; /* Red Mask */
  870. bmp_align_write(file, pixel_buf, (char *)&mask, 4, &write_count);
  871. mask = 0x07E0; /* Green Mask */
  872. bmp_align_write(file, pixel_buf, (char *)&mask, 4, &write_count);
  873. mask = 0x001F; /* Blue Mask */
  874. bmp_align_write(file, pixel_buf, (char *)&mask, 4, &write_count);
  875. }
  876. rtgui_screen_lock(RT_WAITING_FOREVER);
  877. if (grp->framebuffer != RT_NULL)
  878. {
  879. src = (rt_uint16_t *)grp->framebuffer;
  880. src += w * h;
  881. for (i = 0; i < h; i++)
  882. {
  883. src -= w;
  884. #ifdef RGB_CONVERT_TO_BGR
  885. for (j = 0; j < w; j++)
  886. {
  887. tmp = *(src + j);
  888. color = (tmp & 0x001F) << 11;
  889. color += (tmp & 0x07E0);
  890. color += (tmp & 0xF800) >> 11;
  891. *(line_buf + i) = color;
  892. }
  893. bmp_align_write(file, pixel_buf, (char *)line_buf, pitch, &write_count);
  894. #else
  895. bmp_align_write(file, pixel_buf, (char *)src, pitch, &write_count);
  896. #endif
  897. }
  898. }
  899. else
  900. {
  901. rtgui_color_t pixel_color;
  902. rt_uint16_t write_color;
  903. int x;
  904. for (i = h - 1; i >= 0; i--)
  905. {
  906. x = 0;
  907. if (i % 10 == 0)rt_kprintf(">", i);
  908. while (x < w)
  909. {
  910. grp->ops->get_pixel(&pixel_color, x, i);
  911. write_color = rtgui_color_to_565p(pixel_color);
  912. bmp_align_write(file, pixel_buf, (char *)&write_color,
  913. sizeof(rt_uint16_t), &write_count);
  914. x++;
  915. }
  916. }
  917. }
  918. /* write The tail of the last */
  919. if (write_count < WRITE_CLUSTER_SIZE)
  920. rtgui_filerw_write(file, pixel_buf, write_count, 1);
  921. rtgui_screen_unlock();
  922. #ifdef RGB_CONVERT_TO_BGR
  923. rt_free(line_buf);
  924. #endif
  925. rt_free(pixel_buf);
  926. rt_kprintf("bmp create succeed.\n");
  927. rtgui_filerw_close(file);
  928. }
  929. #ifdef RT_USING_FINSH
  930. #include <finsh.h>
  931. FINSH_FUNCTION_EXPORT(screenshot, usage: screenshot(filename));
  932. #endif
  933. #endif
  934. /*
  935. * image zoom in, zoom out interface
  936. * Support 16/24 bits format image
  937. */
  938. static struct rtgui_image *rtgui_image_bmp_zoom(struct rtgui_image *image,
  939. float scalew, float scaleh, rt_uint32_t mode)
  940. {
  941. struct rtgui_image *d_img;
  942. struct rtgui_image_bmp *bmp, *d_bmp;
  943. int bitcount, nbytes, i, j;
  944. int sw, sh, dw, dh;
  945. int dest_buff_size;
  946. int src_line_size, dest_line_size;
  947. char *src_buf;
  948. char *des_buf;
  949. bmp = (struct rtgui_image_bmp *)image->data;
  950. src_buf = bmp->pixels;
  951. sw = bmp->w;
  952. sh = bmp->h;
  953. bitcount = bmp->bit_per_pixel;
  954. if (bitcount != 16 && bitcount != 24)
  955. {
  956. rt_kprintf("Does not support %d bits format\n", bitcount);
  957. return RT_NULL;
  958. }
  959. nbytes = bitcount / 8;
  960. src_line_size = sw *nbytes;
  961. dw = (int)(sw / scalew);
  962. dh = (int)(sh / scaleh);
  963. d_img = rt_malloc(sizeof(struct rtgui_image));
  964. if (d_img == RT_NULL)
  965. {
  966. rt_kprintf("Not enough memory allocation IMG!\n");
  967. return RT_NULL;
  968. }
  969. d_img->w = dw;
  970. d_img->h = dh;
  971. d_img->engine = &rtgui_image_bmp_engine;
  972. d_img->palette = RT_NULL;
  973. /* config dest bmp data */
  974. dest_line_size = ((dw * bitcount + (bitcount - 1)) / bitcount) *nbytes;
  975. dest_buff_size = dest_line_size *dh;
  976. d_bmp = rt_malloc(sizeof(struct rtgui_image_bmp));
  977. if (d_bmp == RT_NULL)
  978. {
  979. rt_free(d_img);
  980. rt_kprintf("Not enough memory allocation BMP!\n");
  981. return RT_NULL;
  982. }
  983. d_bmp->w = dw;
  984. d_bmp->h = dh;
  985. d_bmp->bit_per_pixel = bitcount;
  986. d_bmp->pixel_offset = 54; /* insignificant parameter */
  987. d_bmp->filerw = RT_NULL;
  988. d_bmp->is_loaded = RT_TRUE; /* Don't want to loading */
  989. d_bmp->pitch = d_bmp->w *nbytes;
  990. d_bmp->pad = ((d_bmp->pitch % 4) ? (4 - (d_bmp->pitch % 4)) : 0);
  991. d_bmp->scale = 0;
  992. d_bmp->pixels = rt_malloc(dest_buff_size);
  993. if (d_bmp->pixels == RT_NULL)
  994. {
  995. rt_free(d_img);
  996. rt_free(d_bmp);
  997. rt_kprintf("Not enough memory allocation BMP data!\n");
  998. return RT_NULL;
  999. }
  1000. des_buf = d_bmp->pixels;
  1001. if (mode == RTGUI_IMG_ZOOM_NEAREST)
  1002. {
  1003. for (i = 0; i < dh; i++)
  1004. {
  1005. int src_th = (int)(scaleh * i + 0.5);
  1006. for (j = 0; j < dw; j++)
  1007. {
  1008. int src_tw = (int)(scalew * j + 0.5);
  1009. rt_memcpy(&des_buf[i * dest_line_size] + j * nbytes,
  1010. &src_buf[src_th * src_line_size] + src_tw * nbytes,
  1011. nbytes);
  1012. }
  1013. }
  1014. }
  1015. else if (mode == RTGUI_IMG_ZOOM_BILINEAR)
  1016. {
  1017. /*
  1018. ** known: (i,j), (i+1,j), (i,j+1), (i+1,j+1), u, v
  1019. ** float coord: (i+u, j+v)
  1020. ** f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
  1021. */
  1022. for (i = 0; i < dh; i++)
  1023. {
  1024. int y = (int)(scaleh * i);
  1025. float u = (float)(scaleh * i - y);
  1026. unsigned char c1, c2, c3, c4;
  1027. for (j = 0; j < dw; j++)
  1028. {
  1029. int x = (int)(scalew * j);
  1030. float v = (float)(scalew * j - x);
  1031. if (bitcount == 16)
  1032. {
  1033. /* Each color component is calculated separately */
  1034. rt_uint32_t cc1, cc2, cc3, cc4;
  1035. unsigned char r, g, b;
  1036. cc1 = rtgui_color_from_565p(*(rt_uint16_t *)(src_buf +
  1037. src_line_size * y + nbytes * x));
  1038. cc2 = rtgui_color_from_565p(*(rt_uint16_t *)(src_buf +
  1039. src_line_size * y + nbytes * (x + 1)));
  1040. cc3 = rtgui_color_from_565p(*(rt_uint16_t *)(src_buf +
  1041. src_line_size * (y + 1) + nbytes * x));
  1042. cc4 = rtgui_color_from_565p(*(rt_uint16_t *)(src_buf +
  1043. src_line_size * (y + 1) + nbytes * (x + 1)));
  1044. r = (unsigned char)((1 - u) * (1 - v) * (float)RTGUI_RGB_R(cc1) +
  1045. (1 - u) * v * (float)RTGUI_RGB_R(cc2) + u * (1 - v) * (float)RTGUI_RGB_R(cc3) +
  1046. u * v * (float)RTGUI_RGB_R(cc4));
  1047. g = (unsigned char)((1 - u) * (1 - v) * (float)RTGUI_RGB_G(cc1) +
  1048. (1 - u) * v * (float)RTGUI_RGB_G(cc2) + u * (1 - v) * (float)RTGUI_RGB_G(cc3) +
  1049. u * v * (float)RTGUI_RGB_G(cc4));
  1050. b = (unsigned char)((1 - u) * (1 - v) * (float)RTGUI_RGB_B(cc1) +
  1051. (1 - u) * v * (float)RTGUI_RGB_B(cc2) + u * (1 - v) * (float)RTGUI_RGB_B(cc3) +
  1052. u * v * (float)RTGUI_RGB_B(cc4));
  1053. *(rt_uint16_t *)(des_buf + i * dest_line_size + j * nbytes) =
  1054. rtgui_color_to_565p(RTGUI_RGB(r, g, b));
  1055. }
  1056. else if (bitcount == 24)
  1057. {
  1058. int k;
  1059. for (k = 0; k < 3; k++)
  1060. {
  1061. /* 24 bits color is 3 bytes R:G:B */
  1062. c1 = (src_buf[src_line_size * y + nbytes * x + k]);
  1063. c2 = (src_buf[src_line_size * y + nbytes * (x + 1) + k]);
  1064. c3 = (src_buf[src_line_size * (y + 1) + nbytes * x + k]);
  1065. c4 = (src_buf[src_line_size * (y + 1) + nbytes * (x + 1) + k]);
  1066. des_buf[i * dest_line_size + j * nbytes + k] = (unsigned char)
  1067. ((1 - u) * (1 - v) * (float)c1 + (1 - u) * v * (float)c2 + u * (1 - v) * (float)c3 + u * v * (float)c4);
  1068. }
  1069. }
  1070. }
  1071. }
  1072. }
  1073. d_img->data = d_bmp;
  1074. return d_img;
  1075. }
  1076. #include <math.h>
  1077. #ifndef M_PI
  1078. #define M_PI 3.14159265358979323846
  1079. #endif
  1080. /*
  1081. * around a pos o, rotating pos p
  1082. */
  1083. rt_inline rtgui_point_t _rotate_pos(rtgui_point_t o, rtgui_point_t p, float sina, float cosa)
  1084. {
  1085. rtgui_point_t rp;
  1086. float dx, dy;
  1087. dx = p.x - o.x;
  1088. dy = p.y - o.y;
  1089. rp.x = (float)o.x + dx * cosa + dy * sina;
  1090. rp.y = (float)o.y + dy * cosa - dx * sina;
  1091. return rp;
  1092. }
  1093. /*
  1094. * image rotate interface, rotate direction: clockwise
  1095. * Support 16/24 bits format image
  1096. */
  1097. static struct rtgui_image *rtgui_image_bmp_rotate(struct rtgui_image *image, float angle)
  1098. {
  1099. float age, sina, cosa;
  1100. rtgui_point_t o, p, cp;
  1101. rtgui_rect_t rect;
  1102. struct rtgui_image *d_img;
  1103. struct rtgui_image_bmp *bmp, *d_bmp;
  1104. int bitcount, nbytes, i, j;
  1105. int sw, sh, dw, dh;
  1106. int dest_buff_size;
  1107. int src_line_size, dest_line_size;
  1108. char *src_buf;
  1109. char *des_buf;
  1110. /* rt_tick_t tick = rt_tick_get(); */
  1111. bmp = (struct rtgui_image_bmp *)image->data;
  1112. src_buf = bmp->pixels;
  1113. sw = bmp->w;
  1114. sh = bmp->h;
  1115. bitcount = bmp->bit_per_pixel;
  1116. if (bitcount != 16 && bitcount != 24)
  1117. {
  1118. rt_kprintf("Does not support %d bits format\n", bitcount);
  1119. return RT_NULL;
  1120. }
  1121. nbytes = bitcount / 8;
  1122. src_line_size = sw *nbytes;
  1123. /* convert angle to radians */
  1124. age = angle *M_PI / 180.0;
  1125. sina = sin(age);
  1126. cosa = cos(age);
  1127. /*
  1128. ** known: a, b, angle;
  1129. ** solve: aa = a*abs(cos(angle)) + b*abs(sin(angle));
  1130. ** solve: bb = b*abs(cos(angle)) + a*abs(sin(angle));
  1131. */
  1132. dw = (int)(sw *fabs(cosa) + sh *fabs(sina));
  1133. dh = (int)(sh *fabs(cosa) + sw *fabs(sina));
  1134. rect.x1 = rect.y1 = 0;
  1135. rect.x2 = sw;
  1136. rect.y2 = sh;
  1137. d_img = rt_malloc(sizeof(struct rtgui_image));
  1138. if (d_img == RT_NULL)
  1139. {
  1140. rt_kprintf("Not enough memory allocation IMG!\n");
  1141. return RT_NULL;
  1142. }
  1143. d_img->w = dw;
  1144. d_img->h = dh;
  1145. d_img->engine = &rtgui_image_bmp_engine;
  1146. d_img->palette = RT_NULL;
  1147. /* config dest bmp data */
  1148. dest_line_size = ((dw * bitcount + (bitcount - 1)) / bitcount) *nbytes;
  1149. dest_buff_size = dest_line_size *dh;
  1150. d_bmp = rt_malloc(sizeof(struct rtgui_image_bmp));
  1151. if (d_bmp == RT_NULL)
  1152. {
  1153. rt_free(d_img);
  1154. rt_kprintf("Not enough memory allocation BMP!\n");
  1155. return RT_NULL;
  1156. }
  1157. d_bmp->w = dw;
  1158. d_bmp->h = dh;
  1159. d_bmp->bit_per_pixel = bitcount;
  1160. d_bmp->pixel_offset = 54; /* insignificant parameter */
  1161. d_bmp->filerw = RT_NULL;
  1162. d_bmp->is_loaded = RT_TRUE; /* Don't want to loading */
  1163. d_bmp->pitch = d_bmp->w *nbytes;
  1164. d_bmp->pad = ((d_bmp->pitch % 4) ? (4 - (d_bmp->pitch % 4)) : 0);
  1165. d_bmp->scale = 0;
  1166. d_bmp->pixels = rt_malloc(dest_buff_size);
  1167. if (d_bmp->pixels == RT_NULL)
  1168. {
  1169. rt_free(d_img);
  1170. rt_free(d_bmp);
  1171. rt_kprintf("Not enough memory allocation BMP data!\n");
  1172. return RT_NULL;
  1173. }
  1174. des_buf = d_bmp->pixels;
  1175. /* use white fill empty pixel */
  1176. rt_memset(des_buf, 0xFF, dest_buff_size);
  1177. o.x = dw >> 1;
  1178. o.y = dh >> 1;
  1179. if (bitcount == 16 || bitcount == 24)
  1180. {
  1181. for (i = 0; i < dh; i++)
  1182. {
  1183. for (j = 0; j < dw; j++)
  1184. {
  1185. p.x = j;
  1186. p.y = i;
  1187. cp = _rotate_pos(o, p, sina, cosa);
  1188. cp.x -= (dw - sw) >> 1;
  1189. cp.y -= (dh - sh) >> 1;
  1190. if (rtgui_rect_contains_point(&rect, cp.x, cp.y) != RT_EOK)
  1191. continue;
  1192. rt_memcpy(&des_buf[dest_line_size * i] + nbytes * j,
  1193. &src_buf[src_line_size * cp.y] + nbytes * cp.x, nbytes);
  1194. }
  1195. }
  1196. }
  1197. d_img->data = d_bmp;
  1198. /* rt_kprintf("rotate use %d ticks\n", rt_tick_get()-tick); */
  1199. return d_img;
  1200. }
  1201. void rtgui_image_bmp_init()
  1202. {
  1203. /* register bmp on image system */
  1204. rtgui_image_register_engine(&rtgui_image_bmp_engine);
  1205. }
  1206. #endif