image_bmp.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  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. struct rtgui_image_engine rtgui_image_bmp_engine =
  45. {
  46. "bmp",
  47. { RT_NULL },
  48. rtgui_image_bmp_check,
  49. rtgui_image_bmp_load,
  50. rtgui_image_bmp_unload,
  51. rtgui_image_bmp_blit
  52. };
  53. static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw *file)
  54. {
  55. rt_uint8_t buffer[18];
  56. rt_bool_t is_bmp = RT_FALSE;
  57. do
  58. {
  59. if (!file)
  60. {
  61. break;
  62. }
  63. /* Prepare to decode */
  64. if (rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET) < 0)
  65. {
  66. break;
  67. }
  68. if (rtgui_filerw_read(file, (void *)buffer, 18, 1) != 18)
  69. {
  70. break;
  71. }
  72. /* Read file type */
  73. if (buffer[0] != 'B' || buffer[1] != 'M')
  74. {
  75. break;
  76. }
  77. /* Read BMP header size */
  78. if (*(rt_uint32_t *)&buffer[14] == 12)
  79. {
  80. /* Bitmap Header Version 2.x */
  81. if (rtgui_filerw_read(file, (void *)buffer, 8, 1) != 8)
  82. {
  83. break;
  84. }
  85. /* Read image size */
  86. is_bmp = RT_TRUE;
  87. }
  88. else
  89. {
  90. /* Bitmap Header Version bigger than 2.x */
  91. if (rtgui_filerw_read(file, (void *)buffer, 8, 1) != 8)
  92. {
  93. break;
  94. }
  95. /* Read image size */
  96. is_bmp = RT_TRUE;
  97. }
  98. }
  99. while (0);
  100. return is_bmp;
  101. }
  102. static struct rtgui_image_palette *rtgui_image_bmp_load_palette(
  103. struct rtgui_filerw *file,
  104. rt_uint32_t colorsUsed,
  105. rt_bool_t alpha)
  106. {
  107. /* Load the palette, if any */
  108. rt_uint32_t i;
  109. struct rtgui_image_palette *palette;
  110. palette = rtgui_image_palette_create(colorsUsed);
  111. if (palette == RT_NULL)
  112. {
  113. return RT_NULL;
  114. }
  115. if (alpha)
  116. {
  117. rt_uint8_t temp[4];
  118. for (i = 0; i < colorsUsed; i++)
  119. {
  120. if (rtgui_filerw_read(file, (void *)&temp, 1, 4) != 4)
  121. {
  122. rtgui_free(palette);
  123. return RT_NULL;
  124. }
  125. palette->colors[i] = RTGUI_ARGB(temp[3], temp[2], temp[1], temp[0]);
  126. }
  127. }
  128. else
  129. {
  130. rt_uint8_t temp[3];
  131. for (i = 0; i < colorsUsed; i++)
  132. {
  133. if (rtgui_filerw_read(file, (void *)&temp, 1, 3) != 3)
  134. {
  135. rtgui_free(palette);
  136. return RT_NULL;
  137. }
  138. palette->colors[i] = RTGUI_RGB(temp[2], temp[1], temp[0]);
  139. }
  140. }
  141. return palette;
  142. }
  143. static rt_bool_t rtgui_image_bmp_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
  144. {
  145. rt_uint8_t scale = 0;
  146. rt_uint8_t *wrkBuffer;
  147. struct rtgui_image_bmp *bmp;
  148. rt_uint32_t bmpHeaderSize;
  149. rt_uint32_t colorsUsed;
  150. if (scale > BMP_MAX_SCALING_FACTOR)
  151. {
  152. return RT_FALSE;
  153. }
  154. do
  155. {
  156. wrkBuffer = (rt_uint8_t *)rt_malloc(BMP_WORKING_BUFFER_SIZE);
  157. if (wrkBuffer == RT_NULL)
  158. {
  159. rt_kprintf("BMP err: no mem\n");
  160. break;
  161. }
  162. bmp = (struct rtgui_image_bmp *)rtgui_malloc(sizeof(struct rtgui_image_bmp));
  163. if (bmp == RT_NULL)
  164. {
  165. break;
  166. }
  167. /* Prepare to decode */
  168. if (rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET) < 0)
  169. {
  170. break;
  171. }
  172. if (rtgui_filerw_read(file, (void *)wrkBuffer, 18, 1) != 18)
  173. {
  174. break;
  175. }
  176. /* Read file type */
  177. if (wrkBuffer[0] != 'B' || wrkBuffer[1] != 'M')
  178. {
  179. break;
  180. }
  181. // rt_kprintf("BMP: format ok\n");
  182. /* Read pixel array offset */
  183. bmp->pixel_offset = *(rt_uint32_t *)&wrkBuffer[10];
  184. // rt_kprintf("BMP: bmp->pixel_offset %d\n", bmp->pixel_offset);
  185. /* Read BMP header size */
  186. bmpHeaderSize = *(rt_uint32_t *)&wrkBuffer[14];
  187. // rt_kprintf("BMP: bmpHeaderSize %d\n", bmpHeaderSize);
  188. colorsUsed = 0;
  189. if (bmpHeaderSize == 12)
  190. {
  191. /* Bitmap Header Version 2.x */
  192. if (rtgui_filerw_read(file, (void *)wrkBuffer, 8, 1) != 8)
  193. {
  194. break;
  195. }
  196. /* Read image size */
  197. bmp->w = (rt_uint32_t) * (rt_uint16_t *)&wrkBuffer[0];
  198. bmp->h = (rt_uint32_t) * (rt_uint16_t *)&wrkBuffer[2];
  199. /* Read bits per pixel */
  200. bmp->bit_per_pixel = (rt_uint8_t) * (rt_uint16_t *)&wrkBuffer[6];
  201. }
  202. else
  203. {
  204. /* Bitmap Header Version bigger than 2.x */
  205. rt_uint32_t compression;
  206. if (rtgui_filerw_read(file, (void *)wrkBuffer, 36, 1) != 36)
  207. {
  208. break;
  209. }
  210. /* Read image size */
  211. bmp->w = *(rt_uint32_t *)&wrkBuffer[0];
  212. bmp->h = *(rt_uint32_t *)&wrkBuffer[4];
  213. /* Read bits per pixel */
  214. bmp->bit_per_pixel = (rt_uint8_t) * (rt_uint16_t *)&wrkBuffer[10];
  215. if (bmp->bit_per_pixel > 32)
  216. {
  217. rt_kprintf("BMP err: unsupported format\n");
  218. break;
  219. }
  220. /* Read compression method */
  221. compression = *(rt_uint32_t *)&wrkBuffer[12];
  222. if (compression != BI_RGB && compression != BI_BITFIELDS)
  223. {
  224. rt_kprintf("BMP err: unsupported format\n");
  225. break;
  226. }
  227. /* Read number of colors */
  228. colorsUsed = *(rt_uint32_t *)&wrkBuffer[28];
  229. }
  230. if (!colorsUsed)
  231. {
  232. colorsUsed = 1 << bmp->bit_per_pixel;
  233. }
  234. /* Load palette */
  235. if (bmp->bit_per_pixel <= 8)
  236. {
  237. if (rtgui_filerw_seek(file, 14 + bmpHeaderSize, RTGUI_FILE_SEEK_SET) < 0)
  238. {
  239. break;
  240. }
  241. image->palette = rtgui_image_bmp_load_palette(file, colorsUsed,
  242. bmpHeaderSize > 12 ? RT_TRUE : RT_FALSE);
  243. if (image->palette == RT_NULL)
  244. {
  245. break;
  246. }
  247. }
  248. /* Set image information */
  249. bmp->is_loaded = RT_FALSE;
  250. bmp->scale = scale;
  251. if (bmp->bit_per_pixel == 1)
  252. {
  253. bmp->pitch = (bmp->w + 7) >> 3;
  254. }
  255. else if (bmp->bit_per_pixel == 4)
  256. {
  257. bmp->pitch = (bmp->w + 1) >> 1;
  258. }
  259. else
  260. {
  261. bmp->pitch = bmp->w * (bmp->bit_per_pixel >> 3);
  262. }
  263. bmp->pad = ((bmp->pitch % 4) ? (4 - (bmp->pitch % 4)) : 0);
  264. bmp->pixels = RT_NULL;
  265. bmp->filerw = file;
  266. image->w = bmp->w >> bmp->scale;
  267. image->h = bmp->h >> bmp->scale;
  268. image->engine = &rtgui_image_bmp_engine;
  269. image->data = bmp;
  270. /* Start to decode */
  271. if (load == RT_TRUE)
  272. {
  273. rt_bool_t error = RT_FALSE;
  274. rt_uint8_t *dst;
  275. rt_uint32_t imageWidth;
  276. rt_uint16_t readLength, readIndex, loadIndex;
  277. rt_uint8_t skipLength;
  278. rt_uint16_t y;
  279. rt_uint8_t bytePerPixel;
  280. rt_int8_t scale1, scale2;
  281. bytePerPixel = bmp->bit_per_pixel / 8;
  282. if (!bytePerPixel)
  283. {
  284. bytePerPixel = 1;
  285. }
  286. imageWidth = image->w * bytePerPixel; /* Scaled width in byte */
  287. bmp->pixels = rtgui_malloc(image->h * imageWidth);
  288. if (bmp->pixels == RT_NULL)
  289. {
  290. rt_kprintf("BMP err: no mem to load (%d)\n", image->h * imageWidth);
  291. break;
  292. }
  293. /* Read the pixels. Note that the bmp image is upside down */
  294. if (rtgui_filerw_seek(file, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
  295. {
  296. break;
  297. }
  298. if (bmp->bit_per_pixel == 1)
  299. {
  300. if (bmp->scale > 3)
  301. {
  302. scale1 = bmp->scale - 3;
  303. scale2 = 3;
  304. }
  305. else
  306. {
  307. scale1 = 0;
  308. scale2 = bmp->scale;
  309. }
  310. }
  311. else if (bmp->bit_per_pixel == 4)
  312. {
  313. if (bmp->scale > 1)
  314. {
  315. scale1 = bmp->scale - 1;
  316. scale2 = 1;
  317. }
  318. else
  319. {
  320. scale1 = 0;
  321. scale2 = bmp->scale;
  322. }
  323. }
  324. /* Process whole image */
  325. y = 0;
  326. while (y < image->h)
  327. {
  328. dst = bmp->pixels + (image->h - y - 1) * imageWidth;
  329. readIndex = 0;
  330. skipLength = 0;
  331. /* Process a line */
  332. while (readIndex < bmp->pitch)
  333. {
  334. /* Put progress indicator */
  335. rt_kprintf("\r%lu%%", y * 100UL / image->h);
  336. /* Read data to buffer */
  337. readLength = (BMP_WORKING_BUFFER_SIZE > (bmp->pitch - readIndex)) ? \
  338. (bmp->pitch - readIndex) : BMP_WORKING_BUFFER_SIZE;
  339. if (rtgui_filerw_read(file, (void *)wrkBuffer, 1, readLength) != readLength)
  340. {
  341. rt_kprintf("BMP err: read failed\n");
  342. error = RT_TRUE;
  343. break;
  344. }
  345. readIndex += readLength;
  346. /* Process read buffer */
  347. if (bmp->bit_per_pixel == 1)
  348. {
  349. rt_uint8_t j;
  350. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
  351. {
  352. for (j = 0; j < 8; j += 1 << scale2)
  353. {
  354. *(dst++) = (wrkBuffer[loadIndex] & (1 << (7 - j))) >> (7 - j);
  355. }
  356. }
  357. if (scale1 && (readLength % (1 << scale1)))
  358. {
  359. skipLength = (1 << scale1) - readLength % (1 << scale1);
  360. }
  361. }
  362. else if (bmp->bit_per_pixel == 4)
  363. {
  364. rt_uint8_t j;
  365. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
  366. {
  367. for (j = 0; j < 8; j += 1 << (2 + scale2))
  368. {
  369. *(dst++) = (wrkBuffer[loadIndex] & (0x0F << (4 - j))) >> (4 - j);
  370. }
  371. }
  372. if (scale1 && (readLength % (1 << scale1)))
  373. {
  374. skipLength = (1 << scale1) - readLength % (1 << scale1);
  375. }
  376. }
  377. else
  378. {
  379. if (bmp->scale == 0)
  380. {
  381. rt_memcpy((void *)dst, (void *)wrkBuffer, readLength);
  382. dst += readLength;
  383. }
  384. else
  385. {
  386. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += bytePerPixel << bmp->scale)
  387. {
  388. rt_memcpy((void *)dst, (void *)&wrkBuffer[loadIndex], bytePerPixel);
  389. dst += bytePerPixel;
  390. }
  391. if (readLength % (1 << bmp->scale))
  392. {
  393. skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
  394. }
  395. }
  396. }
  397. }
  398. if (error)
  399. {
  400. break;
  401. }
  402. y++;
  403. /* Skip padding bytes */
  404. if (bmp->pad)
  405. {
  406. if (rtgui_filerw_seek(file, bmp->pad, RTGUI_FILE_SEEK_CUR) < 0)
  407. {
  408. error = RT_TRUE;
  409. break;
  410. }
  411. }
  412. /* Height scale down */
  413. if (bmp->scale)
  414. {
  415. if (rtgui_filerw_seek(file, (bmp->pitch + bmp->pad) * ((1 << bmp->scale) - 1),
  416. RTGUI_FILE_SEEK_CUR) < 0)
  417. {
  418. error = RT_TRUE;
  419. break;
  420. }
  421. }
  422. }
  423. if (error)
  424. {
  425. break;
  426. }
  427. /* Close file */
  428. rtgui_filerw_close(bmp->filerw);
  429. bmp->filerw = RT_NULL;
  430. bmp->is_loaded = RT_TRUE;
  431. // rt_kprintf("BMP: load to RAM\n");
  432. }
  433. /* Release memory */
  434. rt_free(wrkBuffer);
  435. return RT_TRUE;
  436. }
  437. while (0);
  438. /* Release memory */
  439. rt_free(wrkBuffer);
  440. rtgui_free(image->palette);
  441. rtgui_free(bmp->pixels);
  442. rtgui_free(bmp);
  443. return RT_FALSE;
  444. }
  445. static void rtgui_image_bmp_unload(struct rtgui_image *image)
  446. {
  447. struct rtgui_image_bmp *bmp;
  448. if (image != RT_NULL)
  449. {
  450. bmp = (struct rtgui_image_bmp *)image->data;
  451. /* Release memory */
  452. rtgui_free(bmp->pixels);
  453. if (bmp->filerw != RT_NULL)
  454. {
  455. /* Close file */
  456. rtgui_filerw_close(bmp->filerw);
  457. bmp->filerw = RT_NULL;
  458. }
  459. rtgui_free(bmp);
  460. }
  461. }
  462. static void rtgui_image_bmp_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *dst_rect)
  463. {
  464. rt_uint16_t w, h;
  465. struct rtgui_image_bmp *bmp;
  466. rt_uint8_t bytePerPixel;
  467. rt_uint32_t imageWidth;
  468. rt_bool_t error;
  469. bmp = (struct rtgui_image_bmp *)image->data;
  470. RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL || bmp != RT_NULL);
  471. bytePerPixel = bmp->bit_per_pixel / 8;
  472. if (!bytePerPixel)
  473. {
  474. bytePerPixel = 1;
  475. }
  476. imageWidth = image->w * bytePerPixel; /* Scaled width in byte */
  477. error = RT_FALSE;
  478. do
  479. {
  480. /* this dc is not visible */
  481. if (rtgui_dc_get_visible(dc) != RT_TRUE)
  482. {
  483. break;
  484. }
  485. /* the minimum rect */
  486. if (image->w < rtgui_rect_width(*dst_rect))
  487. {
  488. w = image->w;
  489. }
  490. else
  491. {
  492. w = rtgui_rect_width(*dst_rect);
  493. }
  494. if (image->h < rtgui_rect_height(*dst_rect))
  495. {
  496. h = image->h;
  497. }
  498. else
  499. {
  500. h = rtgui_rect_height(*dst_rect);
  501. }
  502. if (!bmp->is_loaded)
  503. {
  504. rt_uint8_t *wrkBuffer;
  505. rt_uint16_t readLength, readIndex, loadIndex;
  506. rt_uint8_t skipLength;
  507. rt_uint16_t x, y;
  508. rt_int8_t scale1, scale2;
  509. rt_uint16_t y_start = dst_rect->y1 + h - 1;
  510. /* Read the pixels. Note that the bmp image is upside down */
  511. if (rtgui_filerw_seek(bmp->filerw, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
  512. {
  513. break;
  514. }
  515. /* the image is upside down. So we need to start from middle if the
  516. * image is higher than the dst_rect. */
  517. if (image->h > rtgui_rect_height(*dst_rect))
  518. {
  519. int hdelta = image->h - rtgui_rect_height(*dst_rect);
  520. if (rtgui_filerw_seek(bmp->filerw, hdelta * (bmp->pitch + bmp->pad) * (1 << bmp->scale),
  521. RTGUI_FILE_SEEK_CUR) < 0)
  522. {
  523. error = RT_TRUE;
  524. break;
  525. }
  526. }
  527. if (bmp->bit_per_pixel == 1)
  528. {
  529. if (bmp->scale > 3)
  530. {
  531. scale1 = bmp->scale - 3;
  532. scale2 = 3;
  533. }
  534. else
  535. {
  536. scale1 = 0;
  537. scale2 = bmp->scale;
  538. }
  539. }
  540. else if (bmp->bit_per_pixel == 4)
  541. {
  542. if (bmp->scale > 1)
  543. {
  544. scale1 = bmp->scale - 1;
  545. scale2 = 1;
  546. }
  547. else
  548. {
  549. scale1 = 0;
  550. scale2 = bmp->scale;
  551. }
  552. }
  553. wrkBuffer = (rt_uint8_t *)rt_malloc(
  554. (BMP_WORKING_BUFFER_SIZE > bmp->pitch) ? \
  555. bmp->pitch : BMP_WORKING_BUFFER_SIZE);
  556. if (wrkBuffer == RT_NULL)
  557. {
  558. rt_kprintf("BMP err: no mem (%d)\n", BMP_WORKING_BUFFER_SIZE);
  559. break;
  560. }
  561. /* Process whole image */
  562. y = 0;
  563. while (y < h)
  564. {
  565. x = 0;
  566. readIndex = 0;
  567. skipLength = 0;
  568. /* Process a line */
  569. while (readIndex < bmp->pitch)
  570. {
  571. /* Put progress indicator */
  572. rt_kprintf("\r%lu%%", y * 100UL / h);
  573. /* Read data to buffer */
  574. readLength = (BMP_WORKING_BUFFER_SIZE > (bmp->pitch - readIndex)) ? \
  575. (bmp->pitch - readIndex) : BMP_WORKING_BUFFER_SIZE;
  576. if (rtgui_filerw_read(bmp->filerw, (void *)wrkBuffer, 1, readLength) != readLength)
  577. {
  578. rt_kprintf("BMP err: read failed\n");
  579. error = RT_TRUE;
  580. break;
  581. }
  582. readIndex += readLength;
  583. /* Process read buffer */
  584. if (bmp->bit_per_pixel == 1)
  585. {
  586. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
  587. {
  588. rt_uint8_t j;
  589. for (j = 0; j < 8; j += 1 << scale2)
  590. {
  591. rtgui_color_t color;
  592. color = image->palette->colors[(wrkBuffer[loadIndex] & (1 << (7 - j))) >> (7 - j)];
  593. rtgui_dc_draw_color_point(dc,
  594. dst_rect->x1 + x++,
  595. y_start - y,
  596. color);
  597. if (x >= w)
  598. break;
  599. }
  600. if (scale1 && (readLength % (1 << scale1)))
  601. {
  602. skipLength = (1 << scale1) - readLength % (1 << scale1);
  603. }
  604. }
  605. }
  606. else if (bmp->bit_per_pixel == 4)
  607. {
  608. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
  609. {
  610. rt_uint8_t j;
  611. for (j = 0; j < 8; j += 1 << (2 + scale2))
  612. {
  613. rtgui_color_t color;
  614. color = image->palette->colors[(wrkBuffer[loadIndex] & (0x0F << (4 - j))) >> (4 - j)];
  615. rtgui_dc_draw_color_point(dc,
  616. dst_rect->x1 + x++,
  617. y_start - y,
  618. color);
  619. if (x >= w)
  620. break;
  621. }
  622. }
  623. if (scale1 && (readLength % (1 << scale1)))
  624. {
  625. skipLength = (1 << scale1) - readLength % (1 << scale1);
  626. }
  627. }
  628. else if (bmp->bit_per_pixel == 8)
  629. {
  630. for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << bmp->scale)
  631. {
  632. rtgui_color_t color;
  633. color = image->palette->colors[wrkBuffer[loadIndex]];
  634. rtgui_dc_draw_color_point(dc,
  635. dst_rect->x1 + x++,
  636. y_start - y,
  637. color);
  638. if (x >= w)
  639. break;
  640. }
  641. if (readLength % (1 << bmp->scale))
  642. {
  643. skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
  644. }
  645. }
  646. else
  647. {
  648. rtgui_blit_line_func blit_line;
  649. rt_uint8_t hw_bytePerPixel = hw_driver->bits_per_pixel / 8;
  650. rt_uint8_t temp[4] = {0};
  651. if (!hw_bytePerPixel)
  652. {
  653. hw_bytePerPixel = 1;
  654. }
  655. if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
  656. {
  657. blit_line = rtgui_blit_line_get_inv(hw_bytePerPixel, bytePerPixel);
  658. }
  659. else
  660. {
  661. blit_line = rtgui_blit_line_get(hw_bytePerPixel, bytePerPixel);
  662. }
  663. for (loadIndex = skipLength;
  664. loadIndex < readLength;
  665. loadIndex += bytePerPixel << bmp->scale)
  666. {
  667. blit_line(temp, &wrkBuffer[loadIndex], bytePerPixel);
  668. dc->engine->blit_line(dc,
  669. dst_rect->x1 + x, dst_rect->x1 + x + 1,
  670. y_start - y,
  671. temp);
  672. x++;
  673. if (x >= w)
  674. break;
  675. }
  676. if (readLength % (1 << bmp->scale))
  677. {
  678. skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
  679. }
  680. }
  681. }
  682. if (error)
  683. {
  684. break;
  685. }
  686. y++;
  687. /* Skip padding bytes */
  688. if (bmp->pad)
  689. {
  690. if (rtgui_filerw_seek(bmp->filerw, bmp->pad, RTGUI_FILE_SEEK_CUR) < 0)
  691. {
  692. error = RT_TRUE;
  693. break;
  694. }
  695. }
  696. /* Height scale down */
  697. if (bmp->scale)
  698. {
  699. if (rtgui_filerw_seek(bmp->filerw, (bmp->pitch + bmp->pad) * ((1 << bmp->scale) - 1),
  700. RTGUI_FILE_SEEK_CUR) < 0)
  701. {
  702. error = RT_TRUE;
  703. break;
  704. }
  705. }
  706. }
  707. if (error)
  708. {
  709. break;
  710. }
  711. /* Release memory */
  712. rt_free(wrkBuffer);
  713. // rt_kprintf("BMP: load to display\n");
  714. }
  715. else
  716. {
  717. rt_uint16_t x, y;
  718. rt_uint8_t *ptr;
  719. for (y = 0; y < h; y ++)
  720. {
  721. ptr = bmp->pixels + (y * imageWidth);
  722. if (bmp->bit_per_pixel <= 8)
  723. {
  724. rtgui_color_t color;
  725. /* Using palette */
  726. for (x = 0; x < w; x ++)
  727. {
  728. color = image->palette->colors[*(ptr++)];
  729. rtgui_dc_draw_color_point(dc,
  730. dst_rect->x1 + x,
  731. dst_rect->y1 + y,
  732. color);
  733. }
  734. }
  735. else
  736. {
  737. rtgui_blit_line_func blit_line;
  738. rt_uint8_t hw_bytePerPixel = hw_driver->bits_per_pixel / 8;
  739. rt_uint8_t temp[4] = {0};
  740. if (!hw_bytePerPixel)
  741. {
  742. hw_bytePerPixel = 1;
  743. }
  744. if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
  745. {
  746. blit_line = rtgui_blit_line_get_inv(hw_bytePerPixel, bytePerPixel);
  747. }
  748. else
  749. {
  750. blit_line = rtgui_blit_line_get(hw_bytePerPixel, bytePerPixel);
  751. }
  752. for (x = 0; x < w; x ++)
  753. {
  754. blit_line(temp, ptr, bytePerPixel);
  755. ptr += bytePerPixel;
  756. dc->engine->blit_line(dc,
  757. dst_rect->x1 + x, dst_rect->x1 + x + 1,
  758. dst_rect->y1 + y,
  759. temp);
  760. }
  761. }
  762. }
  763. }
  764. // rt_kprintf("BMP: blit ok\n");
  765. }
  766. while (0);
  767. }
  768. void rtgui_image_bmp_init()
  769. {
  770. /* register bmp on image system */
  771. rtgui_image_register_engine(&rtgui_image_bmp_engine);
  772. }
  773. #endif