image_bmp.c 26 KB

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