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