You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PixelFormat.cxx 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright (C) 2011 D. R. Commander. All Rights Reserved.
  3. * Copyright 2009-2014 Pierre Ossman for Cendio AB
  4. *
  5. * This is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This software is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this software; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  18. * USA.
  19. */
  20. #ifdef HAVE_CONFIG_H
  21. #include <config.h>
  22. #endif
  23. #include <assert.h>
  24. #include <stdio.h>
  25. #include <stdint.h>
  26. #include <string.h>
  27. #include <rdr/InStream.h>
  28. #include <rdr/OutStream.h>
  29. #include <rfb/Exception.h>
  30. #include <rfb/PixelFormat.h>
  31. #include <rfb/util.h>
  32. #ifdef _WIN32
  33. #define strcasecmp _stricmp
  34. #endif
  35. using namespace rfb;
  36. rdr::U8 PixelFormat::upconvTable[256*8];
  37. rdr::U8 PixelFormat::downconvTable[256*8];
  38. class PixelFormat::Init {
  39. public:
  40. Init();
  41. };
  42. PixelFormat::Init PixelFormat::_init;
  43. PixelFormat::Init::Init()
  44. {
  45. int bits;
  46. // Shifting bits is almost perfect, but not quite. And
  47. // a lookup table is still quicker when there is a large
  48. // difference between the source and destination depth.
  49. for (bits = 1;bits <= 8;bits++) {
  50. int i, maxVal;
  51. rdr::U8 *subUpTable;
  52. rdr::U8 *subDownTable;
  53. maxVal = (1 << bits) - 1;
  54. subUpTable = &upconvTable[(bits-1)*256];
  55. subDownTable = &downconvTable[(bits-1)*256];
  56. for (i = 0;i <= maxVal;i++)
  57. subUpTable[i] = i * 255 / maxVal;
  58. // Duplicate the up table so that we don't have to care about
  59. // the upper bits when doing a lookup
  60. for (;i < 256;i += maxVal+1)
  61. memcpy(&subUpTable[i], &subUpTable[0], maxVal+1);
  62. for (i = 0;i <= 255;i++)
  63. subDownTable[i] = (i * maxVal + 128) / 255;
  64. }
  65. }
  66. PixelFormat::PixelFormat(int b, int d, bool e, bool t,
  67. int rm, int gm, int bm, int rs, int gs, int bs)
  68. : bpp(b), depth(d), trueColour(t), bigEndian(e),
  69. redMax(rm), greenMax(gm), blueMax(bm),
  70. redShift(rs), greenShift(gs), blueShift(bs)
  71. {
  72. if (!isSane())
  73. throw Exception("invalid pixel format");
  74. updateState();
  75. }
  76. PixelFormat::PixelFormat()
  77. : bpp(8), depth(8), trueColour(true), bigEndian(false),
  78. redMax(7), greenMax(7), blueMax(3),
  79. redShift(0), greenShift(3), blueShift(6)
  80. {
  81. updateState();
  82. }
  83. bool PixelFormat::equal(const PixelFormat& other) const
  84. {
  85. if (bpp != other.bpp || depth != other.depth)
  86. return false;
  87. if (redMax != other.redMax)
  88. return false;
  89. if (greenMax != other.greenMax)
  90. return false;
  91. if (blueMax != other.blueMax)
  92. return false;
  93. // Endianness requires more care to determine compatibility
  94. if (bigEndian == other.bigEndian || bpp == 8) {
  95. if (redShift != other.redShift)
  96. return false;
  97. if (greenShift != other.greenShift)
  98. return false;
  99. if (blueShift != other.blueShift)
  100. return false;
  101. } else {
  102. // Has to be the same byte for each channel
  103. if (redShift/8 != (3 - other.redShift/8))
  104. return false;
  105. if (greenShift/8 != (3 - other.greenShift/8))
  106. return false;
  107. if (blueShift/8 != (3 - other.blueShift/8))
  108. return false;
  109. // And the same bit offset within the byte
  110. if (redShift%8 != other.redShift%8)
  111. return false;
  112. if (greenShift%8 != other.greenShift%8)
  113. return false;
  114. if (blueShift%8 != other.blueShift%8)
  115. return false;
  116. // And not cross a byte boundary
  117. if (redShift/8 != (redShift + redBits - 1)/8)
  118. return false;
  119. if (greenShift/8 != (greenShift + greenBits - 1)/8)
  120. return false;
  121. if (blueShift/8 != (blueShift + blueBits - 1)/8)
  122. return false;
  123. }
  124. return true;
  125. }
  126. void PixelFormat::read(rdr::InStream* is)
  127. {
  128. bpp = is->readU8();
  129. depth = is->readU8();
  130. bigEndian = is->readU8();
  131. trueColour = is->readU8();
  132. redMax = is->readU16();
  133. greenMax = is->readU16();
  134. blueMax = is->readU16();
  135. redShift = is->readU8();
  136. greenShift = is->readU8();
  137. blueShift = is->readU8();
  138. is->skip(3);
  139. // We have no real support for colour maps. If the client
  140. // wants one, then we force a 8-bit true colour format and
  141. // pretend it's a colour map.
  142. if (!trueColour) {
  143. redMax = 7;
  144. greenMax = 7;
  145. blueMax = 3;
  146. redShift = 0;
  147. greenShift = 3;
  148. blueShift = 6;
  149. }
  150. if (!isSane())
  151. throw Exception("invalid pixel format");
  152. updateState();
  153. }
  154. void PixelFormat::write(rdr::OutStream* os) const
  155. {
  156. os->writeU8(bpp);
  157. os->writeU8(depth);
  158. os->writeU8(bigEndian);
  159. os->writeU8(trueColour);
  160. os->writeU16(redMax);
  161. os->writeU16(greenMax);
  162. os->writeU16(blueMax);
  163. os->writeU8(redShift);
  164. os->writeU8(greenShift);
  165. os->writeU8(blueShift);
  166. os->pad(3);
  167. }
  168. bool PixelFormat::is888(void) const
  169. {
  170. if (!trueColour)
  171. return false;
  172. if (bpp != 32)
  173. return false;
  174. if (depth != 24)
  175. return false;
  176. if (redMax != 255)
  177. return false;
  178. if (greenMax != 255)
  179. return false;
  180. if (blueMax != 255)
  181. return false;
  182. if ((redShift & 0x7) != 0)
  183. return false;
  184. if ((greenShift & 0x7) != 0)
  185. return false;
  186. if ((blueShift & 0x7) != 0)
  187. return false;
  188. return true;
  189. }
  190. bool PixelFormat::isBigEndian(void) const
  191. {
  192. return bigEndian;
  193. }
  194. bool PixelFormat::isLittleEndian(void) const
  195. {
  196. return ! bigEndian;
  197. }
  198. void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels) const
  199. {
  200. bufferFromRGB(dst, src, pixels, pixels, 1);
  201. }
  202. void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
  203. int w, int stride, int h) const
  204. {
  205. if (is888()) {
  206. // Optimised common case
  207. rdr::U8 *r, *g, *b, *x;
  208. if (bigEndian) {
  209. r = dst + (24 - redShift)/8;
  210. g = dst + (24 - greenShift)/8;
  211. b = dst + (24 - blueShift)/8;
  212. x = dst + (24 - (48 - redShift - greenShift - blueShift))/8;
  213. } else {
  214. r = dst + redShift/8;
  215. g = dst + greenShift/8;
  216. b = dst + blueShift/8;
  217. x = dst + (48 - redShift - greenShift - blueShift)/8;
  218. }
  219. int dstPad = (stride - w) * 4;
  220. while (h--) {
  221. int w_ = w;
  222. while (w_--) {
  223. *r = *(src++);
  224. *g = *(src++);
  225. *b = *(src++);
  226. *x = 0;
  227. r += 4;
  228. g += 4;
  229. b += 4;
  230. x += 4;
  231. }
  232. r += dstPad;
  233. g += dstPad;
  234. b += dstPad;
  235. x += dstPad;
  236. }
  237. } else {
  238. // Generic code
  239. int dstPad = (stride - w) * bpp/8;
  240. while (h--) {
  241. int w_ = w;
  242. while (w_--) {
  243. Pixel p;
  244. rdr::U8 r, g, b;
  245. r = *(src++);
  246. g = *(src++);
  247. b = *(src++);
  248. p = pixelFromRGB(r, g, b);
  249. bufferFromPixel(dst, p);
  250. dst += bpp/8;
  251. }
  252. dst += dstPad;
  253. }
  254. }
  255. }
  256. void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels) const
  257. {
  258. rgbFromBuffer(dst, src, pixels, pixels, 1);
  259. }
  260. void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src,
  261. int w, int stride, int h) const
  262. {
  263. if (is888()) {
  264. // Optimised common case
  265. const rdr::U8 *r, *g, *b;
  266. if (bigEndian) {
  267. r = src + (24 - redShift)/8;
  268. g = src + (24 - greenShift)/8;
  269. b = src + (24 - blueShift)/8;
  270. } else {
  271. r = src + redShift/8;
  272. g = src + greenShift/8;
  273. b = src + blueShift/8;
  274. }
  275. int srcPad = (stride - w) * 4;
  276. while (h--) {
  277. int w_ = w;
  278. while (w_--) {
  279. *(dst++) = *r;
  280. *(dst++) = *g;
  281. *(dst++) = *b;
  282. r += 4;
  283. g += 4;
  284. b += 4;
  285. }
  286. r += srcPad;
  287. g += srcPad;
  288. b += srcPad;
  289. }
  290. } else {
  291. // Generic code
  292. int srcPad = (stride - w) * bpp/8;
  293. while (h--) {
  294. int w_ = w;
  295. while (w_--) {
  296. Pixel p;
  297. rdr::U8 r, g, b;
  298. p = pixelFromBuffer(src);
  299. rgbFromPixel(p, &r, &g, &b);
  300. *(dst++) = r;
  301. *(dst++) = g;
  302. *(dst++) = b;
  303. src += bpp/8;
  304. }
  305. src += srcPad;
  306. }
  307. }
  308. }
  309. Pixel PixelFormat::pixelFromPixel(const PixelFormat &srcPF, Pixel src) const
  310. {
  311. rdr::U16 r, g, b;
  312. srcPF.rgbFromPixel(src, &r, &g, &b);
  313. return pixelFromRGB(r, g, b);
  314. }
  315. void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF,
  316. const rdr::U8* src, int pixels) const
  317. {
  318. bufferFromBuffer(dst, srcPF, src, pixels, 1, pixels, pixels);
  319. }
  320. #define IS_ALIGNED(v, a) (((intptr_t)v & (a-1)) == 0)
  321. void PixelFormat::bufferFromBuffer(rdr::U8* dst, const PixelFormat &srcPF,
  322. const rdr::U8* src, int w, int h,
  323. int dstStride, int srcStride) const
  324. {
  325. if (equal(srcPF)) {
  326. // Trivial case
  327. while (h--) {
  328. memcpy(dst, src, w * bpp/8);
  329. dst += dstStride * bpp/8;
  330. src += srcStride * srcPF.bpp/8;
  331. }
  332. } else if (is888() && srcPF.is888()) {
  333. // Optimised common case A: byte shuffling (e.g. endian conversion)
  334. rdr::U8 *d[4], *s[4];
  335. int dstPad, srcPad;
  336. if (bigEndian) {
  337. s[0] = dst + (24 - redShift)/8;
  338. s[1] = dst + (24 - greenShift)/8;
  339. s[2] = dst + (24 - blueShift)/8;
  340. s[3] = dst + (24 - (48 - redShift - greenShift - blueShift))/8;
  341. } else {
  342. s[0] = dst + redShift/8;
  343. s[1] = dst + greenShift/8;
  344. s[2] = dst + blueShift/8;
  345. s[3] = dst + (48 - redShift - greenShift - blueShift)/8;
  346. }
  347. if (srcPF.bigEndian) {
  348. d[(24 - srcPF.redShift)/8] = s[0];
  349. d[(24 - srcPF.greenShift)/8] = s[1];
  350. d[(24 - srcPF.blueShift)/8] = s[2];
  351. d[(24 - (48 - srcPF.redShift - srcPF.greenShift - srcPF.blueShift))/8] = s[3];
  352. } else {
  353. d[srcPF.redShift/8] = s[0];
  354. d[srcPF.greenShift/8] = s[1];
  355. d[srcPF.blueShift/8] = s[2];
  356. d[(48 - srcPF.redShift - srcPF.greenShift - srcPF.blueShift)/8] = s[3];
  357. }
  358. dstPad = (dstStride - w) * 4;
  359. srcPad = (srcStride - w) * 4;
  360. while (h--) {
  361. int w_ = w;
  362. while (w_--) {
  363. *d[0] = *(src++);
  364. *d[1] = *(src++);
  365. *d[2] = *(src++);
  366. *d[3] = *(src++);
  367. d[0] += 4;
  368. d[1] += 4;
  369. d[2] += 4;
  370. d[3] += 4;
  371. }
  372. d[0] += dstPad;
  373. d[1] += dstPad;
  374. d[2] += dstPad;
  375. d[3] += dstPad;
  376. src += srcPad;
  377. }
  378. } else if (IS_ALIGNED(dst, bpp/8) && srcPF.is888()) {
  379. // Optimised common case B: 888 source
  380. switch (bpp) {
  381. case 8:
  382. directBufferFromBufferFrom888((rdr::U8*)dst, srcPF, src,
  383. w, h, dstStride, srcStride);
  384. break;
  385. case 16:
  386. directBufferFromBufferFrom888((rdr::U16*)dst, srcPF, src,
  387. w, h, dstStride, srcStride);
  388. break;
  389. case 32:
  390. directBufferFromBufferFrom888((rdr::U32*)dst, srcPF, src,
  391. w, h, dstStride, srcStride);
  392. break;
  393. }
  394. } else if (IS_ALIGNED(src, srcPF.bpp/8) && is888()) {
  395. // Optimised common case C: 888 destination
  396. switch (srcPF.bpp) {
  397. case 8:
  398. directBufferFromBufferTo888(dst, srcPF, (rdr::U8*)src,
  399. w, h, dstStride, srcStride);
  400. break;
  401. case 16:
  402. directBufferFromBufferTo888(dst, srcPF, (rdr::U16*)src,
  403. w, h, dstStride, srcStride);
  404. break;
  405. case 32:
  406. directBufferFromBufferTo888(dst, srcPF, (rdr::U32*)src,
  407. w, h, dstStride, srcStride);
  408. break;
  409. }
  410. } else {
  411. // Generic code
  412. int dstPad = (dstStride - w) * bpp/8;
  413. int srcPad = (srcStride - w) * srcPF.bpp/8;
  414. while (h--) {
  415. int w_ = w;
  416. while (w_--) {
  417. Pixel p;
  418. rdr::U8 r, g, b;
  419. p = srcPF.pixelFromBuffer(src);
  420. srcPF.rgbFromPixel(p, &r, &g, &b);
  421. p = pixelFromRGB(r, g, b);
  422. bufferFromPixel(dst, p);
  423. dst += bpp/8;
  424. src += srcPF.bpp/8;
  425. }
  426. dst += dstPad;
  427. src += srcPad;
  428. }
  429. }
  430. }
  431. void PixelFormat::print(char* str, int len) const
  432. {
  433. // Unfortunately snprintf is not widely available so we build the string up
  434. // using strncat - not pretty, but should be safe against buffer overruns.
  435. char num[20];
  436. if (len < 1) return;
  437. str[0] = 0;
  438. strncat(str, "depth ", len-1-strlen(str));
  439. sprintf(num,"%d",depth);
  440. strncat(str, num, len-1-strlen(str));
  441. strncat(str, " (", len-1-strlen(str));
  442. sprintf(num,"%d",bpp);
  443. strncat(str, num, len-1-strlen(str));
  444. strncat(str, "bpp)", len-1-strlen(str));
  445. if (bpp != 8) {
  446. if (bigEndian)
  447. strncat(str, " big-endian", len-1-strlen(str));
  448. else
  449. strncat(str, " little-endian", len-1-strlen(str));
  450. }
  451. if (!trueColour) {
  452. strncat(str, " color-map", len-1-strlen(str));
  453. return;
  454. }
  455. if (blueShift == 0 && greenShift > blueShift && redShift > greenShift &&
  456. blueMax == (1 << greenShift) - 1 &&
  457. greenMax == (1 << (redShift-greenShift)) - 1 &&
  458. redMax == (1 << (depth-redShift)) - 1)
  459. {
  460. strncat(str, " rgb", len-1-strlen(str));
  461. sprintf(num,"%d",depth-redShift);
  462. strncat(str, num, len-1-strlen(str));
  463. sprintf(num,"%d",redShift-greenShift);
  464. strncat(str, num, len-1-strlen(str));
  465. sprintf(num,"%d",greenShift);
  466. strncat(str, num, len-1-strlen(str));
  467. return;
  468. }
  469. if (redShift == 0 && greenShift > redShift && blueShift > greenShift &&
  470. redMax == (1 << greenShift) - 1 &&
  471. greenMax == (1 << (blueShift-greenShift)) - 1 &&
  472. blueMax == (1 << (depth-blueShift)) - 1)
  473. {
  474. strncat(str, " bgr", len-1-strlen(str));
  475. sprintf(num,"%d",depth-blueShift);
  476. strncat(str, num, len-1-strlen(str));
  477. sprintf(num,"%d",blueShift-greenShift);
  478. strncat(str, num, len-1-strlen(str));
  479. sprintf(num,"%d",greenShift);
  480. strncat(str, num, len-1-strlen(str));
  481. return;
  482. }
  483. strncat(str, " rgb max ", len-1-strlen(str));
  484. sprintf(num,"%d,",redMax);
  485. strncat(str, num, len-1-strlen(str));
  486. sprintf(num,"%d,",greenMax);
  487. strncat(str, num, len-1-strlen(str));
  488. sprintf(num,"%d",blueMax);
  489. strncat(str, num, len-1-strlen(str));
  490. strncat(str, " shift ", len-1-strlen(str));
  491. sprintf(num,"%d,",redShift);
  492. strncat(str, num, len-1-strlen(str));
  493. sprintf(num,"%d,",greenShift);
  494. strncat(str, num, len-1-strlen(str));
  495. sprintf(num,"%d",blueShift);
  496. strncat(str, num, len-1-strlen(str));
  497. }
  498. bool PixelFormat::parse(const char* str)
  499. {
  500. char rgbbgr[4];
  501. int bits1, bits2, bits3;
  502. if (sscanf(str, "%3s%1d%1d%1d", rgbbgr, &bits1, &bits2, &bits3) < 4)
  503. return false;
  504. depth = bits1 + bits2 + bits3;
  505. bpp = depth <= 8 ? 8 : ((depth <= 16) ? 16 : 32);
  506. trueColour = true;
  507. rdr::U32 endianTest = 1;
  508. bigEndian = (*(rdr::U8*)&endianTest == 0);
  509. greenShift = bits3;
  510. greenMax = (1 << bits2) - 1;
  511. if (strcasecmp(rgbbgr, "bgr") == 0) {
  512. redShift = 0;
  513. redMax = (1 << bits3) - 1;
  514. blueShift = bits3 + bits2;
  515. blueMax = (1 << bits1) - 1;
  516. } else if (strcasecmp(rgbbgr, "rgb") == 0) {
  517. blueShift = 0;
  518. blueMax = (1 << bits3) - 1;
  519. redShift = bits3 + bits2;
  520. redMax = (1 << bits1) - 1;
  521. } else {
  522. return false;
  523. }
  524. assert(isSane());
  525. updateState();
  526. return true;
  527. }
  528. static int bits(rdr::U16 value)
  529. {
  530. int bits;
  531. bits = 16;
  532. if (!(value & 0xff00)) {
  533. bits -= 8;
  534. value <<= 8;
  535. }
  536. if (!(value & 0xf000)) {
  537. bits -= 4;
  538. value <<= 4;
  539. }
  540. if (!(value & 0xc000)) {
  541. bits -= 2;
  542. value <<= 2;
  543. }
  544. if (!(value & 0x8000)) {
  545. bits -= 1;
  546. value <<= 1;
  547. }
  548. return bits;
  549. }
  550. void PixelFormat::updateState(void)
  551. {
  552. int endianTest = 1;
  553. redBits = bits(redMax);
  554. greenBits = bits(greenMax);
  555. blueBits = bits(blueMax);
  556. maxBits = redBits;
  557. if (greenBits > maxBits)
  558. maxBits = greenBits;
  559. if (blueBits > maxBits)
  560. maxBits = blueBits;
  561. minBits = redBits;
  562. if (greenBits < minBits)
  563. minBits = greenBits;
  564. if (blueBits < minBits)
  565. minBits = blueBits;
  566. if (((*(char*)&endianTest) == 0) != bigEndian)
  567. endianMismatch = true;
  568. else
  569. endianMismatch = false;
  570. }
  571. bool PixelFormat::isSane(void)
  572. {
  573. int totalBits;
  574. if ((bpp != 8) && (bpp != 16) && (bpp != 32))
  575. return false;
  576. if (depth > bpp)
  577. return false;
  578. if (!trueColour && (depth != 8))
  579. return false;
  580. if ((redMax & (redMax + 1)) != 0)
  581. return false;
  582. if ((greenMax & (greenMax + 1)) != 0)
  583. return false;
  584. if ((blueMax & (blueMax + 1)) != 0)
  585. return false;
  586. /*
  587. * We don't allow individual channels > 8 bits in order to keep our
  588. * conversions simple.
  589. */
  590. if (redMax >= (1 << 8))
  591. return false;
  592. if (greenMax >= (1 << 8))
  593. return false;
  594. if (blueMax >= (1 << 8))
  595. return false;
  596. totalBits = bits(redMax) + bits(greenMax) + bits(blueMax);
  597. if (totalBits > depth)
  598. return false;
  599. if ((bits(redMax) + redShift) > bpp)
  600. return false;
  601. if ((bits(greenMax) + greenShift) > bpp)
  602. return false;
  603. if ((bits(blueMax) + blueShift) > bpp)
  604. return false;
  605. if (((redMax << redShift) & (greenMax << greenShift)) != 0)
  606. return false;
  607. if (((redMax << redShift) & (blueMax << blueShift)) != 0)
  608. return false;
  609. if (((greenMax << greenShift) & (blueMax << blueShift)) != 0)
  610. return false;
  611. return true;
  612. }
  613. // Preprocessor generated, optimised methods
  614. #define INBPP 8
  615. #define OUTBPP 8
  616. #include "PixelFormatBPP.cxx"
  617. #undef OUTBPP
  618. #define OUTBPP 16
  619. #include "PixelFormatBPP.cxx"
  620. #undef OUTBPP
  621. #define OUTBPP 32
  622. #include "PixelFormatBPP.cxx"
  623. #undef OUTBPP
  624. #undef INBPP
  625. #define INBPP 16
  626. #define OUTBPP 8
  627. #include "PixelFormatBPP.cxx"
  628. #undef OUTBPP
  629. #define OUTBPP 16
  630. #include "PixelFormatBPP.cxx"
  631. #undef OUTBPP
  632. #define OUTBPP 32
  633. #include "PixelFormatBPP.cxx"
  634. #undef OUTBPP
  635. #undef INBPP
  636. #define INBPP 32
  637. #define OUTBPP 8
  638. #include "PixelFormatBPP.cxx"
  639. #undef OUTBPP
  640. #define OUTBPP 16
  641. #include "PixelFormatBPP.cxx"
  642. #undef OUTBPP
  643. #define OUTBPP 32
  644. #include "PixelFormatBPP.cxx"
  645. #undef OUTBPP
  646. #undef INBPP