image_bmp.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  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. { /* Each color component is calculated separately */
  1033. rt_uint32_t cc1,cc2,cc3,cc4;
  1034. unsigned char r, g, b;
  1035. cc1 = rtgui_color_from_565p(*(rt_uint16_t*)(src_buf +
  1036. src_line_size * y + nbytes * x ));
  1037. cc2 = rtgui_color_from_565p(*(rt_uint16_t*)(src_buf +
  1038. src_line_size * y + nbytes * (x+1)));
  1039. cc3 = rtgui_color_from_565p(*(rt_uint16_t*)(src_buf +
  1040. src_line_size * (y+1) + nbytes * x ));
  1041. cc4 = rtgui_color_from_565p(*(rt_uint16_t*)(src_buf +
  1042. src_line_size * (y+1) + nbytes * (x+1)));
  1043. r = (unsigned char)((1-u)*(1-v)*(float)RTGUI_RGB_R(cc1) +
  1044. (1-u)*v*(float)RTGUI_RGB_R(cc2) + u*(1-v)*(float)RTGUI_RGB_R(cc3) +
  1045. u*v*(float)RTGUI_RGB_R(cc4));
  1046. g = (unsigned char)((1-u)*(1-v)*(float)RTGUI_RGB_G(cc1) +
  1047. (1-u)*v*(float)RTGUI_RGB_G(cc2) + u*(1-v)*(float)RTGUI_RGB_G(cc3) +
  1048. u*v*(float)RTGUI_RGB_G(cc4));
  1049. b = (unsigned char)((1-u)*(1-v)*(float)RTGUI_RGB_B(cc1) +
  1050. (1-u)*v*(float)RTGUI_RGB_B(cc2) + u*(1-v)*(float)RTGUI_RGB_B(cc3) +
  1051. u*v*(float)RTGUI_RGB_B(cc4));
  1052. *(rt_uint16_t*)(des_buf + i * dest_line_size + j * nbytes) =
  1053. rtgui_color_to_565p(RTGUI_RGB(r, g, b));
  1054. }
  1055. else if(bitcount == 24)
  1056. {
  1057. int k;
  1058. for (k = 0; k < 3; k++)
  1059. { /* 24 bits color is 3 bytes R:G:B */
  1060. c1 = (src_buf[src_line_size * y + nbytes * x + k]);
  1061. c2 = (src_buf[src_line_size * y + nbytes * (x+1) + k]);
  1062. c3 = (src_buf[src_line_size * (y+1) + nbytes * x + k]);
  1063. c4 = (src_buf[src_line_size * (y+1) + nbytes * (x+1) + k]);
  1064. des_buf[i * dest_line_size + j * nbytes + k] = (unsigned char)
  1065. ((1-u)*(1-v)*(float)c1 + (1-u)*v*(float)c2 + u*(1-v)*(float)c3 + u*v*(float)c4);
  1066. }
  1067. }
  1068. }
  1069. }
  1070. }
  1071. d_img->data = d_bmp;
  1072. return d_img;
  1073. }
  1074. #include <math.h>
  1075. #ifndef M_PI
  1076. #define M_PI 3.14159265358979323846
  1077. #endif
  1078. /*
  1079. * around a pos o, rotating pos p
  1080. */
  1081. rt_inline rtgui_point_t _rotate_pos(rtgui_point_t o, rtgui_point_t p, float sina, float cosa)
  1082. {
  1083. rtgui_point_t rp;
  1084. float dx, dy;
  1085. dx = p.x - o.x;
  1086. dy = p.y - o.y;
  1087. rp.x = (float)o.x + dx * cosa + dy * sina;
  1088. rp.y = (float)o.y + dy * cosa - dx * sina;
  1089. return rp;
  1090. }
  1091. /*
  1092. * image rotate interface, rotate direction: clockwise
  1093. * Support 16/24 bits format image
  1094. */
  1095. static struct rtgui_image* rtgui_image_bmp_rotate(struct rtgui_image* image, float angle)
  1096. {
  1097. float age, sina, cosa;
  1098. rtgui_point_t o, p, cp;
  1099. rtgui_rect_t rect;
  1100. struct rtgui_image *d_img;
  1101. struct rtgui_image_bmp *bmp, *d_bmp;
  1102. int bitcount, nbytes, i, j;
  1103. int sw, sh, dw, dh;
  1104. int dest_buff_size;
  1105. int src_line_size, dest_line_size;
  1106. char *src_buf;
  1107. char *des_buf;
  1108. /* rt_tick_t tick = rt_tick_get(); */
  1109. bmp = (struct rtgui_image_bmp*)image->data;
  1110. src_buf = bmp->pixels;
  1111. sw = bmp->w;
  1112. sh = bmp->h;
  1113. bitcount = bmp->bit_per_pixel;
  1114. if(bitcount != 16 && bitcount != 24)
  1115. {
  1116. rt_kprintf("Does not support %d bits format\n", bitcount);
  1117. return RT_NULL;
  1118. }
  1119. nbytes = bitcount / 8;
  1120. src_line_size = sw * nbytes;
  1121. /* convert angle to radians */
  1122. age = angle * M_PI / 180.0;
  1123. sina = sin(age);
  1124. cosa = cos(age);
  1125. /*
  1126. ** known: a, b, angle;
  1127. ** solve: aa = a*abs(cos(angle)) + b*abs(sin(angle));
  1128. ** solve: bb = b*abs(cos(angle)) + a*abs(sin(angle));
  1129. */
  1130. dw = (int)(sw * fabs(cosa) + sh * fabs(sina));
  1131. dh = (int)(sh * fabs(cosa) + sw * fabs(sina));
  1132. rect.x1 = rect.y1 = 0;
  1133. rect.x2 = sw; rect.y2 = sh;
  1134. d_img = rt_malloc(sizeof(struct rtgui_image));
  1135. if(d_img == RT_NULL)
  1136. {
  1137. rt_kprintf("Not enough memory allocation IMG!\n");
  1138. return RT_NULL;
  1139. }
  1140. d_img->w = dw;
  1141. d_img->h = dh;
  1142. d_img->engine = &rtgui_image_bmp_engine;
  1143. d_img->palette = RT_NULL;
  1144. /* config dest bmp data */
  1145. dest_line_size = ((dw * bitcount + (bitcount-1)) / bitcount) * nbytes;
  1146. dest_buff_size = dest_line_size * dh;
  1147. d_bmp = rt_malloc(sizeof(struct rtgui_image_bmp));
  1148. if(d_bmp == RT_NULL)
  1149. {
  1150. rt_free(d_img);
  1151. rt_kprintf("Not enough memory allocation BMP!\n");
  1152. return RT_NULL;
  1153. }
  1154. d_bmp->w = dw;
  1155. d_bmp->h = dh;
  1156. d_bmp->bit_per_pixel = bitcount;
  1157. d_bmp->pixel_offset = 54; /* insignificant parameter */
  1158. d_bmp->filerw = RT_NULL;
  1159. d_bmp->is_loaded = RT_TRUE; /* Don't want to loading */
  1160. d_bmp->pitch = d_bmp->w * nbytes;
  1161. d_bmp->pad = ((d_bmp->pitch % 4) ? (4 - (d_bmp->pitch%4)) : 0);
  1162. d_bmp->scale = 0;
  1163. d_bmp->pixels = rt_malloc(dest_buff_size);
  1164. if(d_bmp->pixels == RT_NULL)
  1165. {
  1166. rt_free(d_img);
  1167. rt_free(d_bmp);
  1168. rt_kprintf("Not enough memory allocation BMP data!\n");
  1169. return RT_NULL;
  1170. }
  1171. des_buf = d_bmp->pixels;
  1172. /* use white fill empty pixel */
  1173. rt_memset(des_buf, 0xFF, dest_buff_size);
  1174. o.x = dw>>1;
  1175. o.y = dh>>1;
  1176. if(bitcount == 16 || bitcount == 24)
  1177. {
  1178. for (i = 0; i < dh; i++)
  1179. {
  1180. for (j = 0; j < dw; j++)
  1181. {
  1182. p.x = j; p.y = i;
  1183. cp = _rotate_pos(o, p, sina, cosa);
  1184. cp.x -= (dw-sw)>>1;
  1185. cp.y -= (dh-sh)>>1;
  1186. if(rtgui_rect_contains_point(&rect, cp.x, cp.y) != RT_EOK)
  1187. continue;
  1188. rt_memcpy (&des_buf[dest_line_size * i] + nbytes * j,
  1189. &src_buf[src_line_size * cp.y] + nbytes * cp.x, nbytes);
  1190. }
  1191. }
  1192. }
  1193. d_img->data = d_bmp;
  1194. /* rt_kprintf("rotate use %d ticks\n", rt_tick_get()-tick); */
  1195. return d_img;
  1196. }
  1197. void rtgui_image_bmp_init()
  1198. {
  1199. /* register bmp on image system */
  1200. rtgui_image_register_engine(&rtgui_image_bmp_engine);
  1201. }
  1202. #endif