1 /* ************************************************************************** */
2 /* *             For conditions of distribution and use,                    * */
3 /* *                see copyright notice in libmng.h                        * */
4 /* ************************************************************************** */
5 /* *                                                                        * */
6 /* * project   : libmng                                                     * */
7 /* * file      : libmng_filter.c           copyright (c) 2000-2004 G.Juyn   * */
8 /* * version   : 1.0.9                                                      * */
9 /* *                                                                        * */
10 /* * purpose   : Filtering routines (implementation)                        * */
11 /* *                                                                        * */
12 /* * author    : G.Juyn                                                     * */
13 /* *                                                                        * */
14 /* * comment   : implementation of the filtering routines                   * */
15 /* *                                                                        * */
16 /* * changes   : 0.5.1 - 05/08/2000 - G.Juyn                                * */
17 /* *             - changed strict-ANSI stuff                                * */
18 /* *             0.5.1 - 05/12/2000 - G.Juyn                                * */
19 /* *             - changed trace to macro for callback error-reporting      * */
20 /* *                                                                        * */
21 /* *             0.9.2 - 08/05/2000 - G.Juyn                                * */
22 /* *             - changed file-prefixes                                    * */
23 /* *                                                                        * */
24 /* *             0.9.3 - 09/07/2000 - G.Juyn                                * */
25 /* *             - added support for new filter_types                       * */
26 /* *                                                                        * */
27 /* *             1.0.5 - 08/07/2002 - G.Juyn                                * */
28 /* *             - added test-option for PNG filter method 193 (=no filter) * */
29 /* *             1.0.5 - 08/19/2002 - G.Juyn                                * */
30 /* *             - B597134 - libmng pollutes the linker namespace           * */
31 /* *                                                                        * */
32 /* *             1.0.6 - 07/07/2003 - G.R-P                                 * */
33 /* *             - reversed some loops to use decrementing counter          * */
34 /* *                                                                        * */
35 /* *             1.0.9 - 12/20/2004 - G.Juyn                                * */
36 /* *             - cleaned up macro-invocations (thanks to D. Airlie)       * */
37 /* *                                                                        * */
38 /* ************************************************************************** */
39 
40 #include "libmng.h"
41 #include "libmng_data.h"
42 #include "libmng_error.h"
43 #include "libmng_trace.h"
44 #ifdef __BORLANDC__
45 #pragma hdrstop
46 #endif
47 #include "libmng_filter.h"
48 
49 #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
50 #pragma option -A                      /* force ANSI-C */
51 #endif
52 
53 /* ************************************************************************** */
54 
55 #ifdef MNG_INCLUDE_FILTERS
56 
57 /* ************************************************************************** */
58 
filter_sub(mng_datap pData)59 MNG_LOCAL mng_retcode filter_sub (mng_datap pData)
60 {
61   mng_uint32 iBpp;
62   mng_uint8p pRawx;
63   mng_uint8p pRawx_prev;
64   mng_int32  iX;
65 
66 #ifdef MNG_SUPPORT_TRACE
67   MNG_TRACE (pData, MNG_FN_FILTER_SUB, MNG_LC_START);
68 #endif
69 
70   iBpp       = pData->iFilterbpp;
71   pRawx      = pData->pWorkrow + pData->iPixelofs + iBpp;
72   pRawx_prev = pData->pWorkrow + pData->iPixelofs;
73 
74   for (iX = iBpp; iX < pData->iRowsize; iX++)
75   {
76     *pRawx = (mng_uint8)(*pRawx + *pRawx_prev);
77     pRawx++;
78     pRawx_prev++;
79   }
80 
81 #ifdef MNG_SUPPORT_TRACE
82   MNG_TRACE (pData, MNG_FN_FILTER_SUB, MNG_LC_END);
83 #endif
84 
85   return MNG_NOERROR;
86 }
87 
88 /* ************************************************************************** */
89 
filter_up(mng_datap pData)90 MNG_LOCAL mng_retcode filter_up (mng_datap pData)
91 {
92   mng_uint8p pRawx;
93   mng_uint8p pPriorx;
94   mng_int32  iX;
95 
96 #ifdef MNG_SUPPORT_TRACE
97   MNG_TRACE (pData, MNG_FN_FILTER_UP, MNG_LC_START);
98 #endif
99 
100   pRawx   = pData->pWorkrow + pData->iPixelofs;
101   pPriorx = pData->pPrevrow + pData->iPixelofs;
102 
103 #ifdef MNG_DECREMENT_LOOPS
104   for (iX = pData->iRowsize - 1; iX >= 0; iX--)
105 #else
106   for (iX = 0; iX < pData->iRowsize; iX++)
107 #endif
108   {
109     *pRawx = (mng_uint8)(*pRawx + *pPriorx);
110     pRawx++;
111     pPriorx++;
112   }
113 
114 #ifdef MNG_SUPPORT_TRACE
115   MNG_TRACE (pData, MNG_FN_FILTER_UP, MNG_LC_END);
116 #endif
117 
118   return MNG_NOERROR;
119 }
120 
121 /* ************************************************************************** */
122 
filter_average(mng_datap pData)123 MNG_LOCAL mng_retcode filter_average (mng_datap pData)
124 {
125   mng_int32  iBpp;
126   mng_uint8p pRawx;
127   mng_uint8p pRawx_prev;
128   mng_uint8p pPriorx;
129   mng_int32  iX;
130 
131 #ifdef MNG_SUPPORT_TRACE
132   MNG_TRACE (pData, MNG_FN_FILTER_AVERAGE, MNG_LC_START);
133 #endif
134 
135   iBpp       = pData->iFilterbpp;
136   pRawx      = pData->pWorkrow + pData->iPixelofs;
137   pPriorx    = pData->pPrevrow + pData->iPixelofs;
138   pRawx_prev = pData->pWorkrow + pData->iPixelofs;
139 
140 #ifdef MNG_DECREMENT_LOOPS
141   for (iX = iBpp - 1; iX >= 0; iX--)
142 #else
143   for (iX = 0; iX < iBpp; iX++)
144 #endif
145   {
146     *pRawx = (mng_uint8)(*pRawx + ((*pPriorx) >> 1));
147     pRawx++;
148     pPriorx++;
149   }
150 
151   for (iX = iBpp; iX < pData->iRowsize; iX++)
152   {
153     *pRawx = (mng_uint8)(*pRawx + ((*pRawx_prev + *pPriorx) >> 1));
154     pRawx++;
155     pPriorx++;
156     pRawx_prev++;
157   }
158 
159 #ifdef MNG_SUPPORT_TRACE
160   MNG_TRACE (pData, MNG_FN_FILTER_AVERAGE, MNG_LC_END);
161 #endif
162 
163   return MNG_NOERROR;
164 }
165 
166 /* ************************************************************************** */
167 
filter_paeth(mng_datap pData)168 MNG_LOCAL mng_retcode filter_paeth (mng_datap pData)
169 {
170   mng_int32  iBpp;
171   mng_uint8p pRawx;
172   mng_uint8p pRawx_prev;
173   mng_uint8p pPriorx;
174   mng_uint8p pPriorx_prev;
175   mng_int32  iX;
176   mng_uint32 iA, iB, iC;
177   mng_uint32 iP;
178   mng_uint32 iPa, iPb, iPc;
179 
180 #ifdef MNG_SUPPORT_TRACE
181   MNG_TRACE (pData, MNG_FN_FILTER_PAETH, MNG_LC_START);
182 #endif
183 
184   iBpp         = pData->iFilterbpp;
185   pRawx        = pData->pWorkrow + pData->iPixelofs;
186   pPriorx      = pData->pPrevrow + pData->iPixelofs;
187   pRawx_prev   = pData->pWorkrow + pData->iPixelofs;
188   pPriorx_prev = pData->pPrevrow + pData->iPixelofs;
189 
190 #ifdef MNG_DECREMENT_LOOPS
191   for (iX = iBpp - 1; iX >= 0; iX--)
192 #else
193   for (iX = 0; iX < iBpp; iX++)
194 #endif
195   {
196     *pRawx = (mng_uint8)(*pRawx + *pPriorx);
197 
198     pRawx++;
199     pPriorx++;
200   }
201 
202   for (iX = iBpp; iX < pData->iRowsize; iX++)
203   {
204     iA  = (mng_uint32)*pRawx_prev;
205     iB  = (mng_uint32)*pPriorx;
206     iC  = (mng_uint32)*pPriorx_prev;
207     iP  = iA + iB - iC;
208     iPa = abs (iP - iA);
209     iPb = abs (iP - iB);
210     iPc = abs (iP - iC);
211 
212     if ((iPa <= iPb) && (iPa <= iPc))
213       *pRawx = (mng_uint8)(*pRawx + iA);
214     else
215       if (iPb <= iPc)
216         *pRawx = (mng_uint8)(*pRawx + iB);
217       else
218         *pRawx = (mng_uint8)(*pRawx + iC);
219 
220     pRawx++;
221     pPriorx++;
222     pRawx_prev++;
223     pPriorx_prev++;
224   }
225 
226 #ifdef MNG_SUPPORT_TRACE
227   MNG_TRACE (pData, MNG_FN_FILTER_PAETH, MNG_LC_END);
228 #endif
229 
230   return MNG_NOERROR;
231 }
232 
233 /* ************************************************************************** */
234 
mng_filter_a_row(mng_datap pData)235 mng_retcode mng_filter_a_row (mng_datap pData)
236 {
237   mng_retcode iRetcode;
238 
239 #ifdef MNG_SUPPORT_TRACE
240   MNG_TRACE (pData, MNG_FN_FILTER_A_ROW, MNG_LC_START);
241 #endif
242 
243   switch (*(pData->pWorkrow + pData->iFilterofs))
244   {
245     case 1  : {
246                 iRetcode = filter_sub     (pData);
247                 break;
248               }
249     case 2  : {
250                 iRetcode = filter_up      (pData);
251                 break;
252               }
253     case 3  : {
254                 iRetcode = filter_average (pData);
255                 break;
256               }
257     case 4  : {
258                 iRetcode = filter_paeth   (pData);
259                 break;
260               }
261 
262     default : iRetcode = MNG_INVALIDFILTER;
263   }
264 
265 #ifdef MNG_SUPPORT_TRACE
266   MNG_TRACE (pData, MNG_FN_FILTER_A_ROW, MNG_LC_END);
267 #endif
268 
269   return iRetcode;
270 }
271 
272 /* ************************************************************************** */
273 /* ************************************************************************** */
274 
275 #ifdef FILTER192
mng_init_rowdiffering(mng_datap pData)276 mng_retcode mng_init_rowdiffering (mng_datap pData)
277 {
278   mng_uint8p pRawi, pRawo;
279   mng_int32  iX;
280 
281 #ifdef MNG_SUPPORT_TRACE
282   MNG_TRACE (pData, MNG_FN_INIT_ROWDIFFERING, MNG_LC_START);
283 #endif
284 
285   if (pData->iFilter == 0xC0)          /* has leveling parameters ? */
286   {
287     switch (pData->iColortype)         /* salvage leveling parameters */
288     {
289       case 0 : {                       /* gray */
290                  if (pData->iBitdepth <= 8)
291                    pData->iLevel0 = (mng_uint16)*pData->pWorkrow;
292                  else
293                    pData->iLevel0 = mng_get_uint16 (pData->pWorkrow);
294 
295                  break;
296                }
297       case 2 : {                       /* rgb */
298                  if (pData->iBitdepth <= 8)
299                  {
300                    pData->iLevel0 = (mng_uint16)*pData->pWorkrow;
301                    pData->iLevel1 = (mng_uint16)*(pData->pWorkrow+1);
302                    pData->iLevel2 = (mng_uint16)*(pData->pWorkrow+2);
303                  }
304                  else
305                  {
306                    pData->iLevel0 = mng_get_uint16 (pData->pWorkrow);
307                    pData->iLevel1 = mng_get_uint16 (pData->pWorkrow+2);
308                    pData->iLevel2 = mng_get_uint16 (pData->pWorkrow+4);
309                  }
310 
311                  break;
312                }
313       case 3 : {                       /* indexed */
314                  pData->iLevel0 = (mng_uint16)*pData->pWorkrow;
315                  break;
316                }
317       case 4 : {                       /* gray+alpha */
318                  if (pData->iBitdepth <= 8)
319                  {
320                    pData->iLevel0 = (mng_uint16)*pData->pWorkrow;
321                    pData->iLevel1 = (mng_uint16)*(pData->pWorkrow+1);
322                  }
323                  else
324                  {
325                    pData->iLevel0 = mng_get_uint16 (pData->pWorkrow);
326                    pData->iLevel1 = mng_get_uint16 (pData->pWorkrow+2);
327                  }
328 
329                  break;
330                }
331       case 6 : {                       /* rgb+alpha */
332                  if (pData->iBitdepth <= 8)
333                  {
334                    pData->iLevel0 = (mng_uint16)*pData->pWorkrow;
335                    pData->iLevel1 = (mng_uint16)*(pData->pWorkrow+1);
336                    pData->iLevel2 = (mng_uint16)*(pData->pWorkrow+2);
337                    pData->iLevel3 = (mng_uint16)*(pData->pWorkrow+3);
338                  }
339                  else
340                  {
341                    pData->iLevel0 = mng_get_uint16 (pData->pWorkrow);
342                    pData->iLevel1 = mng_get_uint16 (pData->pWorkrow+2);
343                    pData->iLevel2 = mng_get_uint16 (pData->pWorkrow+4);
344                    pData->iLevel3 = mng_get_uint16 (pData->pWorkrow+6);
345                  }
346 
347                  break;
348                }
349     }
350   }
351                                        /* shift the entire row back in place */
352   pRawi = pData->pWorkrow + pData->iFilterofs;
353   pRawo = pData->pWorkrow;
354 
355   for (iX = 0; iX < pData->iRowsize + pData->iPixelofs - pData->iFilterofs; iX++)
356     *pRawo++ = *pRawi++;
357 
358   pData->iFilterofs = 0;               /* indicate so ! */
359 
360 #ifdef FILTER193
361   if (pData->iFilter == 0xC1)          /* no adaptive filtering ? */
362     pData->iPixelofs = pData->iFilterofs;
363   else
364 #endif
365     pData->iPixelofs = pData->iFilterofs + 1;
366 
367 #ifdef MNG_SUPPORT_TRACE
368   MNG_TRACE (pData, MNG_FN_INIT_ROWDIFFERING, MNG_LC_END);
369 #endif
370 
371   return MNG_NOERROR;
372 }
373 
374 /* ************************************************************************** */
375 
mng_differ_g1(mng_datap pData)376 mng_retcode mng_differ_g1 (mng_datap pData)
377 {
378   mng_uint8p pRawi, pRawo;
379   mng_int32  iX;
380 
381 #ifdef MNG_SUPPORT_TRACE
382   MNG_TRACE (pData, MNG_FN_DIFFER_G1, MNG_LC_START);
383 #endif
384 
385   if (pData->iLevel0 & 0x01)           /* is it uneven level ? */
386   {
387     pRawi = pData->pWorkrow + pData->iPixelofs;
388     pRawo = pData->pPrevrow + pData->iPixelofs;
389                                        /* just invert every bit */
390 #ifdef MNG_DECREMENT_LOOPS
391     for (iX = pData->iRowsize - 1; iX >= 0; iX--)
392 #else
393     for (iX = 0; iX < pData->iRowsize; iX++)
394 #endif
395       *pRawo++ = (mng_uint8)(~(*pRawi++));
396 
397   }
398 
399 #ifdef MNG_SUPPORT_TRACE
400   MNG_TRACE (pData, MNG_FN_DIFFER_G1, MNG_LC_END);
401 #endif
402 
403   return MNG_NOERROR;
404 }
405 
406 /* ************************************************************************** */
407 
mng_differ_g2(mng_datap pData)408 mng_retcode mng_differ_g2 (mng_datap pData)
409 {
410   mng_uint8p pRawi, pRawo;
411   mng_int32  iX;
412   mng_int32  iC, iS;
413   mng_uint8  iB, iN, iQ;
414 
415 #ifdef MNG_SUPPORT_TRACE
416   MNG_TRACE (pData, MNG_FN_DIFFER_G2, MNG_LC_START);
417 #endif
418 
419   pRawi = pData->pWorkrow + pData->iPixelofs;
420   pRawo = pData->pPrevrow + pData->iPixelofs;
421   iC    = 0;
422   iB    = 0;
423   iN    = 0;
424   iS    = 0;
425 
426 #ifdef MNG_DECREMENT_LOOPS
427   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
428 #else
429   for (iX = 0; iX < pData->iRowsamples; iX++)
430 #endif
431   {
432     if (!iC)
433     {
434       iC = 4;
435       iB = *pRawi++;
436       iN = 0;
437       iS = 8;
438     }
439 
440     iS -= 2;
441     iQ = (mng_uint8)(((iB >> iS) + pData->iLevel0) & 0x03);
442     iN = (mng_uint8)((iN << 2) + iQ);
443     iC--;
444 
445     if (!iC)
446       *pRawo++ = iN;
447 
448   }
449 
450   if (iC)
451     *pRawo = (mng_uint8)(iN << iS);
452 
453 #ifdef MNG_SUPPORT_TRACE
454   MNG_TRACE (pData, MNG_FN_DIFFER_G2, MNG_LC_END);
455 #endif
456 
457   return MNG_NOERROR;
458 }
459 
460 /* ************************************************************************** */
461 
mng_differ_g4(mng_datap pData)462 mng_retcode mng_differ_g4 (mng_datap pData)
463 {
464   mng_uint8p pRawi, pRawo;
465   mng_int32  iX;
466   mng_int32  iC, iS;
467   mng_uint8  iB, iN, iQ;
468 
469 #ifdef MNG_SUPPORT_TRACE
470   MNG_TRACE (pData, MNG_FN_DIFFER_G4, MNG_LC_START);
471 #endif
472 
473   pRawi = pData->pWorkrow + pData->iPixelofs;
474   pRawo = pData->pPrevrow + pData->iPixelofs;
475   iC    = 0;
476   iB    = 0;
477   iN    = 0;
478   iS    = 0;
479 
480 #ifdef MNG_DECREMENT_LOOPS
481   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
482 #else
483   for (iX = 0; iX < pData->iRowsamples; iX++)
484 #endif
485   {
486     if (!iC)
487     {
488       iC = 2;
489       iB = *pRawi++;
490       iN = 0;
491       iS = 8;
492     }
493 
494     iS -= 4;
495     iQ = (mng_uint8)(((iB >> iS) + pData->iLevel0) & 0x0F);
496     iN = (mng_uint8)((iN << 4) + iQ);
497     iC--;
498 
499     if (!iC)
500       *pRawo++ = iN;
501 
502   }
503 
504   if (iC)
505     *pRawo = (mng_uint8)(iN << iS);
506 
507 #ifdef MNG_SUPPORT_TRACE
508   MNG_TRACE (pData, MNG_FN_DIFFER_G4, MNG_LC_END);
509 #endif
510 
511   return MNG_NOERROR;
512 }
513 
514 /* ************************************************************************** */
515 
mng_differ_g8(mng_datap pData)516 mng_retcode mng_differ_g8 (mng_datap pData)
517 {
518   mng_uint8p pRawi, pRawo;
519   mng_int32  iX;
520 
521 #ifdef MNG_SUPPORT_TRACE
522   MNG_TRACE (pData, MNG_FN_DIFFER_G8, MNG_LC_START);
523 #endif
524 
525   pRawi = pData->pWorkrow + pData->iPixelofs;
526   pRawo = pData->pPrevrow + pData->iPixelofs;
527 
528 #ifdef MNG_DECREMENT_LOOPS
529   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
530 #else
531   for (iX = 0; iX < pData->iRowsamples; iX++)
532 #endif
533   {
534     *pRawo++ = (mng_uint8)(((mng_uint16)*pRawi + pData->iLevel0) & 0xFF);
535 
536     pRawi++;
537   }
538 
539 #ifdef MNG_SUPPORT_TRACE
540   MNG_TRACE (pData, MNG_FN_DIFFER_G8, MNG_LC_END);
541 #endif
542 
543   return MNG_NOERROR;
544 }
545 
546 /* ************************************************************************** */
547 
mng_differ_g16(mng_datap pData)548 mng_retcode mng_differ_g16 (mng_datap pData)
549 {
550   mng_uint16p pRawi, pRawo;
551   mng_int32   iX;
552 
553 #ifdef MNG_SUPPORT_TRACE
554   MNG_TRACE (pData, MNG_FN_DIFFER_G16, MNG_LC_START);
555 #endif
556 
557   pRawi = (mng_uint16p)(pData->pWorkrow + pData->iPixelofs);
558   pRawo = (mng_uint16p)(pData->pPrevrow + pData->iPixelofs);
559 
560 #ifdef MNG_DECREMENT_LOOPS
561   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
562 #else
563   for (iX = 0; iX < pData->iRowsamples; iX++)
564 #endif
565   {
566     *pRawo++ = (mng_uint16)(((mng_uint32)*pRawi + (mng_uint32)pData->iLevel0) & 0xFFFF);
567 
568     pRawi++;
569   }
570 
571 #ifdef MNG_SUPPORT_TRACE
572   MNG_TRACE (pData, MNG_FN_DIFFER_G16, MNG_LC_END);
573 #endif
574 
575   return MNG_NOERROR;
576 }
577 
578 /* ************************************************************************** */
579 
mng_differ_rgb8(mng_datap pData)580 mng_retcode mng_differ_rgb8 (mng_datap pData)
581 {
582   mng_uint8p pRawi, pRawo;
583   mng_int32  iX;
584 
585 #ifdef MNG_SUPPORT_TRACE
586   MNG_TRACE (pData, MNG_FN_DIFFER_RGB8, MNG_LC_START);
587 #endif
588 
589   pRawi = pData->pWorkrow + pData->iPixelofs;
590   pRawo = pData->pPrevrow + pData->iPixelofs;
591 
592 #ifdef MNG_DECREMENT_LOOPS
593   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
594 #else
595   for (iX = 0; iX < pData->iRowsamples; iX++)
596 #endif
597   {
598     *(pRawo+1) = (mng_uint8)(((mng_uint16)*(pRawi+1) + pData->iLevel1) & 0xFF);
599     *pRawo     = (mng_uint8)(((mng_uint16)*pRawi     + pData->iLevel0 +
600                               (mng_uint16)*(pRawo+1)) & 0xFF);
601     *(pRawo+2) = (mng_uint8)(((mng_uint16)*(pRawi+2) + pData->iLevel2 +
602                               (mng_uint16)*(pRawo+1)) & 0xFF);
603 
604     pRawi += 3;
605     pRawo += 3;
606   }
607 
608 #ifdef MNG_SUPPORT_TRACE
609   MNG_TRACE (pData, MNG_FN_DIFFER_RGB8, MNG_LC_END);
610 #endif
611 
612   return MNG_NOERROR;
613 }
614 
615 /* ************************************************************************** */
616 
mng_differ_rgb16(mng_datap pData)617 mng_retcode mng_differ_rgb16 (mng_datap pData)
618 {
619   mng_uint16p pRawi, pRawo;
620   mng_int32   iX;
621 
622 #ifdef MNG_SUPPORT_TRACE
623   MNG_TRACE (pData, MNG_FN_DIFFER_RGB16, MNG_LC_START);
624 #endif
625 
626   pRawi = (mng_uint16p)(pData->pWorkrow + pData->iPixelofs);
627   pRawo = (mng_uint16p)(pData->pPrevrow + pData->iPixelofs);
628 
629 #ifdef MNG_DECREMENT_LOOPS
630   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
631 #else
632   for (iX = 0; iX < pData->iRowsamples; iX++)
633 #endif
634   {
635     *(pRawo+1) = (mng_uint16)(((mng_uint32)*(pRawi+1) + (mng_uint32)pData->iLevel1) & 0xFFFF);
636     *pRawo     = (mng_uint16)(((mng_uint32)*pRawi     + (mng_uint32)pData->iLevel0 +
637                                (mng_uint32)*(pRawo+1)) & 0xFFFF);
638     *(pRawo+2) = (mng_uint16)(((mng_uint32)*(pRawi+2) + (mng_uint32)pData->iLevel2 +
639                                (mng_uint32)*(pRawo+1)) & 0xFFFF);
640 
641     pRawi += 3;
642     pRawo += 3;
643   }
644 
645 #ifdef MNG_SUPPORT_TRACE
646   MNG_TRACE (pData, MNG_FN_DIFFER_RGB16, MNG_LC_END);
647 #endif
648 
649   return MNG_NOERROR;
650 }
651 
652 /* ************************************************************************** */
653 
mng_differ_idx1(mng_datap pData)654 mng_retcode mng_differ_idx1 (mng_datap pData)
655 {
656   mng_uint8p pRawi, pRawo;
657   mng_int32  iX;
658 
659 #ifdef MNG_SUPPORT_TRACE
660   MNG_TRACE (pData, MNG_FN_DIFFER_IDX1, MNG_LC_START);
661 #endif
662 
663   if (pData->iLevel0 & 0x01)           /* is it uneven level ? */
664   {
665     pRawi = pData->pWorkrow + pData->iPixelofs;
666     pRawo = pData->pPrevrow + pData->iPixelofs;
667                                        /* just invert every bit */
668 #ifdef MNG_DECREMENT_LOOPS
669     for (iX = pData->iRowsize - 1; iX >= 0; iX--)
670 #else
671     for (iX = 0; iX < pData->iRowsize; iX++)
672 #endif
673       *pRawo++ = (mng_uint8)(~(*pRawi++));
674 
675   }
676 
677 #ifdef MNG_SUPPORT_TRACE
678   MNG_TRACE (pData, MNG_FN_DIFFER_IDX1, MNG_LC_END);
679 #endif
680 
681   return MNG_NOERROR;
682 }
683 
684 /* ************************************************************************** */
685 
mng_differ_idx2(mng_datap pData)686 mng_retcode mng_differ_idx2 (mng_datap pData)
687 {
688   mng_uint8p pRawi, pRawo;
689   mng_int32  iX;
690   mng_int32  iC, iS;
691   mng_uint8  iB, iN, iQ;
692 
693 #ifdef MNG_SUPPORT_TRACE
694   MNG_TRACE (pData, MNG_FN_DIFFER_IDX2, MNG_LC_START);
695 #endif
696 
697   pRawi = pData->pWorkrow + pData->iPixelofs;
698   pRawo = pData->pPrevrow + pData->iPixelofs;
699   iC    = 0;
700   iB    = 0;
701   iN    = 0;
702   iS    = 0;
703 
704 #ifdef MNG_DECREMENT_LOOPS
705   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
706 #else
707   for (iX = 0; iX < pData->iRowsamples; iX++)
708 #endif
709   {
710     if (!iC)
711     {
712       iC = 4;
713       iB = *pRawi++;
714       iN = 0;
715       iS = 8;
716     }
717 
718     iS -= 2;
719     iQ = (mng_uint8)(((iB >> iS) + pData->iLevel0) & 0x03);
720     iN = (mng_uint8)((iN << 2) + iQ);
721     iC--;
722 
723     if (!iC)
724       *pRawo++ = iN;
725 
726   }
727 
728   if (iC)
729     *pRawo = (mng_uint8)(iN << iS);
730 
731 #ifdef MNG_SUPPORT_TRACE
732   MNG_TRACE (pData, MNG_FN_DIFFER_IDX2, MNG_LC_END);
733 #endif
734 
735   return MNG_NOERROR;
736 }
737 
738 /* ************************************************************************** */
739 
mng_differ_idx4(mng_datap pData)740 mng_retcode mng_differ_idx4 (mng_datap pData)
741 {
742   mng_uint8p pRawi, pRawo;
743   mng_int32  iX;
744   mng_int32  iC, iS;
745   mng_uint8  iB, iN, iQ;
746 
747 #ifdef MNG_SUPPORT_TRACE
748   MNG_TRACE (pData, MNG_FN_DIFFER_IDX4, MNG_LC_START);
749 #endif
750 
751   pRawi = pData->pWorkrow + pData->iPixelofs;
752   pRawo = pData->pPrevrow + pData->iPixelofs;
753   iC    = 0;
754   iB    = 0;
755   iN    = 0;
756   iS    = 0;
757 
758 #ifdef MNG_DECREMENT_LOOPS
759   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
760 #else
761   for (iX = 0; iX < pData->iRowsamples; iX++)
762 #endif
763   {
764     if (!iC)
765     {
766       iC = 2;
767       iB = *pRawi++;
768       iN = 0;
769       iS = 8;
770     }
771 
772     iS -= 4;
773     iQ = (mng_uint8)(((iB >> iS) + pData->iLevel0) & 0x0F);
774     iN = (mng_uint8)((iN << 4) + iQ);
775     iC--;
776 
777     if (!iC)
778       *pRawo++ = iN;
779 
780   }
781 
782   if (iC)
783     *pRawo = (mng_uint8)(iN << iS);
784 
785 #ifdef MNG_SUPPORT_TRACE
786   MNG_TRACE (pData, MNG_FN_DIFFER_IDX4, MNG_LC_END);
787 #endif
788 
789   return MNG_NOERROR;
790 }
791 
792 /* ************************************************************************** */
793 
mng_differ_idx8(mng_datap pData)794 mng_retcode mng_differ_idx8 (mng_datap pData)
795 {
796   mng_uint8p pRawi, pRawo;
797   mng_int32  iX;
798 
799 #ifdef MNG_SUPPORT_TRACE
800   MNG_TRACE (pData, MNG_FN_DIFFER_IDX8, MNG_LC_START);
801 #endif
802 
803   pRawi = pData->pWorkrow + pData->iPixelofs;
804   pRawo = pData->pPrevrow + pData->iPixelofs;
805 
806 #ifdef MNG_DECREMENT_LOOPS
807   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
808 #else
809   for (iX = 0; iX < pData->iRowsamples; iX++)
810 #endif
811   {
812     *pRawo++ = (mng_uint8)(((mng_uint16)*pRawi + pData->iLevel0) & 0xFF);
813 
814     pRawi++;
815   }
816 
817 #ifdef MNG_SUPPORT_TRACE
818   MNG_TRACE (pData, MNG_FN_DIFFER_IDX8, MNG_LC_END);
819 #endif
820 
821   return MNG_NOERROR;
822 }
823 
824 /* ************************************************************************** */
825 
mng_differ_ga8(mng_datap pData)826 mng_retcode mng_differ_ga8 (mng_datap pData)
827 {
828   mng_uint8p pRawi, pRawo;
829   mng_int32  iX;
830 
831 #ifdef MNG_SUPPORT_TRACE
832   MNG_TRACE (pData, MNG_FN_DIFFER_GA8, MNG_LC_START);
833 #endif
834 
835   pRawi = pData->pWorkrow + pData->iPixelofs;
836   pRawo = pData->pPrevrow + pData->iPixelofs;
837 
838 #ifdef MNG_DECREMENT_LOOPS
839   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
840 #else
841   for (iX = 0; iX < pData->iRowsamples; iX++)
842 #endif
843   {
844     *pRawo     = (mng_uint8)(((mng_uint16)*pRawi     + pData->iLevel0) & 0xFF);
845     *(pRawo+1) = (mng_uint8)(((mng_uint16)*(pRawi+1) + pData->iLevel1) & 0xFF);
846 
847     pRawi += 2;
848     pRawo += 2;
849   }
850 
851 #ifdef MNG_SUPPORT_TRACE
852   MNG_TRACE (pData, MNG_FN_DIFFER_GA8, MNG_LC_END);
853 #endif
854 
855   return MNG_NOERROR;
856 }
857 
858 /* ************************************************************************** */
859 
mng_differ_ga16(mng_datap pData)860 mng_retcode mng_differ_ga16 (mng_datap pData)
861 {
862   mng_uint16p pRawi, pRawo;
863   mng_int32   iX;
864 
865 #ifdef MNG_SUPPORT_TRACE
866   MNG_TRACE (pData, MNG_FN_DIFFER_GA16, MNG_LC_START);
867 #endif
868 
869   pRawi = (mng_uint16p)(pData->pWorkrow + pData->iPixelofs);
870   pRawo = (mng_uint16p)(pData->pPrevrow + pData->iPixelofs);
871 
872 #ifdef MNG_DECREMENT_LOOPS
873   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
874 #else
875   for (iX = 0; iX < pData->iRowsamples; iX++)
876 #endif
877   {
878     *pRawo     = (mng_uint16)(((mng_uint32)*pRawi     + (mng_uint32)pData->iLevel0) & 0xFFFF);
879     *(pRawo+1) = (mng_uint16)(((mng_uint32)*(pRawi+1) + (mng_uint32)pData->iLevel1) & 0xFFFF);
880 
881     pRawi += 2;
882   }
883 
884 #ifdef MNG_SUPPORT_TRACE
885   MNG_TRACE (pData, MNG_FN_DIFFER_GA16, MNG_LC_END);
886 #endif
887 
888   return MNG_NOERROR;
889 }
890 
891 /* ************************************************************************** */
892 
mng_differ_rgba8(mng_datap pData)893 mng_retcode mng_differ_rgba8 (mng_datap pData)
894 {
895   mng_uint8p pRawi, pRawo;
896   mng_int32  iX;
897 
898 #ifdef MNG_SUPPORT_TRACE
899   MNG_TRACE (pData, MNG_FN_DIFFER_RGBA8, MNG_LC_START);
900 #endif
901 
902   pRawi = pData->pWorkrow + pData->iPixelofs;
903   pRawo = pData->pPrevrow + pData->iPixelofs;
904 
905 #ifdef MNG_DECREMENT_LOOPS
906   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
907 #else
908   for (iX = 0; iX < pData->iRowsamples; iX++)
909 #endif
910   {
911     *(pRawo+1) = (mng_uint8)(((mng_uint16)*(pRawi+1) + pData->iLevel1) & 0xFF);
912     *pRawo     = (mng_uint8)(((mng_uint16)*pRawi     + pData->iLevel0 +
913                               (mng_uint16)*(pRawo+1)) & 0xFF);
914     *(pRawo+2) = (mng_uint8)(((mng_uint16)*(pRawi+2) + pData->iLevel2 +
915                               (mng_uint16)*(pRawo+1)) & 0xFF);
916     *(pRawo+3) = (mng_uint8)(((mng_uint16)*(pRawi+3) + pData->iLevel3) & 0xFF);
917 
918     pRawi += 4;
919     pRawo += 4;
920   }
921 
922 #ifdef MNG_SUPPORT_TRACE
923   MNG_TRACE (pData, MNG_FN_DIFFER_RGBA8, MNG_LC_END);
924 #endif
925 
926   return MNG_NOERROR;
927 }
928 
929 /* ************************************************************************** */
930 
mng_differ_rgba16(mng_datap pData)931 mng_retcode mng_differ_rgba16 (mng_datap pData)
932 {
933   mng_uint16p pRawi, pRawo;
934   mng_int32   iX;
935 
936 #ifdef MNG_SUPPORT_TRACE
937   MNG_TRACE (pData, MNG_FN_DIFFER_RGBA16, MNG_LC_START);
938 #endif
939 
940   pRawi = (mng_uint16p)(pData->pWorkrow + pData->iPixelofs);
941   pRawo = (mng_uint16p)(pData->pPrevrow + pData->iPixelofs);
942 
943 #ifdef MNG_DECREMENT_LOOPS
944   for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
945 #else
946   for (iX = 0; iX < pData->iRowsamples; iX++)
947 #endif
948   {
949     *(pRawo+1) = (mng_uint16)(((mng_uint32)*(pRawi+1) + (mng_uint32)pData->iLevel1) & 0xFFFF);
950     *pRawo     = (mng_uint16)(((mng_uint32)*pRawi     + (mng_uint32)pData->iLevel0 +
951                                (mng_uint32)*(pRawo+1)) & 0xFFFF);
952     *(pRawo+2) = (mng_uint16)(((mng_uint32)*(pRawi+2) + (mng_uint32)pData->iLevel2 +
953                                (mng_uint32)*(pRawo+1)) & 0xFFFF);
954     *(pRawo+3) = (mng_uint16)(((mng_uint32)*(pRawi+3) + (mng_uint32)pData->iLevel3) & 0xFFFF);
955 
956     pRawi += 4;
957     pRawo += 4;
958   }
959 
960 #ifdef MNG_SUPPORT_TRACE
961   MNG_TRACE (pData, MNG_FN_DIFFER_RGBA16, MNG_LC_END);
962 #endif
963 
964   return MNG_NOERROR;
965 }
966 
967 /* ************************************************************************** */
968 
969 #endif /* FILTER192 */
970 
971 /* ************************************************************************** */
972 
973 #endif /* MNG_INCLUDE_FILTERS */
974 
975 /* ************************************************************************** */
976 /* * end of file                                                            * */
977 /* ************************************************************************** */
978 
979