convtest.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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: IPTCSurface;
  11. surface: IPTCSurface;
  12. format: IPTCFormat;
  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: IPTCSurface);
  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: IPTCFormat;
  161. src, dest: IPTCSurface;
  162. pixels: Pointer;
  163. F: File;
  164. begin
  165. Writeln(sbits, ' ', sr, ' ', sg, ' ', sb, ' ', dbits, ' ', dr, ' ', dg, ' ', db, ' ', da);
  166. srcformat := TPTCFormatFactory.CreateNew(sbits, sr, sg, sb);
  167. destformat := TPTCFormatFactory.CreateNew(dbits, dr, dg, db, da);
  168. src := TPTCSurfaceFactory.CreateNew(320, 200, srcformat);
  169. dest := TPTCSurfaceFactory.CreateNew(destXSize, destYSize, destformat);
  170. if dithering then
  171. dest.Option('attempt dithering');
  172. generic(image, src);
  173. src.copy(dest);
  174. { generic(src, dest);}
  175. generic(dest, surface);
  176. Inc(TestNum);
  177. AssignFile(F, 'test' + IntToStr(TestNum) + '.raw');
  178. Rewrite(F, 1);
  179. try
  180. pixels := surface.lock;
  181. try
  182. BlockWrite(F, pixels^, surface.height * surface.pitch);
  183. finally
  184. surface.unlock;
  185. end;
  186. finally
  187. CloseFile(F);
  188. end;
  189. end;
  190. procedure load(surface: IPTCSurface; filename: String);
  191. var
  192. F: File;
  193. width, height: Integer;
  194. pixels: PByte;
  195. y: Integer;
  196. begin
  197. AssignFile(F, filename);
  198. Reset(F, 1);
  199. try
  200. Seek(F, 18);
  201. width := surface.width;
  202. height := surface.height;
  203. pixels := surface.lock;
  204. try
  205. for y := height - 1 downto 0 do
  206. BlockRead(F, pixels[width * y * 3], width * 3);
  207. finally
  208. surface.unlock;
  209. end;
  210. finally
  211. CloseFile(F);
  212. end;
  213. end;
  214. begin
  215. TestNum := 0;
  216. try
  217. {$IFDEF FPC_LITTLE_ENDIAN}
  218. format := TPTCFormatFactory.CreateNew(24, $00FF0000, $0000FF00, $000000FF);
  219. {$ELSE FPC_LITTLE_ENDIAN}
  220. format := TPTCFormatFactory.CreateNew(24, $000000FF, $0000FF00, $00FF0000);
  221. {$ENDIF FPC_LITTLE_ENDIAN}
  222. surface := TPTCSurfaceFactory.CreateNew(destXSize, destYSize, format);
  223. image := TPTCSurfaceFactory.CreateNew(320, 200, format);
  224. load(image, '../examples/image.tga');
  225. Writeln('testing equal converters');
  226. {test equal converters}
  227. test(32, $00FF0000, $0000FF00, $000000FF, 32, $00FF0000, $0000FF00, $000000FF); { 1 }
  228. test(24, $FF0000, $00FF00, $0000FF, 24, $FF0000, $00FF00, $0000FF); { 2 }
  229. test(16, $F800, $07E0, $001F, 16, $F800,$07E0, $001F); { 3 }
  230. test( 8, $E0, $1C, $03, 8, $E0, $1C, $03); { 4 }
  231. Writeln('testing generic converters');
  232. {test generic}
  233. test(32, $FF000000, $000000FF, $000FF000, 32, $000FF000, $0FF00000, $000000FF); { 5 }
  234. test(32, $FF000000, $000000FF, $000FF000, 24, $00FF00, $FF0000, $000000FF); { 6 }
  235. test(32, $FF000000, $000000FF, $000FF000, 16, $F000, $0F00, $00F0); { 7 }
  236. test(32, $FF000000, $000000FF, $000FF000, 8, $0C, $03, $F0); { 8 }
  237. test(24, $FF0000, $0000FF, $00FF00, 32, $000FF000, $0FF00000, $000000FF); { 9 }
  238. test(24, $FF0000, $0000FF, $00FF00, 24, $00FF00, $FF0000, $000000FF); { 10 }
  239. test(24, $FF0000, $0000FF, $00FF00, 16, $F000, $0F00, $00F0); { 11 }
  240. test(24, $FF0000, $0000FF, $00FF00, 8, $0C, $03, $F0); { 12 }
  241. test(16, $001F, $F800, $07E0, 32, $000FF000, $0FF00000, $000000FF); { 13 }
  242. test(16, $001F, $F800, $07E0, 24, $00FF00, $FF0000, $000000FF); { 14 }
  243. test(16, $001F, $F800, $07E0, 16, $F000, $0F00, $00F0); { 15 }
  244. test(16, $001F, $F800, $07E0, 8, $0C, $03, $F0); { 16 }
  245. // test(8, $03, $E0, $1C, 32, $000FF000, $0FF00000, $000000FF); {unsupported}
  246. // test(8, $03, $E0, $1C, 24, $00FF00, $FF0000, $000000FF); {unsupported}
  247. // test(8, $03, $E0, $1C, 16, $F000, $0F00, $00F0); {unsupported}
  248. // test(8, $03, $E0, $1C, 8, $0C, $03, $F0); {unsupported}
  249. Writeln('testing specialized converters');
  250. {From 32 bit RGB 888}
  251. test(32,$ff0000,$ff00,$ff,16,$f800,$7e0,$1f); { 16RGB565 } { 17 }
  252. test(32,$ff0000,$ff00,$ff, 8,$e0,$1c,$3); { 8RGB332 } { 18 }
  253. test(32,$ff0000,$ff00,$ff,16,$7c00,$3e0,$1f); { 16RGB555 } { 19 }
  254. test(32,$ff0000,$ff00,$ff,24,$ff0000,$ff00,$ff); { 24RGB888 } { 20 }
  255. test(32,$ff0000,$ff00,$ff,32,$ff,$ff00,$ff0000); { 32BGR888 } { 21 }
  256. test(32,$ff0000,$ff00,$ff,16,$1f,$7e0,$f800); { 16BGR565 } { 22 }
  257. test(32,$ff0000,$ff00,$ff,16,$1f,$3e0,$7c00); { 16BGR555 } { 23 }
  258. test(32,$ff0000,$ff00,$ff,32,$ff000000,$ff0000,$ff00,$ff); { 32RGBA888 } { 24 }
  259. test(32,$ff0000,$ff00,$ff,32,$ff00,$ff0000,$ff000000,$ff); { 32BGRA888 } { 25 }
  260. test(32,$ff0000,$ff00,$ff,24,$ff,$ff00,$ff0000); { 24BGR888 } { 26 }
  261. {From 24 bit RGB 888}
  262. test(24,$ff0000,$ff00,$ff,32,$ff0000,$ff00,$ff); { 32RGB888 } { 27 }
  263. test(24,$ff0000,$ff00,$ff,16,$f800,$7e0,$1f); { 16RGB565 } { 28 }
  264. test(24,$ff0000,$ff00,$ff, 8,$e0,$1c,$3); { 8RGB332 } { 29 }
  265. test(24,$ff0000,$ff00,$ff,16,$7c00,$3e0,$1f); { 16RGB555 } { 30 }
  266. test(24,$ff0000,$ff00,$ff,32,$ff,$ff00,$ff0000); { 32BGR888 } { 31 }
  267. test(24,$ff0000,$ff00,$ff,16,$1f,$7e0,$f800); { 16BGR565 } { 32 }
  268. test(24,$ff0000,$ff00,$ff,16,$1f,$3e0,$7c00); { 16BGR555 } { 33 }
  269. test(24,$ff0000,$ff00,$ff,32,$ff000000,$ff0000,$ff00,$ff); { 32RGBA888 } { 34 }
  270. test(24,$ff0000,$ff00,$ff,32,$ff00,$ff0000,$ff000000,$ff); { 32BGRA888 } { 35 }
  271. test(24,$ff0000,$ff00,$ff,24,$ff,$ff00,$ff0000); { 24BGR888 } { 36 }
  272. {From 16 bit RGB 565}
  273. test(16,$f800,$7e0,$1f,32,$ff0000,$ff00,$ff); { 32RGB888 } { 37 }
  274. test(16,$f800,$7e0,$1f, 8,$e0,$1c,$3); { 8RGB332 } { 38 }
  275. test(16,$f800,$7e0,$1f,16,$7c00,$3e0,$1f); { 16RGB555 } { 39 }
  276. test(16,$f800,$7e0,$1f,24,$ff0000,$ff00,$ff); { 24RGB888 } { 40 }
  277. test(16,$f800,$7e0,$1f,32,$ff,$ff00,$ff0000); { 32BGR888 } { 41 }
  278. test(16,$f800,$7e0,$1f,16,$1f,$7e0,$f800); { 16BGR565 } { 42 }
  279. test(16,$f800,$7e0,$1f,16,$1f,$3e0,$7c00); { 16BGR555 } { 43 }
  280. test(16,$f800,$7e0,$1f,32,$ff000000,$ff0000,$ff00,$ff); { 32RGBA888 } { 44 }
  281. test(16,$f800,$7e0,$1f,32,$ff00,$ff0000,$ff000000,$ff); { 32BGRA888 } { 45 }
  282. test(16,$f800,$7e0,$1f,24,$ff,$ff00,$ff0000); { 24BGR888 } { 46 }
  283. {From 32 bit muhmu}
  284. test(32,$ff00000,$3fc00,$ff,32,$ff0000,$ff00,$ff); { 32RGB888 } { 47 }
  285. test(32,$ff00000,$3fc00,$ff,16,$f800,$7e0,$1f); { 16RGB565 } { 48 }
  286. test(32,$ff00000,$3fc00,$ff, 8,$e0,$1c,$3); { 8RGB332 } { 49 }
  287. test(32,$ff00000,$3fc00,$ff,16,$7c00,$3e0,$1f); { 16RGB555 } { 50 }
  288. test(32,$ff00000,$3fc00,$ff,24,$ff0000,$ff00,$ff); { 24RGB888 } { 51 }
  289. test(32,$ff00000,$3fc00,$ff,32,$ff,$ff00,$ff0000); { 32BGR888 } { 52 }
  290. test(32,$ff00000,$3fc00,$ff,16,$1f,$7e0,$f800); { 16BGR565 } { 53 }
  291. test(32,$ff00000,$3fc00,$ff,16,$1f,$3e0,$7c00); { 16BGR555 } { 54 }
  292. test(32,$ff00000,$3fc00,$ff,32,$ff000000,$ff0000,$ff00,$ff); { 32RGBA888 } { 55 }
  293. test(32,$ff00000,$3fc00,$ff,32,$ff00,$ff0000,$ff000000,$ff); { 32BGRA888 } { 56 }
  294. test(32,$ff00000,$3fc00,$ff,24,$ff,$ff00,$ff0000); { 24BGR888 } { 57 }
  295. Writeln('testing dithering converters');
  296. test(32,$ff0000,$ff00,$ff,16,$f800,$7e0,$1f, 0, True); { 16RGB565 } { 58 }
  297. test(32,$ff0000,$ff00,$ff, 8,$e0,$1c,$3, 0 , True); { 8RGB332 } { 59 }
  298. except
  299. on error: TPTCError do
  300. error.report;
  301. end;
  302. end.