convtest.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. program convtest;
  2. {$MODE objfpc}
  3. {$I endian.inc}
  4. uses
  5. SysUtils, ptc;
  6. const
  7. destXSize = {480}320;
  8. destYSize = {300}200;
  9. var
  10. image: TPTCSurface = nil;
  11. surface: TPTCSurface = nil;
  12. format: TPTCFormat = nil;
  13. TestNum: Integer;
  14. function fb(q: Uint32): Integer;
  15. begin
  16. fb := 0;
  17. while (q and 1) = 0 do
  18. begin
  19. Inc(fb);
  20. q := q shr 1;
  21. end;
  22. end;
  23. function nb(q: Uint32): Integer;
  24. begin
  25. nb := 0;
  26. while q <> 0 do
  27. begin
  28. Inc(nb);
  29. q := q and (q - 1);
  30. end;
  31. end;
  32. procedure generic(src, dest: TPTCSurface);
  33. var
  34. X, Y: Integer;
  35. XSize, YSize: Integer;
  36. r, g, b: Uint32;
  37. pix: Uint32;
  38. Psrc, Pdest: PUint8;
  39. srcbits: Integer;
  40. Srmask, Sgmask, Sbmask: Uint32;
  41. Srmasknb, Sgmasknb, Sbmasknb: Integer;
  42. Srmaskfb, Sgmaskfb, Sbmaskfb: Integer;
  43. destbits: Integer;
  44. Drmask, Dgmask, Dbmask: Uint32;
  45. Drmasknb, Dgmasknb, Dbmasknb: Integer;
  46. Drmaskfb, Dgmaskfb, Dbmaskfb: Integer;
  47. begin
  48. XSize := dest.width;
  49. YSize := dest.height;
  50. srcbits := src.format.bits;
  51. Srmask := src.format.r;
  52. Sgmask := src.format.g;
  53. Sbmask := src.format.b;
  54. Srmasknb := nb(Srmask);
  55. Sgmasknb := nb(Sgmask);
  56. Sbmasknb := nb(Sbmask);
  57. Srmaskfb := fb(Srmask);
  58. Sgmaskfb := fb(Sgmask);
  59. Sbmaskfb := fb(Sbmask);
  60. destbits := dest.format.bits;
  61. Drmask := dest.format.r;
  62. Dgmask := dest.format.g;
  63. Dbmask := dest.format.b;
  64. Drmasknb := nb(Drmask);
  65. Dgmasknb := nb(Dgmask);
  66. Dbmasknb := nb(Dbmask);
  67. Drmaskfb := fb(Drmask);
  68. Dgmaskfb := fb(Dgmask);
  69. Dbmaskfb := fb(Dbmask);
  70. { Writeln(Srmasknb, ' ', Drmasknb);}
  71. Psrc := src.lock;
  72. try
  73. Pdest := dest.lock;
  74. try
  75. for Y := 0 to YSize - 1 do
  76. for X := 0 to XSize - 1 do
  77. begin
  78. case srcbits of
  79. 32: begin
  80. pix := (PUint32(Psrc))^;
  81. Inc(Psrc, 4);
  82. end;
  83. 24: begin
  84. {$IFDEF FPC_LITTLE_ENDIAN}
  85. pix := (Psrc^) or ((Psrc + 1)^ shl 8) or ((Psrc + 2)^ shl 16);
  86. {$ELSE FPC_LITTLE_ENDIAN}
  87. pix := (Psrc^ shl 16) or ((Psrc + 1)^ shl 8) or ((Psrc + 2)^);
  88. {$ENDIF FPC_LITTLE_ENDIAN}
  89. Inc(Psrc, 3);
  90. end;
  91. 16: begin
  92. pix := (PUint16(Psrc))^;
  93. Inc(Psrc, 2);
  94. end;
  95. 8: begin
  96. pix := Psrc^;
  97. Inc(Psrc);
  98. end;
  99. end;
  100. r := pix and Srmask;
  101. g := pix and Sgmask;
  102. b := pix and Sbmask;
  103. r := r shr Srmaskfb;
  104. g := g shr Sgmaskfb;
  105. b := b shr Sbmaskfb;
  106. if (Drmasknb - Srmasknb) >= 0 then
  107. r := r shl (Drmasknb - Srmasknb)
  108. else
  109. r := r shr (Srmasknb - Drmasknb);
  110. if (Dgmasknb - Sgmasknb) >= 0 then
  111. g := g shl (Dgmasknb - Sgmasknb)
  112. else
  113. g := g shr (Sgmasknb - Dgmasknb);
  114. if (Dbmasknb - Sbmasknb) >= 0 then
  115. b := b shl (Dbmasknb - Sbmasknb)
  116. else
  117. b := b shr (Sbmasknb - Dbmasknb);
  118. r := r shl Drmaskfb;
  119. g := g shl Dgmaskfb;
  120. b := b shl Dbmaskfb;
  121. pix := r or g or b;
  122. case destbits of
  123. 32: begin
  124. (PUint32(Pdest))^ := pix;
  125. Inc(Pdest, 4);
  126. end;
  127. 24: begin
  128. {$IFDEF FPC_LITTLE_ENDIAN}
  129. Pdest^ := pix and $FF;
  130. (Pdest + 1)^ := (pix shr 8) and $FF;
  131. (Pdest + 2)^ := (pix shr 16) and $FF;
  132. {$ELSE FPC_LITTLE_ENDIAN}
  133. Pdest^ := (pix shr 16) and $FF;
  134. (Pdest + 1)^ := (pix shr 8) and $FF;
  135. (Pdest + 2)^ := pix and $FF;
  136. {$ENDIF FPC_LITTLE_ENDIAN}
  137. Inc(Pdest, 3);
  138. end;
  139. 16: begin
  140. (PUint16(Pdest))^ := pix;
  141. Inc(Pdest, 2);
  142. end;
  143. 8: begin
  144. Pdest^ := pix;
  145. Inc(Pdest);
  146. end;
  147. end;
  148. end;
  149. finally
  150. dest.unlock;
  151. end;
  152. finally
  153. src.unlock;
  154. end;
  155. end;
  156. procedure test(sbits: Integer; sr, sg, sb: Uint32;
  157. dbits: Integer; dr, dg, db: Uint32; da: Uint32 = 0;
  158. dithering: Boolean = False);
  159. var
  160. srcformat, destformat: TPTCFormat;
  161. src, dest: TPTCSurface;
  162. pixels: Pointer;
  163. F: File;
  164. begin
  165. Writeln(sbits, ' ', sr, ' ', sg, ' ', sb, ' ', dbits, ' ', dr, ' ', dg, ' ', db, ' ', da);
  166. try
  167. srcformat := TPTCFormat.Create(sbits, sr, sg, sb);
  168. destformat := TPTCFormat.Create(dbits, dr, dg, db, da);
  169. src := TPTCSurface.Create(320, 200, srcformat);
  170. dest := TPTCSurface.Create(destXSize, destYSize, destformat);
  171. if dithering then
  172. dest.Option('attempt dithering');
  173. generic(image, src);
  174. src.copy(dest);
  175. { generic(src, dest);}
  176. generic(dest, surface);
  177. finally
  178. src.Free;
  179. dest.Free;
  180. srcformat.Free;
  181. destformat.Free;
  182. end;
  183. Inc(TestNum);
  184. AssignFile(F, 'test' + IntToStr(TestNum) + '.raw');
  185. Rewrite(F, 1);
  186. try
  187. pixels := surface.lock;
  188. try
  189. BlockWrite(F, pixels^, surface.height * surface.pitch);
  190. finally
  191. surface.unlock;
  192. end;
  193. finally
  194. CloseFile(F);
  195. end;
  196. end;
  197. procedure load(surface: TPTCSurface; filename: String);
  198. var
  199. F: File;
  200. width, height: Integer;
  201. pixels: PByte;
  202. y: Integer;
  203. begin
  204. AssignFile(F, filename);
  205. Reset(F, 1);
  206. try
  207. Seek(F, 18);
  208. width := surface.width;
  209. height := surface.height;
  210. pixels := surface.lock;
  211. try
  212. for y := height - 1 downto 0 do
  213. BlockRead(F, pixels[width * y * 3], width * 3);
  214. finally
  215. surface.unlock;
  216. end;
  217. finally
  218. CloseFile(F);
  219. end;
  220. end;
  221. begin
  222. TestNum := 0;
  223. try
  224. try
  225. {$IFDEF FPC_LITTLE_ENDIAN}
  226. format := TPTCFormat.Create(24, $00FF0000, $0000FF00, $000000FF);
  227. {$ELSE FPC_LITTLE_ENDIAN}
  228. format := TPTCFormat.Create(24, $000000FF, $0000FF00, $00FF0000);
  229. {$ENDIF FPC_LITTLE_ENDIAN}
  230. surface := TPTCSurface.Create(destXSize, destYSize, format);
  231. image := TPTCSurface.Create(320, 200, format);
  232. load(image, '../examples/image.tga');
  233. Writeln('testing equal converters');
  234. {test equal converters}
  235. test(32, $00FF0000, $0000FF00, $000000FF, 32, $00FF0000, $0000FF00, $000000FF); { 1 }
  236. test(24, $FF0000, $00FF00, $0000FF, 24, $FF0000, $00FF00, $0000FF); { 2 }
  237. test(16, $F800, $07E0, $001F, 16, $F800,$07E0, $001F); { 3 }
  238. test( 8, $E0, $1C, $03, 8, $E0, $1C, $03); { 4 }
  239. Writeln('testing generic converters');
  240. {test generic}
  241. test(32, $FF000000, $000000FF, $000FF000, 32, $000FF000, $0FF00000, $000000FF); { 5 }
  242. test(32, $FF000000, $000000FF, $000FF000, 24, $00FF00, $FF0000, $000000FF); { 6 }
  243. test(32, $FF000000, $000000FF, $000FF000, 16, $F000, $0F00, $00F0); { 7 }
  244. test(32, $FF000000, $000000FF, $000FF000, 8, $0C, $03, $F0); { 8 }
  245. test(24, $FF0000, $0000FF, $00FF00, 32, $000FF000, $0FF00000, $000000FF); { 9 }
  246. test(24, $FF0000, $0000FF, $00FF00, 24, $00FF00, $FF0000, $000000FF); { 10 }
  247. test(24, $FF0000, $0000FF, $00FF00, 16, $F000, $0F00, $00F0); { 11 }
  248. test(24, $FF0000, $0000FF, $00FF00, 8, $0C, $03, $F0); { 12 }
  249. test(16, $001F, $F800, $07E0, 32, $000FF000, $0FF00000, $000000FF); { 13 }
  250. test(16, $001F, $F800, $07E0, 24, $00FF00, $FF0000, $000000FF); { 14 }
  251. test(16, $001F, $F800, $07E0, 16, $F000, $0F00, $00F0); { 15 }
  252. test(16, $001F, $F800, $07E0, 8, $0C, $03, $F0); { 16 }
  253. // test(8, $03, $E0, $1C, 32, $000FF000, $0FF00000, $000000FF); {unsupported}
  254. // test(8, $03, $E0, $1C, 24, $00FF00, $FF0000, $000000FF); {unsupported}
  255. // test(8, $03, $E0, $1C, 16, $F000, $0F00, $00F0); {unsupported}
  256. // test(8, $03, $E0, $1C, 8, $0C, $03, $F0); {unsupported}
  257. Writeln('testing specialized converters');
  258. {From 32 bit RGB 888}
  259. test(32,$ff0000,$ff00,$ff,16,$f800,$7e0,$1f); { 16RGB565 } { 17 }
  260. test(32,$ff0000,$ff00,$ff, 8,$e0,$1c,$3); { 8RGB332 } { 18 }
  261. test(32,$ff0000,$ff00,$ff,16,$7c00,$3e0,$1f); { 16RGB555 } { 19 }
  262. test(32,$ff0000,$ff00,$ff,24,$ff0000,$ff00,$ff); { 24RGB888 } { 20 }
  263. test(32,$ff0000,$ff00,$ff,32,$ff,$ff00,$ff0000); { 32BGR888 } { 21 }
  264. test(32,$ff0000,$ff00,$ff,16,$1f,$7e0,$f800); { 16BGR565 } { 22 }
  265. test(32,$ff0000,$ff00,$ff,16,$1f,$3e0,$7c00); { 16BGR555 } { 23 }
  266. test(32,$ff0000,$ff00,$ff,32,$ff000000,$ff0000,$ff00,$ff); { 32RGBA888 } { 24 }
  267. test(32,$ff0000,$ff00,$ff,32,$ff00,$ff0000,$ff000000,$ff); { 32BGRA888 } { 25 }
  268. test(32,$ff0000,$ff00,$ff,24,$ff,$ff00,$ff0000); { 24BGR888 } { 26 }
  269. {From 24 bit RGB 888}
  270. test(24,$ff0000,$ff00,$ff,32,$ff0000,$ff00,$ff); { 32RGB888 } { 27 }
  271. test(24,$ff0000,$ff00,$ff,16,$f800,$7e0,$1f); { 16RGB565 } { 28 }
  272. test(24,$ff0000,$ff00,$ff, 8,$e0,$1c,$3); { 8RGB332 } { 29 }
  273. test(24,$ff0000,$ff00,$ff,16,$7c00,$3e0,$1f); { 16RGB555 } { 30 }
  274. test(24,$ff0000,$ff00,$ff,32,$ff,$ff00,$ff0000); { 32BGR888 } { 31 }
  275. test(24,$ff0000,$ff00,$ff,16,$1f,$7e0,$f800); { 16BGR565 } { 32 }
  276. test(24,$ff0000,$ff00,$ff,16,$1f,$3e0,$7c00); { 16BGR555 } { 33 }
  277. test(24,$ff0000,$ff00,$ff,32,$ff000000,$ff0000,$ff00,$ff); { 32RGBA888 } { 34 }
  278. test(24,$ff0000,$ff00,$ff,32,$ff00,$ff0000,$ff000000,$ff); { 32BGRA888 } { 35 }
  279. test(24,$ff0000,$ff00,$ff,24,$ff,$ff00,$ff0000); { 24BGR888 } { 36 }
  280. {From 16 bit RGB 565}
  281. test(16,$f800,$7e0,$1f,32,$ff0000,$ff00,$ff); { 32RGB888 } { 37 }
  282. test(16,$f800,$7e0,$1f, 8,$e0,$1c,$3); { 8RGB332 } { 38 }
  283. test(16,$f800,$7e0,$1f,16,$7c00,$3e0,$1f); { 16RGB555 } { 39 }
  284. test(16,$f800,$7e0,$1f,24,$ff0000,$ff00,$ff); { 24RGB888 } { 40 }
  285. test(16,$f800,$7e0,$1f,32,$ff,$ff00,$ff0000); { 32BGR888 } { 41 }
  286. test(16,$f800,$7e0,$1f,16,$1f,$7e0,$f800); { 16BGR565 } { 42 }
  287. test(16,$f800,$7e0,$1f,16,$1f,$3e0,$7c00); { 16BGR555 } { 43 }
  288. test(16,$f800,$7e0,$1f,32,$ff000000,$ff0000,$ff00,$ff); { 32RGBA888 } { 44 }
  289. test(16,$f800,$7e0,$1f,32,$ff00,$ff0000,$ff000000,$ff); { 32BGRA888 } { 45 }
  290. test(16,$f800,$7e0,$1f,24,$ff,$ff00,$ff0000); { 24BGR888 } { 46 }
  291. {From 32 bit muhmu}
  292. test(32,$ff00000,$3fc00,$ff,32,$ff0000,$ff00,$ff); { 32RGB888 } { 47 }
  293. test(32,$ff00000,$3fc00,$ff,16,$f800,$7e0,$1f); { 16RGB565 } { 48 }
  294. test(32,$ff00000,$3fc00,$ff, 8,$e0,$1c,$3); { 8RGB332 } { 49 }
  295. test(32,$ff00000,$3fc00,$ff,16,$7c00,$3e0,$1f); { 16RGB555 } { 50 }
  296. test(32,$ff00000,$3fc00,$ff,24,$ff0000,$ff00,$ff); { 24RGB888 } { 51 }
  297. test(32,$ff00000,$3fc00,$ff,32,$ff,$ff00,$ff0000); { 32BGR888 } { 52 }
  298. test(32,$ff00000,$3fc00,$ff,16,$1f,$7e0,$f800); { 16BGR565 } { 53 }
  299. test(32,$ff00000,$3fc00,$ff,16,$1f,$3e0,$7c00); { 16BGR555 } { 54 }
  300. test(32,$ff00000,$3fc00,$ff,32,$ff000000,$ff0000,$ff00,$ff); { 32RGBA888 } { 55 }
  301. test(32,$ff00000,$3fc00,$ff,32,$ff00,$ff0000,$ff000000,$ff); { 32BGRA888 } { 56 }
  302. test(32,$ff00000,$3fc00,$ff,24,$ff,$ff00,$ff0000); { 24BGR888 } { 57 }
  303. Writeln('testing dithering converters');
  304. test(32,$ff0000,$ff00,$ff,16,$f800,$7e0,$1f, 0, True); { 16RGB565 } { 58 }
  305. test(32,$ff0000,$ff00,$ff, 8,$e0,$1c,$3, 0 , True); { 8RGB332 } { 59 }
  306. finally
  307. surface.Free;
  308. image.Free;
  309. format.Free;
  310. end;
  311. except
  312. on error: TPTCError do
  313. error.report;
  314. end;
  315. end.