x11_image.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. // Copyright (C) 2004-2021 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. /*
  23. * Blit RGBA images to X with X(Shm)Images
  24. */
  25. #ifndef _XOPEN_SOURCE
  26. # define _XOPEN_SOURCE 1
  27. #endif
  28. #ifndef _XOPEN_SOURCE
  29. # define _XOPEN_SOURCE 1
  30. #endif
  31. #define noSHOWINFO
  32. #include "mupdf/fitz.h"
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <X11/Xlib.h>
  37. #include <X11/Xutil.h>
  38. #include <sys/ipc.h>
  39. #include <sys/shm.h>
  40. #include <X11/extensions/XShm.h>
  41. #include <limits.h>
  42. extern int ffs(int);
  43. static int is_big_endian(void)
  44. {
  45. static const int one = 1;
  46. return *(char*)&one == 0;
  47. }
  48. typedef void (*ximage_convert_func_t)
  49. (
  50. const unsigned char *src,
  51. int srcstride,
  52. unsigned char *dst,
  53. int dststride,
  54. int w,
  55. int h
  56. );
  57. #define POOLSIZE 4
  58. #define WIDTH 256
  59. #define HEIGHT 256
  60. enum {
  61. ARGB8888,
  62. BGRA8888,
  63. RGBA8888,
  64. ABGR8888,
  65. RGB888,
  66. BGR888,
  67. RGB565,
  68. RGB565_BR,
  69. RGB555,
  70. RGB555_BR,
  71. BGR233,
  72. UNKNOWN
  73. };
  74. #ifdef SHOWINFO
  75. static char *modename[] = {
  76. "ARGB8888",
  77. "BGRA8888",
  78. "RGBA8888",
  79. "ABGR8888",
  80. "RGB888",
  81. "BGR888",
  82. "RGB565",
  83. "RGB565_BR",
  84. "RGB555",
  85. "RGB555_BR",
  86. "BGR233",
  87. "UNKNOWN"
  88. };
  89. #endif
  90. extern ximage_convert_func_t ximage_convert_funcs[];
  91. static struct
  92. {
  93. Display *display;
  94. int screen;
  95. XVisualInfo visual;
  96. Colormap colormap;
  97. int bitsperpixel;
  98. int mode;
  99. XColor rgbcube[256];
  100. ximage_convert_func_t convert_func;
  101. int useshm;
  102. int shmcode;
  103. XImage *pool[POOLSIZE];
  104. /* MUST exist during the lifetime of the shared ximage according to the
  105. xc/doc/hardcopy/Xext/mit-shm.PS.gz */
  106. XShmSegmentInfo shminfo[POOLSIZE];
  107. int lastused;
  108. } info;
  109. static XImage *
  110. createximage(Display *dpy, Visual *vis, XShmSegmentInfo *xsi, int depth, int w, int h)
  111. {
  112. XImage *img;
  113. Status status;
  114. if (!XShmQueryExtension(dpy))
  115. goto fallback;
  116. if (!info.useshm)
  117. goto fallback;
  118. img = XShmCreateImage(dpy, vis, depth, ZPixmap, NULL, xsi, w, h);
  119. if (!img)
  120. {
  121. fprintf(stderr, "warn: could not XShmCreateImage\n");
  122. goto fallback;
  123. }
  124. xsi->shmid = shmget(IPC_PRIVATE,
  125. (size_t)img->bytes_per_line * img->height,
  126. IPC_CREAT | 0777);
  127. if (xsi->shmid < 0)
  128. {
  129. XDestroyImage(img);
  130. fprintf(stderr, "warn: could not shmget\n");
  131. goto fallback;
  132. }
  133. img->data = xsi->shmaddr = shmat(xsi->shmid, NULL, 0);
  134. if (img->data == (char*)-1)
  135. {
  136. XDestroyImage(img);
  137. fprintf(stderr, "warn: could not shmat\n");
  138. goto fallback;
  139. }
  140. xsi->readOnly = False;
  141. status = XShmAttach(dpy, xsi);
  142. if (!status)
  143. {
  144. shmdt(xsi->shmaddr);
  145. XDestroyImage(img);
  146. fprintf(stderr, "warn: could not XShmAttach\n");
  147. goto fallback;
  148. }
  149. XSync(dpy, False);
  150. shmctl(xsi->shmid, IPC_RMID, NULL);
  151. return img;
  152. fallback:
  153. info.useshm = 0;
  154. img = XCreateImage(dpy, vis, depth, ZPixmap, 0, NULL, w, h, 32, 0);
  155. if (!img)
  156. {
  157. fprintf(stderr, "fail: could not XCreateImage");
  158. abort();
  159. }
  160. img->data = malloc((size_t)h * img->bytes_per_line);
  161. if (!img->data)
  162. {
  163. fprintf(stderr, "fail: could not malloc");
  164. abort();
  165. }
  166. return img;
  167. }
  168. static void
  169. make_colormap(void)
  170. {
  171. if (info.visual.class == PseudoColor && info.visual.depth == 8)
  172. {
  173. int i, r, g, b;
  174. i = 0;
  175. for (b = 0; b < 4; b++) {
  176. for (g = 0; g < 8; g++) {
  177. for (r = 0; r < 8; r++) {
  178. info.rgbcube[i].pixel = i;
  179. info.rgbcube[i].red = (r * 36) << 8;
  180. info.rgbcube[i].green = (g * 36) << 8;
  181. info.rgbcube[i].blue = (b * 85) << 8;
  182. info.rgbcube[i].flags =
  183. DoRed | DoGreen | DoBlue;
  184. i++;
  185. }
  186. }
  187. }
  188. info.colormap = XCreateColormap(info.display,
  189. RootWindow(info.display, info.screen),
  190. info.visual.visual,
  191. AllocAll);
  192. XStoreColors(info.display, info.colormap, info.rgbcube, 256);
  193. return;
  194. }
  195. else if (info.visual.class == TrueColor)
  196. {
  197. info.colormap = 0;
  198. return;
  199. }
  200. fprintf(stderr, "Cannot handle visual class %d with depth: %d\n",
  201. info.visual.class, info.visual.depth);
  202. return;
  203. }
  204. static void
  205. select_mode(void)
  206. {
  207. int byteorder;
  208. int byterev;
  209. unsigned long rm, gm, bm;
  210. unsigned long rs, gs, bs;
  211. byteorder = ImageByteOrder(info.display);
  212. if (is_big_endian())
  213. byterev = byteorder != MSBFirst;
  214. else
  215. byterev = byteorder != LSBFirst;
  216. rm = info.visual.red_mask;
  217. gm = info.visual.green_mask;
  218. bm = info.visual.blue_mask;
  219. rs = ffs(rm) - 1;
  220. gs = ffs(gm) - 1;
  221. bs = ffs(bm) - 1;
  222. #ifdef SHOWINFO
  223. printf("ximage: mode %d/%d %08lx %08lx %08lx (%ld,%ld,%ld) %s%s\n",
  224. info.visual.depth,
  225. info.bitsperpixel,
  226. rm, gm, bm, rs, gs, bs,
  227. byteorder == MSBFirst ? "msb" : "lsb",
  228. byterev ? " <swap>":"");
  229. #endif
  230. info.mode = UNKNOWN;
  231. if (info.bitsperpixel == 8) {
  232. /* Either PseudoColor with BGR233 colormap, or TrueColor */
  233. info.mode = BGR233;
  234. }
  235. else if (info.bitsperpixel == 16) {
  236. if (rm == 0xF800 && gm == 0x07E0 && bm == 0x001F)
  237. info.mode = !byterev ? RGB565 : RGB565_BR;
  238. if (rm == 0x7C00 && gm == 0x03E0 && bm == 0x001F)
  239. info.mode = !byterev ? RGB555 : RGB555_BR;
  240. }
  241. else if (info.bitsperpixel == 24) {
  242. if (rs == 0 && gs == 8 && bs == 16)
  243. info.mode = byteorder == MSBFirst ? RGB888 : BGR888;
  244. if (rs == 16 && gs == 8 && bs == 0)
  245. info.mode = byteorder == MSBFirst ? BGR888 : RGB888;
  246. }
  247. else if (info.bitsperpixel == 32) {
  248. if (rs == 0 && gs == 8 && bs == 16)
  249. info.mode = byteorder == MSBFirst ? ABGR8888 : RGBA8888;
  250. if (rs == 8 && gs == 16 && bs == 24)
  251. info.mode = byteorder == MSBFirst ? BGRA8888 : ARGB8888;
  252. if (rs == 16 && gs == 8 && bs == 0)
  253. info.mode = byteorder == MSBFirst ? ARGB8888 : BGRA8888;
  254. if (rs == 24 && gs == 16 && bs == 8)
  255. info.mode = byteorder == MSBFirst ? RGBA8888 : ABGR8888;
  256. }
  257. #ifdef SHOWINFO
  258. printf("ximage: RGBA8888 to %s\n", modename[info.mode]);
  259. #endif
  260. /* select conversion function */
  261. info.convert_func = ximage_convert_funcs[info.mode];
  262. }
  263. static int
  264. create_pool(void)
  265. {
  266. int i;
  267. info.lastused = 0;
  268. for (i = 0; i < POOLSIZE; i++) {
  269. info.pool[i] = NULL;
  270. }
  271. for (i = 0; i < POOLSIZE; i++) {
  272. info.pool[i] = createximage(info.display,
  273. info.visual.visual, &info.shminfo[i], info.visual.depth,
  274. WIDTH, HEIGHT);
  275. if (!info.pool[i]) {
  276. return 0;
  277. }
  278. }
  279. return 1;
  280. }
  281. static XImage *
  282. next_pool_image(void)
  283. {
  284. if (info.lastused + 1 >= POOLSIZE) {
  285. if (info.useshm)
  286. XSync(info.display, False);
  287. else
  288. XFlush(info.display);
  289. info.lastused = 0;
  290. }
  291. return info.pool[info.lastused ++];
  292. }
  293. static int
  294. ximage_error_handler(Display *display, XErrorEvent *event)
  295. {
  296. /* Turn off shared memory images if we get an error from the MIT-SHM extension */
  297. if (event->request_code == info.shmcode)
  298. {
  299. char buf[80];
  300. XGetErrorText(display, event->error_code, buf, sizeof buf);
  301. fprintf(stderr, "ximage: disabling shared memory extension: %s\n", buf);
  302. info.useshm = 0;
  303. return 0;
  304. }
  305. XSetErrorHandler(NULL);
  306. return (XSetErrorHandler(ximage_error_handler))(display, event);
  307. }
  308. int
  309. ximage_init(Display *display, int screen, Visual *visual)
  310. {
  311. XVisualInfo template;
  312. XVisualInfo *visuals;
  313. int nvisuals;
  314. XPixmapFormatValues *formats;
  315. int nformats;
  316. int ok;
  317. int i;
  318. int major;
  319. int event;
  320. int error;
  321. info.display = display;
  322. info.screen = screen;
  323. info.colormap = 0;
  324. /* Get XVisualInfo for this visual */
  325. template.visualid = XVisualIDFromVisual(visual);
  326. visuals = XGetVisualInfo(display, VisualIDMask, &template, &nvisuals);
  327. if (nvisuals != 1) {
  328. fprintf(stderr, "Visual not found!\n");
  329. XFree(visuals);
  330. return 0;
  331. }
  332. memcpy(&info.visual, visuals, sizeof (XVisualInfo));
  333. XFree(visuals);
  334. /* Get appropriate PixmapFormat for this visual */
  335. formats = XListPixmapFormats(info.display, &nformats);
  336. for (i = 0; i < nformats; i++) {
  337. if (formats[i].depth == info.visual.depth) {
  338. info.bitsperpixel = formats[i].bits_per_pixel;
  339. break;
  340. }
  341. }
  342. XFree(formats);
  343. if (i == nformats) {
  344. fprintf(stderr, "PixmapFormat not found!\n");
  345. return 0;
  346. }
  347. /* extract mode */
  348. select_mode();
  349. /* prepare colormap */
  350. make_colormap();
  351. /* identify code for MIT-SHM extension */
  352. if (XQueryExtension(display, "MIT-SHM", &major, &event, &error) &&
  353. XShmQueryExtension(display))
  354. info.shmcode = major;
  355. /* intercept errors looking for SHM code */
  356. XSetErrorHandler(ximage_error_handler);
  357. /* prepare pool of XImages */
  358. info.useshm = 1;
  359. ok = create_pool();
  360. if (!ok)
  361. return 0;
  362. #ifdef SHOWINFO
  363. printf("ximage: %sPutImage\n", info.useshm ? "XShm" : "X");
  364. #endif
  365. return 1;
  366. }
  367. int
  368. ximage_get_depth(void)
  369. {
  370. return info.visual.depth;
  371. }
  372. Visual *
  373. ximage_get_visual(void)
  374. {
  375. return info.visual.visual;
  376. }
  377. Colormap
  378. ximage_get_colormap(void)
  379. {
  380. return info.colormap;
  381. }
  382. void
  383. ximage_blit(Drawable d, GC gc,
  384. int dstx, int dsty,
  385. unsigned char *srcdata,
  386. int srcx, int srcy,
  387. int srcw, int srch,
  388. int srcstride)
  389. {
  390. XImage *image;
  391. int ax, ay;
  392. int w, h;
  393. unsigned char *srcptr;
  394. if (srcw >= (INT_MAX / 4) / srch)
  395. {
  396. fprintf(stderr, "image size overflow: %d x %d\n", srcw, srch);
  397. exit(1);
  398. }
  399. for (ay = 0; ay < srch; ay += HEIGHT)
  400. {
  401. h = fz_mini(srch - ay, HEIGHT);
  402. for (ax = 0; ax < srcw; ax += WIDTH)
  403. {
  404. w = fz_mini(srcw - ax, WIDTH);
  405. image = next_pool_image();
  406. srcptr = srcdata +
  407. (ay + srcy) * srcstride +
  408. (ax + srcx) * 4;
  409. info.convert_func(srcptr, srcstride,
  410. (unsigned char *) image->data,
  411. image->bytes_per_line, w, h);
  412. if (info.useshm)
  413. {
  414. XShmPutImage(info.display, d, gc, image,
  415. 0, 0, dstx + ax, dsty + ay,
  416. w, h, False);
  417. }
  418. else
  419. {
  420. XPutImage(info.display, d, gc, image,
  421. 0, 0,
  422. dstx + ax,
  423. dsty + ay,
  424. w, h);
  425. }
  426. }
  427. }
  428. }
  429. /*
  430. * Primitive conversion functions
  431. */
  432. #ifndef restrict
  433. #ifndef _C99
  434. #ifdef __GNUC__
  435. #define restrict __restrict__
  436. #else
  437. #define restrict
  438. #endif
  439. #endif
  440. #endif
  441. #define PARAMS \
  442. const unsigned char * restrict src, \
  443. int srcstride, \
  444. unsigned char * restrict dst, \
  445. int dststride, \
  446. int w, \
  447. int h
  448. /*
  449. * Convert byte:RGBA8888 to various formats
  450. */
  451. static void
  452. ximage_convert_argb8888(PARAMS)
  453. {
  454. int x, y;
  455. for (y = 0; y < h; y++) {
  456. for (x = 0; x < w; x ++) {
  457. dst[x * 4 + 0] = src[x * 4 + 3]; /* a */
  458. dst[x * 4 + 1] = src[x * 4 + 0]; /* r */
  459. dst[x * 4 + 2] = src[x * 4 + 1]; /* g */
  460. dst[x * 4 + 3] = src[x * 4 + 2]; /* b */
  461. }
  462. dst += dststride;
  463. src += srcstride;
  464. }
  465. }
  466. static void
  467. ximage_convert_bgra8888(PARAMS)
  468. {
  469. int x, y;
  470. for (y = 0; y < h; y++) {
  471. for (x = 0; x < w; x++) {
  472. dst[x * 4 + 0] = src[x * 4 + 2];
  473. dst[x * 4 + 1] = src[x * 4 + 1];
  474. dst[x * 4 + 2] = src[x * 4 + 0];
  475. dst[x * 4 + 3] = src[x * 4 + 3];
  476. }
  477. dst += dststride;
  478. src += srcstride;
  479. }
  480. }
  481. static void
  482. ximage_convert_abgr8888(PARAMS)
  483. {
  484. int x, y;
  485. for (y = 0; y < h; y++) {
  486. for (x = 0; x < w; x++) {
  487. dst[x * 4 + 0] = src[x * 4 + 3];
  488. dst[x * 4 + 1] = src[x * 4 + 2];
  489. dst[x * 4 + 2] = src[x * 4 + 1];
  490. dst[x * 4 + 3] = src[x * 4 + 0];
  491. }
  492. dst += dststride;
  493. src += srcstride;
  494. }
  495. }
  496. static void
  497. ximage_convert_rgba8888(PARAMS)
  498. {
  499. int x, y;
  500. for (y = 0; y < h; y++) {
  501. for (x = 0; x < w; x++) {
  502. ((unsigned *)dst)[x] = ((unsigned *)src)[x];
  503. }
  504. dst += dststride;
  505. src += srcstride;
  506. }
  507. }
  508. static void
  509. ximage_convert_bgr888(PARAMS)
  510. {
  511. int x, y;
  512. for (y = 0; y < h; y++) {
  513. for (x = 0; x < w; x++) {
  514. dst[3*x + 0] = src[4*x + 2];
  515. dst[3*x + 1] = src[4*x + 1];
  516. dst[3*x + 2] = src[4*x + 0];
  517. }
  518. src += srcstride;
  519. dst += dststride;
  520. }
  521. }
  522. static void
  523. ximage_convert_rgb888(PARAMS)
  524. {
  525. int x, y;
  526. for (y = 0; y < h; y++) {
  527. for (x = 0; x < w; x++) {
  528. dst[3*x + 0] = src[4*x + 0];
  529. dst[3*x + 1] = src[4*x + 1];
  530. dst[3*x + 2] = src[4*x + 2];
  531. }
  532. src += srcstride;
  533. dst += dststride;
  534. }
  535. }
  536. static void
  537. ximage_convert_rgb565(PARAMS)
  538. {
  539. unsigned char r, g, b;
  540. int x, y;
  541. for (y = 0; y < h; y++) {
  542. for (x = 0; x < w; x++) {
  543. r = src[4*x + 0];
  544. g = src[4*x + 1];
  545. b = src[4*x + 2];
  546. ((unsigned short *)dst)[x] =
  547. ((r & 0xF8) << 8) |
  548. ((g & 0xFC) << 3) |
  549. (b >> 3);
  550. }
  551. src += srcstride;
  552. dst += dststride;
  553. }
  554. }
  555. static void
  556. ximage_convert_rgb565_br(PARAMS)
  557. {
  558. unsigned char r, g, b;
  559. int x, y;
  560. for (y = 0; y < h; y++) {
  561. for (x = 0; x < w; x++) {
  562. r = src[4*x + 0];
  563. g = src[4*x + 1];
  564. b = src[4*x + 2];
  565. /* final word is:
  566. g4 g3 g2 b7 b6 b5 b4 b3 : r7 r6 r5 r4 r3 g7 g6 g5
  567. */
  568. ((unsigned short *)dst)[x] =
  569. (r & 0xF8) |
  570. ((g & 0xE0) >> 5) |
  571. ((g & 0x1C) << 11) |
  572. ((b & 0xF8) << 5);
  573. }
  574. src += srcstride;
  575. dst += dststride;
  576. }
  577. }
  578. static void
  579. ximage_convert_rgb555(PARAMS)
  580. {
  581. unsigned char r, g, b;
  582. int x, y;
  583. for (y = 0; y < h; y++) {
  584. for (x = 0; x < w; x++) {
  585. r = src[4*x + 0];
  586. g = src[4*x + 1];
  587. b = src[4*x + 2];
  588. ((unsigned short *)dst)[x] =
  589. ((r & 0xF8) << 7) |
  590. ((g & 0xF8) << 2) |
  591. (b >> 3);
  592. }
  593. src += srcstride;
  594. dst += dststride;
  595. }
  596. }
  597. static void
  598. ximage_convert_rgb555_br(PARAMS)
  599. {
  600. unsigned char r, g, b;
  601. int x, y;
  602. for (y = 0; y < h; y++) {
  603. for (x = 0; x < w; x++) {
  604. r = src[4*x + 0];
  605. g = src[4*x + 1];
  606. b = src[4*x + 2];
  607. /* final word is:
  608. g5 g4 g3 b7 b6 b5 b4 b3 : 0 r7 r6 r5 r4 r3 g7 g6
  609. */
  610. ((unsigned short *)dst)[x] =
  611. ((r & 0xF8) >> 1) |
  612. ((g & 0xC0) >> 6) |
  613. ((g & 0x38) << 10) |
  614. ((b & 0xF8) << 5);
  615. }
  616. src += srcstride;
  617. dst += dststride;
  618. }
  619. }
  620. static void
  621. ximage_convert_bgr233(PARAMS)
  622. {
  623. unsigned char r, g, b;
  624. int x,y;
  625. for(y = 0; y < h; y++) {
  626. for(x = 0; x < w; x++) {
  627. r = src[4*x + 0];
  628. g = src[4*x + 1];
  629. b = src[4*x + 2];
  630. /* format: b7 b6 g7 g6 g5 r7 r6 r5 */
  631. dst[x] = (b&0xC0) | ((g>>2)&0x38) | ((r>>5)&0x7);
  632. }
  633. src += srcstride;
  634. dst += dststride;
  635. }
  636. }
  637. static void
  638. ximage_convert_generic(PARAMS)
  639. {
  640. unsigned long rm, gm, bm, rs, gs, bs, rx, bx, gx;
  641. unsigned long pixel;
  642. unsigned long r, g, b;
  643. int x, y;
  644. rm = info.visual.red_mask;
  645. gm = info.visual.green_mask;
  646. bm = info.visual.blue_mask;
  647. rs = ffs(rm) - 1;
  648. gs = ffs(gm) - 1;
  649. bs = ffs(bm) - 1;
  650. rx = ffs(~(rm >> rs)) - 1;
  651. gx = ffs(~(gm >> gs)) - 1;
  652. bx = ffs(~(bm >> bs)) - 1;
  653. for (y = 0; y < h; y++) {
  654. for (x = 0; x < w; x++) {
  655. r = src[4*x + 0];
  656. g = src[4*x + 1];
  657. b = src[4*x + 2];
  658. /* adjust precision */
  659. if (rx < 8) r >>= (8 - rx); else if (rx > 8) r <<= (rx - 8);
  660. if (gx < 8) g >>= (8 - gx); else if (gx > 8) g <<= (gx - 8);
  661. if (bx < 8) b >>= (8 - bx); else if (bx > 8) b <<= (bx - 8);
  662. pixel = (r << rs) | (g << gs) | (b << bs);
  663. if (ImageByteOrder(info.display) == MSBFirst) {
  664. if (info.bitsperpixel > 16) {
  665. dst[4*x + 0] = (pixel >> 24) & 0xFF;
  666. dst[4*x + 1] = (pixel >> 16) & 0xFF;
  667. dst[4*x + 2] = (pixel >> 8) & 0xFF;
  668. dst[4*x + 3] = (pixel) & 0xFF;
  669. } else if (info.bitsperpixel > 8) {
  670. dst[2*x + 0] = (pixel >> 8) & 0xFF;
  671. dst[2*x + 1] = (pixel) & 0xFF;
  672. }
  673. } else {
  674. if (info.bitsperpixel > 16) {
  675. dst[4*x + 0] = (pixel) & 0xFF;
  676. dst[4*x + 1] = (pixel >> 8) & 0xFF;
  677. dst[4*x + 2] = (pixel >> 16) & 0xFF;
  678. dst[4*x + 3] = (pixel >> 24) & 0xFF;
  679. } else if (info.bitsperpixel > 8) {
  680. dst[2*x + 0] = (pixel) & 0xFF;
  681. dst[2*x + 1] = (pixel >> 8) & 0xFF;
  682. }
  683. }
  684. }
  685. src += srcstride;
  686. dst += dststride;
  687. }
  688. }
  689. ximage_convert_func_t ximage_convert_funcs[] = {
  690. ximage_convert_argb8888,
  691. ximage_convert_bgra8888,
  692. ximage_convert_rgba8888,
  693. ximage_convert_abgr8888,
  694. ximage_convert_rgb888,
  695. ximage_convert_bgr888,
  696. ximage_convert_rgb565,
  697. ximage_convert_rgb565_br,
  698. ximage_convert_rgb555,
  699. ximage_convert_rgb555_br,
  700. ximage_convert_bgr233,
  701. ximage_convert_generic
  702. };