p_32.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. {
  2. Free Pascal port of the Hermes C library.
  3. Copyright (C) 2001-2003 Nikolay Nikolov ([email protected])
  4. Original C version by Christian Nentwich ([email protected])
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version
  9. with the following modification:
  10. As a special exception, the copyright holders of this library give you
  11. permission to link this library with independent modules to produce an
  12. executable, regardless of the license terms of these independent modules,and
  13. to copy and distribute the resulting executable under terms of your choice,
  14. provided that you also meet, for each linked independent module, the terms
  15. and conditions of the license of that module. An independent module is a
  16. module which is not derived from or based on this library. If you modify
  17. this library, you may extend this exception to your version of the library,
  18. but you are not obligated to do so. If you do not wish to do so, delete this
  19. exception statement from your version.
  20. This library is distributed in the hope that it will be useful,
  21. but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  23. Lesser General Public License for more details.
  24. You should have received a copy of the GNU Lesser General Public
  25. License along with this library; if not, write to the Free Software
  26. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  27. }
  28. {
  29. 32 bit to * converters for the HERMES library
  30. Copyright (c) 1998 Christian Nentwich ([email protected])
  31. This source code is licensed under the GNU LGPL
  32. Please refer to the file COPYING.LIB contained in the distribution for
  33. licensing conditions
  34. }
  35. { -------------------------------------------------------------------------
  36. NORMAL CONVERTERS
  37. ------------------------------------------------------------------------- }
  38. { TO 32 BGR }
  39. procedure ConvertP_32rgb888_32bgr888(source, dest: PUint8; count, inc_source: DWord); cdecl;
  40. var
  41. s_pixel: Uint32;
  42. s_ptr: PUint8;
  43. tmp: Uint8;
  44. begin
  45. s_ptr := @s_pixel;
  46. repeat
  47. s_pixel := PUint32(source)^;
  48. tmp := (s_ptr + R_32)^;
  49. (s_ptr + R_32)^ := (s_ptr + B_32)^;
  50. (s_ptr + B_32)^ := tmp;
  51. PUint32(dest)^ := s_pixel;
  52. Inc(dest, 4);
  53. Inc(source, 4);
  54. Dec(count);
  55. until count = 0;
  56. end;
  57. { 32 RGBA }
  58. procedure ConvertP_32rgb888_32rgba888(source, dest: PUint8; count, inc_source: DWord); cdecl;
  59. begin
  60. repeat
  61. PUint32(dest)^ := (PUint32(source)^ shl 8) or $ff;
  62. Inc(dest, 4);
  63. Inc(source, 4);
  64. Dec(count);
  65. until count = 0;
  66. end;
  67. { 32 BGRA }
  68. procedure ConvertP_32rgb888_32bgra888(source, dest: PUint8; count, inc_source: DWord); cdecl;
  69. var
  70. s_pixel: Uint32;
  71. s_ptr: PUint8;
  72. tmp: Uint8;
  73. begin
  74. s_ptr := @s_pixel;
  75. repeat
  76. s_pixel := PUint32(source)^;
  77. tmp := (s_ptr + R_32)^;
  78. (s_ptr + R_32)^ := (s_ptr + B_32)^;
  79. (s_ptr + B_32)^ := tmp;
  80. PUint32(dest)^ := (s_pixel shl 8) or $ff;
  81. Inc(dest, 4);
  82. Inc(source, 4);
  83. Dec(count);
  84. until count = 0;
  85. end;
  86. { TO 24 RGB }
  87. procedure ConvertP_32rgb888_24rgb888(source, dest: PUint8; count, inc_source: DWord); cdecl;
  88. var
  89. s_pixel, s_pixel2: Uint32;
  90. s_point: PUint8;
  91. c: DWord;
  92. begin
  93. s_point := PUint8(@s_pixel) + (R_32 - R_24);
  94. { Align mod 4 (quite important in this case.. ) }
  95. while (PtrUInt(dest) and $3) <> 0 do
  96. begin
  97. s_pixel := PUint32(source)^;
  98. (dest + 0)^ := (s_point + 0)^;
  99. (dest + 1)^ := (s_point + 1)^;
  100. (dest + 2)^ := (s_point + 2)^;
  101. Inc(source, 4);
  102. Inc(dest, 3);
  103. Dec(count);
  104. if count = 0 then
  105. exit;
  106. end;
  107. { Main loop. }
  108. c := count shr 2;
  109. while c <> 0 do
  110. begin
  111. Dec(c);
  112. s_pixel := PUint32(source)^;
  113. s_pixel2 := (PUint32(source) + 1)^;
  114. {$IFDEF FPC_LITTLE_ENDIAN}
  115. s_pixel := (s_pixel and $ffffff) or (s_pixel2 shl 24);
  116. {$ELSE FPC_LITTLE_ENDIAN}
  117. s_pixel := (s_pixel shl 8) or ((s_pixel2 shr 16) and $FF);
  118. {$ENDIF FPC_LITTLE_ENDIAN}
  119. PUint32(dest)^ := s_pixel;
  120. s_pixel := (PUint32(source) + 2)^;
  121. {$IFDEF FPC_LITTLE_ENDIAN}
  122. s_pixel2 := ((s_pixel2 shr 8) and $ffff) or (s_pixel shl 16);
  123. {$ELSE FPC_LITTLE_ENDIAN}
  124. s_pixel2 := (s_pixel2 shl 16) or ((s_pixel shr 8) and $FFFF);
  125. {$ENDIF FPC_LITTLE_ENDIAN}
  126. (PUint32(dest) + 1)^ := s_pixel2;
  127. s_pixel2 := (PUint32(source) + 3)^;
  128. {$IFDEF FPC_LITTLE_ENDIAN}
  129. s_pixel := ((s_pixel shr 16) and $ff) or (s_pixel2 shl 8);
  130. {$ELSE FPC_LITTLE_ENDIAN}
  131. s_pixel := (s_pixel shl 24) or (s_pixel2 and $FFFFFF);
  132. {$ENDIF FPC_LITTLE_ENDIAN}
  133. (PUint32(dest) + 2)^ := s_pixel;
  134. Inc(source, 16);
  135. Inc(dest, 12);
  136. end;
  137. { Convert trailing pixels }
  138. count := count and $3;
  139. while count <> 0 do
  140. begin
  141. Dec(count);
  142. s_pixel := PUint32(source)^;
  143. (dest + 0)^ := (s_point + 0)^;
  144. (dest + 1)^ := (s_point + 1)^;
  145. (dest + 2)^ := (s_point + 2)^;
  146. Inc(source, 4);
  147. Inc(dest, 3);
  148. end;
  149. end;
  150. { TO 24 BGR }
  151. procedure ConvertP_32rgb888_24bgr888(source, dest: PUint8; count, inc_source: DWord); cdecl;
  152. var
  153. s_pixel: Uint32;
  154. s_point: PUint8;
  155. begin
  156. s_point := PUint8(@s_pixel) + (R_32 - R_24);
  157. repeat
  158. s_pixel := PUint32(source)^;
  159. { Note that R and B are swapped }
  160. (dest + 0)^ := (s_point + 2)^;
  161. (dest + 1)^ := (s_point + 1)^;
  162. (dest + 2)^ := (s_point + 0)^;
  163. Inc(source, 4);
  164. Inc(dest, 3);
  165. Dec(count);
  166. until count = 0;
  167. end;
  168. { TO 16 RGB 565 }
  169. procedure ConvertP_32rgb888_16rgb565(source, dest: PUint8; count, inc_source: DWord); cdecl;
  170. var
  171. i: DWord;
  172. s_pixel: Uint32;
  173. source_32, dest_32: PUint32;
  174. begin
  175. dest_32 := PUint32(dest);
  176. source_32 := PUint32(source);
  177. { if the current pixel isn't dword aligned, try write one pixel first }
  178. if (PtrUInt(dest_32) and $3) <> 0 then
  179. begin
  180. s_pixel := ((source_32^ shr 8) and $f800) or
  181. ((source_32^ shr 5) and $7e0) or
  182. ((source_32^ shr 3) and $1f);
  183. PUint16(dest_32)^ := s_pixel;
  184. dest_32 := PUint32(dest + 2);
  185. Inc(source_32);
  186. Dec(count);
  187. end;
  188. { Write blocks of two pixels }
  189. for i := 1 to count shr 1 do
  190. begin
  191. {This horrible construct is actually faster than loading into a variable}
  192. {$IFDEF FPC_LITTLE_ENDIAN}
  193. dest_32^ := ((source_32^ shr 8) and $f800) or
  194. ((source_32^ shr 5) and $7e0) or
  195. ((source_32^ shr 3) and $1f) or
  196. (((source_32 + 1)^ shl 8) and $f8000000) or
  197. (((source_32 + 1)^ shl 11) and $7e00000) or
  198. (((source_32 + 1)^ shl 13) and $1f0000);
  199. {$ELSE FPC_LITTLE_ENDIAN}
  200. dest_32^ := ((source_32^ shl 8) and $f8000000) or
  201. ((source_32^ shl 11) and $7e00000) or
  202. ((source_32^ shl 13) and $1f0000) or
  203. (((source_32 + 1)^ shr 8) and $f800) or
  204. (((source_32 + 1)^ shr 5) and $7e0) or
  205. (((source_32 + 1)^ shr 3) and $1f);
  206. {$ENDIF FPC_LITTLE_ENDIAN}
  207. Inc(dest_32);
  208. Inc(source_32, 2);
  209. end;
  210. { Eventually, write a single odd pixel that might be left }
  211. if (count and 1) <> 0 then
  212. begin
  213. s_pixel := source_32^;
  214. PUint16(dest_32)^ := ((s_pixel shr 8) and $f800) or
  215. ((s_pixel shr 5) and $7e0) or
  216. ((s_pixel shr 3) and $1f);
  217. end;
  218. end;
  219. { TO 16 BGR 565 }
  220. procedure ConvertP_32rgb888_16bgr565(source, dest: PUint8; count, inc_source: DWord); cdecl;
  221. var
  222. i: DWord;
  223. r, g, b: Uint32;
  224. s_pixel, d_pixelblock: Uint32;
  225. d_pixel: Uint16;
  226. begin
  227. { if the current pixel isn't dword aligned, try write one pixel first }
  228. if (PtrUInt(dest) and $3) <> 0 then
  229. begin
  230. s_pixel := PUint32(source)^;
  231. r := (s_pixel shr 19) and $1f;
  232. g := (s_pixel shr 5) and $7e0;
  233. b := (s_pixel shl 8) and $f800;
  234. d_pixel := r or g or b;
  235. PUint16(dest)^ := d_pixel;
  236. Inc(source, 4);
  237. Inc(dest, 2);
  238. Dec(count);
  239. end;
  240. { Write blocks of two pixels }
  241. for i := 1 to count shr 1 do
  242. begin
  243. s_pixel := PUint32(source)^;
  244. d_pixelblock := (((s_pixel shr 19) and $1f) or
  245. ((s_pixel shr 5) and $7e0) or
  246. ((s_pixel shl 8) and $f800)) shl DWORD_SMALLINT0_SHL;
  247. s_pixel := (PUint32(source) + 1)^;
  248. d_pixelblock := d_pixelblock or
  249. ((((s_pixel shr 19) and $1f) or
  250. ((s_pixel shr 5) and $7e0) or
  251. ((s_pixel shl 8) and $f800)) shl DWORD_SMALLINT1_SHL);
  252. PUint32(dest)^ := d_pixelblock;
  253. Inc(source, 8);
  254. Inc(dest, 4);
  255. end;
  256. { Eventually, write a single odd pixel that might be left }
  257. if (count and 1) <> 0 then
  258. begin
  259. s_pixel := PUint32(source)^;
  260. r := (s_pixel shr 19) and $1f;
  261. g := (s_pixel shr 5) and $7e0;
  262. b := (s_pixel shl 8) and $f800;
  263. d_pixel := r or g or b;
  264. PUint16(dest)^ := d_pixel;
  265. end;
  266. end;
  267. { TO 16 RGB 555 }
  268. procedure ConvertP_32rgb888_16rgb555(source, dest: PUint8; count, inc_source: DWord); cdecl;
  269. var
  270. r, g, b: Uint32;
  271. s_pixel, d_pixelblock: Uint32;
  272. d_pixel: Uint16;
  273. i: DWord;
  274. begin
  275. if (PtrUInt(dest) and $3) <> 0 then
  276. begin
  277. s_pixel := PUint32(source)^;
  278. r := (s_pixel shr 9) and $7c00;
  279. g := (s_pixel shr 6) and $3e0;
  280. b := (s_pixel shr 3) and $1f;
  281. d_pixel := r or g or b;
  282. PUint16(dest)^ := d_pixel;
  283. Inc(source, 4);
  284. Inc(dest, 2);
  285. Dec(count);
  286. end;
  287. for i := 1 to count shr 1 do
  288. begin
  289. s_pixel := PUint32(source)^;
  290. d_pixelblock := (((s_pixel shr 9) and $7c00) or
  291. ((s_pixel shr 6) and $3e0) or
  292. ((s_pixel shr 3) and $1f)) shl DWORD_SMALLINT0_SHL;
  293. s_pixel := (PUint32(source) + 1)^;
  294. d_pixelblock := d_pixelblock or
  295. ((((s_pixel shr 9) and $7c00) or
  296. ((s_pixel shr 6) and $3e0) or
  297. ((s_pixel shr 3) and $1f)) shl DWORD_SMALLINT1_SHL);
  298. PUint32(dest)^ := d_pixelblock;
  299. Inc(source, 8);
  300. Inc(dest, 4);
  301. end;
  302. if (count and 1) <> 0 then
  303. begin
  304. s_pixel := PUint32(source)^;
  305. r := (s_pixel shr 9) and $7c00;
  306. g := (s_pixel shr 6) and $3e0;
  307. b := (s_pixel shr 3) and $1f;
  308. d_pixel := r or g or b;
  309. PUint16(dest)^ := d_pixel;
  310. end;
  311. end;
  312. { TO 16 BGR 555 }
  313. procedure ConvertP_32rgb888_16bgr555(source, dest: PUint8; count, inc_source: DWord); cdecl;
  314. var
  315. r, g, b: Uint32;
  316. s_pixel, d_pixelblock: Uint32;
  317. d_pixel: Uint16;
  318. i: DWord;
  319. begin
  320. if (PtrUInt(dest) and $3) <> 0 then
  321. begin
  322. s_pixel := PUint32(source)^;
  323. r := (s_pixel shr 19) and $1f;
  324. g := (s_pixel shr 6) and $3e0;
  325. b := (s_pixel shl 7) and $7c00;
  326. d_pixel := r or g or b;
  327. PUint16(dest)^ := d_pixel;
  328. Inc(source, 4);
  329. Inc(dest, 2);
  330. Dec(count);
  331. end;
  332. for i := 1 to count shr 1 do
  333. begin
  334. s_pixel := PUint32(source)^;
  335. d_pixelblock := (((s_pixel shr 19) and $1f) or
  336. ((s_pixel shr 6) and $3e0) or
  337. ((s_pixel shl 7) and $7c00)) shl DWORD_SMALLINT0_SHL;
  338. s_pixel := (PUint32(source) + 1)^;
  339. d_pixelblock := d_pixelblock or
  340. ((((s_pixel shr 19) and $1f) or
  341. ((s_pixel shr 6) and $3e0) or
  342. ((s_pixel shl 7) and $7c00)) shl DWORD_SMALLINT1_SHL);
  343. PUint32(dest)^ := d_pixelblock;
  344. Inc(source, 8);
  345. Inc(dest, 4);
  346. end;
  347. if (count and 1) <> 0 then
  348. begin
  349. s_pixel := PUint32(source)^;
  350. r := (s_pixel shr 19) and $1f;
  351. g := (s_pixel shr 6) and $3e0;
  352. b := (s_pixel shl 7) and $7c00;
  353. d_pixel := r or g or b;
  354. PUint16(dest)^ := d_pixel;
  355. end;
  356. end;
  357. { TO 8 RGB 332 }
  358. procedure ConvertP_32rgb888_8rgb332(source, dest: PUint8; count, inc_source: DWord); cdecl;
  359. var
  360. i: DWord;
  361. s_pixel, d_block: Uint32;
  362. d_pixel: Uint8;
  363. begin
  364. { Process single pixels until we are dword aligned }
  365. while (PtrUInt(dest) and $3) <> 0 do
  366. begin
  367. s_pixel := PUint32(source)^;
  368. d_pixel := ((s_pixel shr 16) and $e0) or
  369. ((s_pixel shr 11) and $1c) or
  370. ((s_pixel shr 6) and $3);
  371. dest^ := d_pixel;
  372. Dec(count);
  373. if count = 0 then
  374. exit;
  375. Inc(dest);
  376. Inc(source, 4);
  377. end;
  378. { Now process blocks of four pixels }
  379. for i := 1 to count shr 2 do
  380. begin
  381. s_pixel := PUint32(source)^;
  382. d_block := (((s_pixel shr 16) and $e0) or
  383. ((s_pixel shr 11) and $1c) or
  384. ((s_pixel shr 6) and $3)) shl DWORD_BYTE0_SHL;
  385. s_pixel := (PUint32(source) + 1)^;
  386. d_block := ((((s_pixel shr 16) and $e0) or
  387. ((s_pixel shr 11) and $1c) or
  388. ((s_pixel shr 6) and $3)) shl DWORD_BYTE1_SHL) or d_block;
  389. s_pixel := (PUint32(source) + 2)^;
  390. d_block := ((((s_pixel shr 16) and $e0) or
  391. ((s_pixel shr 11) and $1c) or
  392. ((s_pixel shr 6) and $3)) shl DWORD_BYTE2_SHL) or d_block;
  393. s_pixel := (PUint32(source) + 3)^;
  394. d_block := ((((s_pixel shr 16) and $e0) or
  395. ((s_pixel shr 11) and $1c) or
  396. ((s_pixel shr 6) and $3)) shl DWORD_BYTE3_SHL) or d_block;
  397. PUint32(dest)^ := d_block;
  398. Inc(source, 16);
  399. Inc(dest, 4);
  400. end;
  401. { Write all possibly remaining pixel }
  402. count := count and $3;
  403. while count <> 0 do
  404. begin
  405. Dec(count);
  406. s_pixel := PUint32(source)^;
  407. dest^ := ((s_pixel shr 16) and $e0) or
  408. ((s_pixel shr 11) and $1c) or
  409. ((s_pixel shr 6) and $3);
  410. Inc(dest);
  411. Inc(source, 4);
  412. end;
  413. end;
  414. { -------------------------------------------------------------------------
  415. STRETCH CONVERTERS
  416. ------------------------------------------------------------------------- }
  417. procedure ConvertP_32rgb888_32bgr888_S(source, dest: PUint8; count, inc_source: DWord); cdecl;
  418. var
  419. x: DWord;
  420. s_pixel: Uint32;
  421. s_ptr: PUint8;
  422. tmp: Uint8;
  423. begin
  424. x := 0;
  425. s_ptr := @s_pixel;
  426. repeat
  427. s_pixel := (PUint32(source)+(x shr 16))^;
  428. tmp := (s_ptr + R_32)^;
  429. (s_ptr + R_32)^ := (s_ptr + B_32)^;
  430. (s_ptr + B_32)^ := tmp;
  431. PUint32(dest)^ := s_pixel;
  432. Inc(dest, 4);
  433. Inc(x, inc_source);
  434. Dec(count);
  435. until count = 0;
  436. end;
  437. procedure ConvertP_32rgb888_32rgba888_S(source, dest: PUint8; count, inc_source: DWord); cdecl;
  438. var
  439. x: DWord;
  440. begin
  441. x := 0;
  442. repeat
  443. PUint32(dest)^ := ((PUint32(source) + (x shr 16))^ shl 8) or $ff;
  444. Inc(dest, 4);
  445. Inc(x, inc_source);
  446. Dec(count);
  447. until count = 0;
  448. end;
  449. procedure ConvertP_32rgb888_32bgra888_S(source, dest: PUint8; count, inc_source: DWord); cdecl;
  450. var
  451. x: DWord;
  452. s_pixel: Uint32;
  453. s_ptr: PUint8;
  454. tmp: Uint8;
  455. begin
  456. x := 0;
  457. s_ptr := @s_pixel;
  458. repeat
  459. s_pixel := (PUint32(source)+(x shr 16))^;
  460. tmp := (s_ptr + R_32)^;
  461. (s_ptr + R_32)^ := (s_ptr + B_32)^;
  462. (s_ptr + B_32)^ := tmp;
  463. PUint32(dest)^ := (s_pixel shl 8) or $ff;
  464. Inc(dest, 4);
  465. Inc(x, inc_source);
  466. Dec(count);
  467. until count = 0;
  468. end;
  469. procedure ConvertP_32rgb888_24rgb888_S(source, dest: PUint8; count, inc_source: DWord); cdecl;
  470. const
  471. endian_fixup = R_32 - R_24;
  472. var
  473. x, c: DWord;
  474. s1, s2: DWord;
  475. begin
  476. x := 0;
  477. while (PtrUInt(dest) and 3) <> 0 do
  478. begin
  479. (dest + 0)^ := (source + 0 + endian_fixup)^;
  480. (dest + 1)^ := (source + 1 + endian_fixup)^;
  481. (dest + 2)^ := (source + 2 + endian_fixup)^;
  482. Inc(x, inc_source);
  483. Inc(source, (x shr 16)*4);
  484. x := x and $FFFF;
  485. Inc(dest, 3);
  486. Dec(count);
  487. if count = 0 then
  488. exit;
  489. end;
  490. c := count shr 2;
  491. while c > 0 do
  492. begin
  493. {$IFDEF FPC_LITTLE_ENDIAN}
  494. s1 := (PUint32(source) + ((x + inc_source) shr 16))^ and $FFFFFF;
  495. PUint32(dest)^ := ((PUint32(source) + (x shr 16))^ and $FFFFFF) or (s1 shl 24);
  496. s2 := (PUint32(source) + ((x + 2*inc_source) shr 16))^ and $FFFFFF;
  497. PUint32(dest + 4)^ := (s1 shr 8) or (s2 shl 16);
  498. PUint32(dest + 8)^ := (s2 shr 16) or ((PUint32(source) + ((x + 3*inc_source) shr 16))^ shl 8);
  499. {$ELSE FPC_LITTLE_ENDIAN}
  500. s1 := (PUint32(source) + ((x + inc_source) shr 16))^ and $FFFFFF;
  501. PUint32(dest)^ := ((PUint32(source) + (x shr 16))^ shl 8) or (s1 shr 16);
  502. s2 := (PUint32(source) + ((x + 2*inc_source) shr 16))^ and $FFFFFF;
  503. PUint32(dest + 4)^ := (s1 shl 16) or (s2 shr 8);
  504. PUint32(dest + 8)^ := (s2 shl 24) or ((PUint32(source) + ((x + 3*inc_source) shr 16))^ and $FFFFFF);
  505. {$ENDIF FPC_LITTLE_ENDIAN}
  506. Inc(x, 4*inc_source);
  507. Inc(dest, 12);
  508. Dec(c);
  509. end;
  510. Inc(source, (x shr 16) * 4);
  511. x := x and $FFFF;
  512. count := count and $3;
  513. while count > 0 do
  514. begin
  515. (dest + 0)^ := (source + 0 + endian_fixup)^;
  516. (dest + 1)^ := (source + 1 + endian_fixup)^;
  517. (dest + 2)^ := (source + 2 + endian_fixup)^;
  518. Inc(x, inc_source);
  519. Inc(source, (x shr 16)*4);
  520. x := x and $FFFF;
  521. Inc(dest, 3);
  522. Dec(count);
  523. end;
  524. end;
  525. procedure ConvertP_32rgb888_24bgr888_S(source, dest: PUint8; count, inc_source: DWord); cdecl;
  526. const
  527. endian_fixup = R_32 - R_24;
  528. var
  529. x, c: DWord;
  530. s1, s2, s3, s4: DWord;
  531. begin
  532. x := 0;
  533. while (PtrUInt(dest) and 3) <> 0 do
  534. begin
  535. (dest + 0)^ := (source + 2 + endian_fixup)^;
  536. (dest + 1)^ := (source + 1 + endian_fixup)^;
  537. (dest + 2)^ := (source + 0 + endian_fixup)^;
  538. Inc(x, inc_source);
  539. Inc(source, (x shr 16)*4);
  540. x := x and $FFFF;
  541. Inc(dest, 3);
  542. Dec(count);
  543. if count = 0 then
  544. exit;
  545. end;
  546. c := count shr 2;
  547. while c > 0 do
  548. begin
  549. s1 := (PUint32(source) + (x shr 16))^;
  550. s2 := (PUint32(source) + ((x + inc_source) shr 16))^;
  551. s3 := (PUint32(source) + ((x + 2*inc_source) shr 16))^;
  552. s4 := (PUint32(source) + ((x + 3*inc_source) shr 16))^;
  553. {$IFDEF FPC_LITTLE_ENDIAN}
  554. PUint32(dest + 0)^ := ((s2 and $FF0000) shl 8) or ((s1 and $FF) shl 16) or (s1 and $FF00) or ((s1 shr 16) and $FF);
  555. PUint32(dest + 4)^ := ((s3 and $FF00) shl 16) or (s3 and $FF0000) or ((s2 and $FF) shl 8) or ((s2 shr 8) and $FF);
  556. PUint32(dest + 8)^ := ((s4 and $FF) shl 24) or ((s4 and $FF00) shl 8) or ((s4 shr 8) and $FF00) or (s3 and $FF);
  557. {$ELSE FPC_LITTLE_ENDIAN}
  558. PUint32(dest + 0)^ := ((s1 and $FF) shl 24) or ((s1 and $FF00) shl 8) or ((s1 and $FF0000) shr 8) or (s2 and $FF);
  559. PUint32(dest + 4)^ := ((s2 and $FF00) shl 16) or (s2 and $FF0000) or ((s3 and $FF) shl 8) or ((s3 and $FF00) shr 8);
  560. PUint32(dest + 8)^ := ((s3 and $FF0000) shl 8) or ((s4 and $FF) shl 16) or (s4 and $FF00) or ((s4 and $FF0000) shr 16);
  561. {$ENDIF FPC_LITTLE_ENDIAN}
  562. Inc(x, 4*inc_source);
  563. Inc(dest, 12);
  564. Dec(c);
  565. end;
  566. Inc(source, (x shr 16) * 4);
  567. x := x and $FFFF;
  568. count := count and $3;
  569. while count > 0 do
  570. begin
  571. (dest + 0)^ := (source + 2 + endian_fixup)^;
  572. (dest + 1)^ := (source + 1 + endian_fixup)^;
  573. (dest + 2)^ := (source + 0 + endian_fixup)^;
  574. Inc(x, inc_source);
  575. Inc(source, (x shr 16)*4);
  576. x := x and $FFFF;
  577. Inc(dest, 3);
  578. Dec(count);
  579. end;
  580. end;
  581. procedure ConvertP_32rgb888_16rgb565_S(source, dest: PUint8; count, inc_source: DWord); cdecl;
  582. var
  583. x, c: DWord;
  584. p: Uint32;
  585. begin
  586. x := 0;
  587. { Align mod 4 }
  588. if (PtrUInt(dest) and 3) <> 0 then
  589. begin
  590. PUint16(dest)^ := (((PUint32(source) + (x shr 16))^ shr 8) and $f800) or
  591. (((PUint32(source) + (x shr 16))^ shr 5) and $7e0) or
  592. (((PUint32(source) + (x shr 16))^ shr 3) and $1f);
  593. Inc(x, inc_source);
  594. Inc(dest, 2);
  595. Dec(count);
  596. end;
  597. { Try to write 2 pixel blocks }
  598. c := count shr 1;
  599. while c <> 0 do
  600. begin
  601. Dec(c);
  602. p := ((((PUint32(source) + (x shr 16))^ shr 8) and $f800) or
  603. (((PUint32(source) + (x shr 16))^ shr 5) and $7e0) or
  604. (((PUint32(source) + (x shr 16))^ shr 3) and $1f)) shl DWORD_SMALLINT0_SHL;
  605. Inc(x, inc_source);
  606. p := p or
  607. (((((PUint32(source) + (x shr 16))^ shr 8) and $f800) or
  608. (((PUint32(source) + (x shr 16))^ shr 5) and $7e0) or
  609. (((PUint32(source) + (x shr 16))^ shr 3) and $1f)) shl DWORD_SMALLINT1_SHL);
  610. Inc(x, inc_source);
  611. PUint32(dest)^ := p;
  612. Inc(dest, 4);
  613. end;
  614. { Write trailing pixel }
  615. if (count and 1) <> 0 then
  616. PUint16(dest)^ := (((PUint32(source) + (x shr 16))^ shr 8) and $f800) or
  617. (((PUint32(source) + (x shr 16))^ shr 5) and $7e0) or
  618. (((PUint32(source) + (x shr 16))^ shr 3) and $1f);
  619. end;
  620. procedure ConvertP_32rgb888_16bgr565_S(source, dest: PUint8; count, inc_source: DWord); cdecl;
  621. var
  622. x, c: DWord;
  623. p: Uint32;
  624. begin
  625. x := 0;
  626. { Align mod 4 }
  627. if (PtrUInt(dest) and 3) <> 0 then
  628. begin
  629. PUint16(dest)^ := (((PUint32(source) + (x shr 16))^ shr 19) and $1f) or
  630. (((PUint32(source) + (x shr 16))^ shr 5) and $7e0) or
  631. (((PUint32(source) + (x shr 16))^ shl 8) and $f800);
  632. Inc(x, inc_source);
  633. Inc(dest, 2);
  634. Dec(count);
  635. end;
  636. { Try to write 2 pixel blocks }
  637. c := count shr 1;
  638. while c <> 0 do
  639. begin
  640. Dec(c);
  641. p := ((((PUint32(source) + (x shr 16))^ shr 19) and $1f) or
  642. (((PUint32(source) + (x shr 16))^ shr 5) and $7e0) or
  643. (((PUint32(source) + (x shr 16))^ shl 8) and $f800)) shl DWORD_SMALLINT0_SHL;
  644. Inc(x, inc_source);
  645. p := p or
  646. (((((PUint32(source) + (x shr 16))^ shr 19) and $1f) or
  647. (((PUint32(source) + (x shr 16))^ shr 5) and $7e0) or
  648. (((PUint32(source) + (x shr 16))^ shl 8) and $f800)) shl DWORD_SMALLINT1_SHL);
  649. Inc(x, inc_source);
  650. PUint32(dest)^ := p;
  651. Inc(dest, 4);
  652. end;
  653. { Write trailing pixel }
  654. if (count and 1) <> 0 then
  655. PUint16(dest)^ := (((PUint32(source) + (x shr 16))^ shr 19) and $1f) or
  656. (((PUint32(source) + (x shr 16))^ shr 5) and $7e0) or
  657. (((PUint32(source) + (x shr 16))^ shl 8) and $f800);
  658. end;
  659. procedure ConvertP_32rgb888_16rgb555_S(source, dest: PUint8; count, inc_source: DWord); cdecl;
  660. var
  661. x, c: DWord;
  662. p: Uint32;
  663. begin
  664. x := 0;
  665. { Align mod 4 }
  666. if (PtrUInt(dest) and 3) <> 0 then
  667. begin
  668. PUint16(dest)^ := (((PUint32(source) + (x shr 16))^ shr 9) and $7c00) or
  669. (((PUint32(source) + (x shr 16))^ shr 6) and $3e0) or
  670. (((PUint32(source) + (x shr 16))^ shr 3) and $1f);
  671. Inc(x, inc_source);
  672. Inc(dest, 2);
  673. Dec(count);
  674. end;
  675. { Try to write 2 pixel blocks }
  676. c := count shr 1;
  677. while c <> 0 do
  678. begin
  679. Dec(c);
  680. p := ((((PUint32(source) + (x shr 16))^ shr 9) and $7c00) or
  681. (((PUint32(source) + (x shr 16))^ shr 6) and $3e0) or
  682. (((PUint32(source) + (x shr 16))^ shr 3) and $1f)) shl DWORD_SMALLINT0_SHL;
  683. Inc(x, inc_source);
  684. p := p or
  685. (((((PUint32(source) + (x shr 16))^ shr 9) and $7c00) or
  686. (((PUint32(source) + (x shr 16))^ shr 6) and $3e0) or
  687. (((PUint32(source) + (x shr 16))^ shr 3) and $1f)) shl DWORD_SMALLINT1_SHL);
  688. Inc(x, inc_source);
  689. PUint32(dest)^ := p;
  690. Inc(dest, 4);
  691. end;
  692. { Write trailing pixel }
  693. if (count and 1) <> 0 then
  694. PUint16(dest)^ := (((PUint32(source) + (x shr 16))^ shr 9) and $7c00) or
  695. (((PUint32(source) + (x shr 16))^ shr 6) and $3e0) or
  696. (((PUint32(source) + (x shr 16))^ shr 3) and $1f);
  697. end;
  698. procedure ConvertP_32rgb888_16bgr555_S(source, dest: PUint8; count, inc_source: DWord); cdecl;
  699. var
  700. x, c: DWord;
  701. p: Uint32;
  702. begin
  703. x := 0;
  704. { Align mod 4 }
  705. if (PtrUInt(dest) and 3) <> 0 then
  706. begin
  707. PUint16(dest)^ := (((PUint32(source) + (x shr 16))^ shr 19) and $1f) or
  708. (((PUint32(source) + (x shr 16))^ shr 6) and $3e0) or
  709. (((PUint32(source) + (x shr 16))^ shl 7) and $7c00);
  710. Inc(x, inc_source);
  711. Inc(dest, 2);
  712. Dec(count);
  713. end;
  714. { Try to write 2 pixel blocks }
  715. c := count shr 1;
  716. while c <> 0 do
  717. begin
  718. Dec(c);
  719. p := ((((PUint32(source) + (x shr 16))^ shr 19) and $1f) or
  720. (((PUint32(source) + (x shr 16))^ shr 6) and $3e0) or
  721. (((PUint32(source) + (x shr 16))^ shl 7) and $7c00)) shl DWORD_SMALLINT0_SHL;
  722. Inc(x, inc_source);
  723. p := p or
  724. (((((PUint32(source) + (x shr 16))^ shr 19) and $1f) or
  725. (((PUint32(source) + (x shr 16))^ shr 6) and $3e0) or
  726. (((PUint32(source) + (x shr 16))^ shl 7) and $7c00)) shl DWORD_SMALLINT1_SHL);
  727. Inc(x, inc_source);
  728. PUint32(dest)^ := p;
  729. Inc(dest, 4);
  730. end;
  731. { Write trailing pixel }
  732. if (count and 1) <> 0 then
  733. PUint16(dest)^ := (((PUint32(source) + (x shr 16))^ shr 19) and $1f) or
  734. (((PUint32(source) + (x shr 16))^ shr 6) and $3e0) or
  735. (((PUint32(source) + (x shr 16))^ shl 7) and $7c00);
  736. end;
  737. procedure ConvertP_32rgb888_8rgb332_S(source, dest: PUint8; count, inc_source: DWord); cdecl;
  738. var
  739. x, c: DWord;
  740. p: Uint32;
  741. begin
  742. x := 0;
  743. { Write single pixels until the destination address is aligned mod 4 }
  744. while (PtrUInt(dest) and $3) <> 0 do
  745. begin
  746. dest^ := (((PUint32(source) + (x shr 16))^ shr 16) and $e0) or
  747. (((PUint32(source) + (x shr 16))^ shr 11) and $1c) or
  748. (((PUint32(source) + (x shr 16))^ shr 6) and $3);
  749. Inc(x, inc_source);
  750. Inc(dest);
  751. Dec(count);
  752. if count = 0 then
  753. exit;
  754. end;
  755. { Write blocks of four pixels now }
  756. c := count shr 2;
  757. while c <> 0 do
  758. begin
  759. Dec(c);
  760. p := ((((PUint32(source) + (x shr 16))^ shr 16) and $e0) or
  761. (((PUint32(source) + (x shr 16))^ shr 11) and $1c) or
  762. (((PUint32(source) + (x shr 16))^ shr 6) and $3)) shl DWORD_BYTE0_SHL;
  763. Inc(x, inc_source);
  764. p := p or
  765. (((((PUint32(source) + (x shr 16))^ shr 16) and $e0) or
  766. (((PUint32(source) + (x shr 16))^ shr 11) and $1c) or
  767. (((PUint32(source) + (x shr 16))^ shr 6) and $3)) shl DWORD_BYTE1_SHL);
  768. Inc(x, inc_source);
  769. p := p or
  770. (((((PUint32(source) + (x shr 16))^ shr 16) and $e0) or
  771. (((PUint32(source) + (x shr 16))^ shr 11) and $1c) or
  772. (((PUint32(source) + (x shr 16))^ shr 6) and $3)) shl DWORD_BYTE2_SHL);
  773. Inc(x, inc_source);
  774. p := p or
  775. (((((PUint32(source) + (x shr 16))^ shr 16) and $e0) or
  776. (((PUint32(source) + (x shr 16))^ shr 11) and $1c) or
  777. (((PUint32(source) + (x shr 16))^ shr 6) and $3)) shl DWORD_BYTE3_SHL);
  778. Inc(x, inc_source);
  779. PUint32(dest)^ := p;
  780. Inc(dest, 4);
  781. end;
  782. { Write up to three trailing pixels }
  783. c := count and $3;
  784. while c <> 0 do
  785. begin
  786. Dec(c);
  787. dest^ := (((PUint32(source) + (x shr 16))^ shr 16) and $e0) or
  788. (((PUint32(source) + (x shr 16))^ shr 11) and $1c) or
  789. (((PUint32(source) + (x shr 16))^ shr 6) and $3);
  790. Inc(x, inc_source);
  791. Inc(dest);
  792. end;
  793. end;