1{ 2 Free Pascal port of the Hermes C library. 3 Copyright (C) 2001-2003 Nikolay Nikolov (nickysn@users.sourceforge.net) 4 Original C version by Christian Nentwich (c.nentwich@cs.ucl.ac.uk) 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version 10 with the following modification: 11 12 As a special exception, the copyright holders of this library give you 13 permission to link this library with independent modules to produce an 14 executable, regardless of the license terms of these independent modules,and 15 to copy and distribute the resulting executable under terms of your choice, 16 provided that you also meet, for each linked independent module, the terms 17 and conditions of the license of that module. An independent module is a 18 module which is not derived from or based on this library. If you modify 19 this library, you may extend this exception to your version of the library, 20 but you are not obligated to do so. If you do not wish to do so, delete this 21 exception statement from your version. 22 23 This library is distributed in the hope that it will be useful, 24 but WITHOUT ANY WARRANTY; without even the implied warranty of 25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 26 Lesser General Public License for more details. 27 28 You should have received a copy of the GNU Lesser General Public 29 License along with this library; if not, write to the Free Software 30 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 31} 32 33{ 34 35 Generic C converter (from 8 bit indexed) for the HERMES library 36 Copyright (c) 1998 Christian Nentwich (c.nentwich@cs.ucl.ac.uk) 37 This source code is licensed under the GNU LGPL 38 39 Please refer to the file COPYING.LIB contained in the distribution for 40 licensing conditions 41} 42 43{ ------------------------------------------------------------------------- 44 45 NORMAL CONVERTERS 46 47 ------------------------------------------------------------------------- } 48 49procedure ConvertP_index8_32(iface: PHermesConverterInterface); cdecl; 50var 51 i: Integer; 52 s_pixel: Uint8; 53 d_pixel: Uint32; 54 source, dest: PUint8; 55begin 56 source := iface^.s_pixels; 57 dest := iface^.d_pixels; 58 repeat 59 for i := 0 to iface^.s_width - 1 do 60 begin 61 s_pixel := source^; 62 d_pixel := iface^.lookup[s_pixel]; 63 PUint32(dest)^ := d_pixel; 64 Inc(source); 65 Inc(dest, 4); 66 end; 67 Inc(source, iface^.s_add); 68 Inc(dest, iface^.d_add); 69 Dec(iface^.s_height); 70 until iface^.s_height = 0; 71end; 72 73procedure ConvertP_index8_24(iface: PHermesConverterInterface); cdecl; 74var 75 count: Integer; 76 s_pixel, s_pixel2, d_pixel: Uint32; 77 d_ptr, source, dest: PUint8; 78begin 79 d_ptr := PUint8(@d_pixel) + (R_32 - R_24); 80 source := iface^.s_pixels; 81 dest := iface^.d_pixels; 82 repeat 83 count := iface^.d_width shr 2; 84 while count <> 0 do 85 begin 86 Dec(count); 87 88 s_pixel := iface^.lookup[source^]; Inc(source); 89 s_pixel2 := iface^.lookup[source^]; Inc(source); 90 91 {$IFDEF FPC_LITTLE_ENDIAN} 92 s_pixel := s_pixel or (s_pixel2 shl 24); 93 {$ELSE FPC_LITTLE_ENDIAN} 94 s_pixel := (s_pixel shl 8) or (s_pixel2 shr 16); 95 {$ENDIF FPC_LITTLE_ENDIAN} 96 PUint32(dest)^ := s_pixel; 97 98 s_pixel := iface^.lookup[source^]; Inc(source); 99 {$IFDEF FPC_LITTLE_ENDIAN} 100 s_pixel2 := (s_pixel2 shr 8) or (s_pixel shl 16); 101 {$ELSE FPC_LITTLE_ENDIAN} 102 s_pixel2 := (s_pixel2 shl 16) or (s_pixel shr 8); 103 {$ENDIF FPC_LITTLE_ENDIAN} 104 PUint32(dest + 4)^ := s_pixel2; 105 106 s_pixel2 := iface^.lookup[source^]; Inc(source); 107 {$IFDEF FPC_LITTLE_ENDIAN} 108 s_pixel := (s_pixel shr 16) or (s_pixel2 shl 8); 109 {$ELSE FPC_LITTLE_ENDIAN} 110 s_pixel := (s_pixel shl 24) or s_pixel2; 111 {$ENDIF FPC_LITTLE_ENDIAN} 112 PUint32(dest + 8)^ := s_pixel; 113 114 Inc(dest, 12); 115 end; 116 117 count := iface^.d_width and $3; 118 while count <> 0 do 119 begin 120 Dec(count); 121 d_pixel := iface^.lookup[source^]; Inc(source); 122 123 (dest + 0)^ := (d_ptr + 0)^; 124 (dest + 1)^ := (d_ptr + 1)^; 125 (dest + 2)^ := (d_ptr + 2)^; 126 127 Inc(dest, 3); 128 end; 129 Inc(source, iface^.s_add); 130 Inc(dest, iface^.d_add); 131 Dec(iface^.d_height); 132 until iface^.d_height = 0; 133end; 134 135procedure ConvertP_index8_16(iface: PHermesConverterInterface); cdecl; 136var 137 source, dest: PUint8; 138 count, c: DWord; 139begin 140 source := iface^.s_pixels; 141 dest := iface^.d_pixels; 142 repeat 143 count := iface^.s_width; 144 if (PtrUInt(dest) and $3) <> 0 then 145 begin 146 PUint16(dest)^ := iface^.lookup[source^]; Inc(source); 147 Inc(dest, 2); 148 Dec(count); 149 end; 150 c := count shr 1; 151 if c <> 0 then 152 repeat 153 PUint32(dest)^ := (iface^.lookup[source^] shl DWORD_SMALLINT0_SHL) or 154 (iface^.lookup[(source + 1)^] shl DWORD_SMALLINT1_SHL); 155 Inc(dest, 4); 156 Inc(source, 2); 157 Dec(c); 158 until c = 0; 159 if (count and 1) <> 0 then 160 begin 161 PUint16(dest)^ := iface^.lookup[source^]; 162 Inc(source); 163 Inc(dest, 2); 164 end; 165 Inc(source, iface^.s_add); 166 Inc(dest, iface^.d_add); 167 Dec(iface^.s_height); 168 until iface^.s_height = 0; 169end; 170 171procedure ConvertP_index8_8(iface: PHermesConverterInterface); cdecl; 172var 173 source, dest: PUint8; 174 count, c: DWord; 175begin 176 source := iface^.s_pixels; 177 dest := iface^.d_pixels; 178 repeat 179 count := iface^.s_width; 180 if (PtrUInt(dest) and $3) <> 0 then 181 begin 182 dest^ := iface^.lookup[source^]; Inc(source); 183 Inc(dest); 184 Dec(count); 185 end; 186 c := count shr 2; 187 if c <> 0 then 188 repeat 189 PUint32(dest)^ := (iface^.lookup[source^] shl DWORD_BYTE0_SHL) or 190 (iface^.lookup[(source + 1)^] shl DWORD_BYTE1_SHL) or 191 (iface^.lookup[(source + 2)^] shl DWORD_BYTE2_SHL) or 192 (iface^.lookup[(source + 3)^] shl DWORD_BYTE3_SHL); 193 Inc(dest, 4); 194 Inc(source, 4); 195 Dec(c); 196 until c = 0; 197 count := count and $03; 198 while count > 0 do 199 begin 200 dest^ := iface^.lookup[source^]; Inc(source); 201 Inc(dest); 202 Dec(count); 203 end; 204 Inc(source, iface^.s_add); 205 Inc(dest, iface^.d_add); 206 Dec(iface^.s_height); 207 until iface^.s_height = 0; 208end; 209 210{ ------------------------------------------------------------------------- 211 212 STRETCH CONVERTERS 213 214 ------------------------------------------------------------------------- } 215 216procedure ConvertP_index8_32_S(iface: PHermesConverterInterface); cdecl; 217var 218 x, y, count: DWord; 219 dx, dy: DWord; 220 source: PUint8; 221begin 222 y := 0; 223 dy := (iface^.s_height shl 16) div iface^.d_height; 224 dx := (iface^.s_width shl 16) div iface^.d_width; 225 source := iface^.s_pixels; 226 repeat 227 count := iface^.d_width; 228 x := 0; 229 230 repeat 231 PUint32(iface^.d_pixels)^ := iface^.lookup[(source + (x shr 16))^]; 232 Inc(x, dx); 233 Inc(iface^.d_pixels, 4); 234 Dec(count); 235 until count = 0; 236 237 { Go to next destination row } 238 Inc(iface^.d_pixels, iface^.d_add); 239 240 { Calculate amount of rows to move in source surface } 241 Inc(y, dy); 242 243 Inc(source, (y shr 16) * DWord(iface^.s_pitch)); 244 y := y and $ffff; 245 Dec(iface^.d_height); 246 until iface^.d_height = 0; 247end; 248 249procedure ConvertP_index8_24_S(iface: PHermesConverterInterface); cdecl; 250var 251 x, y, count: DWord; 252 dx, dy: DWord; 253 d_ptr, source, dest: PUint8; 254 s_pixel, s_pixel2, d_pixel: Uint32; 255begin 256 d_ptr := PUint8(@d_pixel) + (R_32 - R_24); 257 y := 0; 258 dy := (iface^.s_height shl 16) div iface^.d_height; 259 dx := (iface^.s_width shl 16) div iface^.d_width; 260 source := iface^.s_pixels; 261 dest := iface^.d_pixels; 262 repeat 263 x := 0; 264 count := iface^.d_width shr 2; 265 while count <> 0 do 266 begin 267 Dec(count); 268 269 s_pixel := iface^.lookup[(source + (x shr 16))^]; Inc(x, dx); 270 s_pixel2 := iface^.lookup[(source + (x shr 16))^]; Inc(x, dx); 271 272 {$IFDEF FPC_LITTLE_ENDIAN} 273 s_pixel := s_pixel or (s_pixel2 shl 24); 274 {$ELSE FPC_LITTLE_ENDIAN} 275 s_pixel := (s_pixel shl 8) or (s_pixel2 shr 16); 276 {$ENDIF FPC_LITTLE_ENDIAN} 277 PUint32(dest)^ := s_pixel; 278 279 s_pixel := iface^.lookup[(source + (x shr 16))^]; Inc(x, dx); 280 {$IFDEF FPC_LITTLE_ENDIAN} 281 s_pixel2 := (s_pixel2 shr 8) or (s_pixel shl 16); 282 {$ELSE FPC_LITTLE_ENDIAN} 283 s_pixel2 := (s_pixel2 shl 16) or (s_pixel shr 8); 284 {$ENDIF FPC_LITTLE_ENDIAN} 285 PUint32(dest + 4)^ := s_pixel2; 286 287 s_pixel2 := iface^.lookup[(source + (x shr 16))^]; Inc(x, dx); 288 {$IFDEF FPC_LITTLE_ENDIAN} 289 s_pixel := (s_pixel shr 16) or (s_pixel2 shl 8); 290 {$ELSE FPC_LITTLE_ENDIAN} 291 s_pixel := (s_pixel shl 24) or s_pixel2; 292 {$ENDIF FPC_LITTLE_ENDIAN} 293 PUint32(dest + 8)^ := s_pixel; 294 295 Inc(dest, 12); 296 end; 297 298 count := iface^.d_width and $3; 299 while count <> 0 do 300 begin 301 Dec(count); 302 d_pixel := iface^.lookup[(source + (x shr 16))^]; Inc(x, dx); 303 304 (dest + 0)^ := (d_ptr + 0)^; 305 (dest + 1)^ := (d_ptr + 1)^; 306 (dest + 2)^ := (d_ptr + 2)^; 307 308 Inc(dest, 3); 309 end; 310 311 { Go to next destination row } 312{ Inc(iface^.d_pixels, iface^.d_add);} 313 Inc(dest, iface^.d_add); 314 315 { Calculate amount of rows to move in source surface } 316 Inc(y, dy); 317 318 Inc(source, (y shr 16) * DWord(iface^.s_pitch)); 319 y := y and $ffff; 320 Dec(iface^.d_height); 321 until iface^.d_height = 0; 322end; 323 324{ Quick hack of a index 8 to 16 stretch converter } 325procedure ConvertP_index8_16_S(iface: PHermesConverterInterface); cdecl; 326var 327 x, y, count: DWord; 328 dx, dy: DWord; 329 source, dest: PUint8; 330begin 331 y := 0; 332 dy := (iface^.s_height shl 16) div iface^.d_height; 333 dx := (iface^.s_width shl 16) div iface^.d_width; 334 source := iface^.s_pixels; 335 dest := iface^.d_pixels; 336 repeat 337 { do a two pixel at a time loop } 338 339 count := iface^.d_width shr 1; 340 x := 0; 341 342 while count <> 0 do 343 begin 344 Dec(count); 345 PUint32(dest)^ := (iface^.lookup[(source + (x shr 16))^] shl DWORD_SMALLINT0_SHL) or 346 (iface^.lookup[(source + ((x + dx) shr 16))^] shl DWORD_SMALLINT1_SHL); 347 Inc(x, dx); Inc(x, dx); 348 Inc(dest, 4); 349 end; 350 351 { Clean up remaining pixel if odd width } 352 if (iface^.d_width and 1) <> 0 then 353 begin 354 PUint16(dest)^ := iface^.lookup[(source + (x shr 16))^]; 355 Inc(dest, 2); 356 end; 357 358 { Go to next destination row } 359 Inc(dest, iface^.d_add); 360 361 { Calculate amount of rows to move in source surface } 362 Inc(y, dy); 363 364 Inc(source, (y shr 16) * DWord(iface^.s_pitch)); 365 y := y and $ffff; 366 Dec(iface^.d_height); 367 until iface^.d_height = 0; 368end; 369 370procedure ConvertP_index8_8_S(iface: PHermesConverterInterface); cdecl; 371var 372 x, y, count, c: DWord; 373 dx, dy: DWord; 374 source, dest: PUint8; 375begin 376 y := 0; 377 dy := (iface^.s_height shl 16) div iface^.d_height; 378 dx := (iface^.s_width shl 16) div iface^.d_width; 379 source := iface^.s_pixels; 380 dest := iface^.d_pixels; 381 repeat 382 { do a four pixel at a time loop } 383 384 count := iface^.d_width; 385 x := 0; 386 387 while ((PtrUInt(dest) and 3) <> 0) and (count > 0) do 388 begin 389 Dec(count); 390 dest^ := iface^.lookup[(source + (x shr 16))^]; 391 Inc(x, dx); 392 Inc(dest); 393 end; 394 395 c := count shr 2; 396 count := count and 3; 397 398 while c <> 0 do 399 begin 400 Dec(c); 401 PUint32(dest)^ := (iface^.lookup[(source + (x shr 16))^] shl DWORD_BYTE0_SHL) or 402 (iface^.lookup[(source + ((x + dx) shr 16))^] shl DWORD_BYTE1_SHL) or 403 (iface^.lookup[(source + ((x + (dx shl 1)) shr 16))^] shl DWORD_BYTE2_SHL) or 404 (iface^.lookup[(source + ((x + dx + (dx shl 1)) shr 16))^] shl DWORD_BYTE3_SHL); 405 Inc(x, dx shl 2); 406 Inc(dest, 4); 407 end; 408 409 while count > 0 do 410 begin 411 Dec(count); 412 dest^ := iface^.lookup[(source + (x shr 16))^]; 413 Inc(dest); 414 end; 415 416 { Go to next destination row } 417 Inc(dest, iface^.d_add); 418 419 { Calculate amount of rows to move in source surface } 420 Inc(y, dy); 421 422 Inc(source, (y shr 16) * DWord(iface^.s_pitch)); 423 y := y and $ffff; 424 Dec(iface^.d_height); 425 until iface^.d_height = 0; 426end; 427