0023024: Update headers of OCCT files
[occt.git] / src / AlienImage / AlienImage_GIFLZWDict.cxx
CommitLineData
b311480e 1// Created by: DCB
2// Copyright (c) 1998-1999 Matra Datavision
3// Copyright (c) 1999-2012 OPEN CASCADE SAS
4//
5// The content of this file is subject to the Open CASCADE Technology Public
6// License Version 6.5 (the "License"). You may not use the content of this file
7// except in compliance with the License. Please obtain a copy of the License
8// at http://www.opencascade.org and read it completely before using this file.
9//
10// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
7fd59977 12//
b311480e 13// The Original Code and all software distributed under the License is
14// distributed on an "AS IS" basis, without warranty of any kind, and the
15// Initial Developer hereby disclaims all such warranties, including without
16// limitation, any warranties of merchantability, fitness for a particular
17// purpose or non-infringement. Please see the License for the specific terms
18// and conditions governing the rights and limitations under the License.
19
20// Notes: Most of code is taken from Xw_save_gif_image.c file (ZOV)
7fd59977 21
22#include <AlienImage_GIFLZWDict.hxx>
23#include <stdio.h>
24
25const Handle(Standard_Type)& STANDARD_TYPE(AlienImage_GIFLZWDict)
26{
27 static Handle(Standard_Type) _atype =
28 new Standard_Type ("AlienImage_GIFLZWDict", sizeof (AlienImage_GIFLZWDict));
29 return _atype;
30}
31
32//=============================================================================
33// Functions to write GIF image to file.
34//=============================================================================
35
36//===================== Static definitions ===================
37static AlienImage_GIFLZWDict* dict;
38static int startBits, codeBits, nextCode, bumpCode, rack, mask, putIdx,
39 ClearCode, EOFCode, FreeCode;
40
41static void _init_dict (void);
42static int _find_child (int, int);
43static BOOL _put_bits (BYTE *, ULONG, UINT, OSD_File&);
44static BOOL _flush_bits (BYTE *, OSD_File&);
45
46
47//=============================================================================
48int _lzw_encode (OSD_File& file, const BYTE* pData, int width, int height, int inc)
49{
50 int i, x, y;
51 BYTE byte, OutBuff [BUFF_SIZE];
52 const BYTE *pLine;
53 int strCode, chr;
54
55 dict = (AlienImage_GIFLZWDict*) malloc (sizeof (AlienImage_GIFLZWDict)*TBL_SIZE);
56 if (dict == NULL)
57 goto _ExitError;
58
59 x = y = 0;
60 pLine = pData;
61
62 OutBuff[ 0 ] = 0;
63 putIdx = 1;
64 mask = 0x01;
65 rack = 0;
66 startBits = 8;
67 ClearCode = 1 << startBits;
68 EOFCode = ClearCode + 1;
69 FreeCode = EOFCode + 1;
70
71 _init_dict ();
72
73 byte = startBits;
74
75 file.Write (&byte, sizeof(byte));
76 if (file.Failed ())
77 goto _ExitError;
78
79 strCode = pLine[ x++ ];
80
81 if (!_put_bits (OutBuff, (ULONG) ClearCode, codeBits, file))
82 goto _ExitError;
83
84 while (y < height) {
85
86 chr = pLine[ x++ ];
87
88 i = _find_child ( strCode, chr );
89
90 if ( dict[ i ].code != UNUSED )
91 strCode = dict[ i ].code;
92
93 else {
94 dict[ i ].code = nextCode++;
95 dict[ i ].prnt = strCode;
96 dict[ i ].byte = chr;
97
98 if (!_put_bits (OutBuff, (ULONG) strCode, codeBits, file))
99 goto _ExitError;
100
101 strCode = chr;
102
103 if (nextCode > MAX_CODE) {
104 if (!_put_bits (OutBuff, (ULONG) ClearCode, codeBits, file))
105 goto _ExitError;
106
107 _init_dict ();
108 }
109 else if (nextCode > bumpCode) {
110 ++codeBits;
111 bumpCode <<= 1;
112 }
113 }
114
115 if (x == width) {
116 x = 0;
117 ++y;
118 pLine += inc;
119 }
120 }
121
122 if (!_put_bits (OutBuff, (ULONG) strCode, codeBits, file)) goto _ExitError;
123 if (!_put_bits (OutBuff, (ULONG) EOFCode, codeBits, file)) goto _ExitError;
124 if (!_flush_bits (OutBuff, file)) goto _ExitError;
125
126 if (dict)
127 free (dict);
128 return TRUE;
129
130
131_ExitError:
132 if (dict)
133 free (dict);
134 return FALSE;
135}
136
137//====================================================================
138static void _init_dict ()
139{
140 memset (dict, UNUSED, sizeof (AlienImage_GIFLZWDict)*TBL_SIZE);
141 nextCode = FreeCode;
142 codeBits = startBits + 1;
143 bumpCode = 1 << codeBits;
144}
145
146//====================================================================
147static int _find_child (int prntCode, int chr)
148{
149 int idx, offset;
150
151 idx = ( chr << ( NBITS - 8 ) ) ^ prntCode;
152 offset = idx ? TBL_SIZE - idx : 1;
153
154 for (;;) {
155
156 if (dict[ idx ].code == UNUSED ||
157 dict[ idx ].prnt == prntCode && dict[ idx ].byte == ( BYTE )chr)
158 return idx;
159
160 idx = ( idx >= offset ) ? idx - offset : idx + TBL_SIZE - offset;
161 }
162}
163
164//====================================================================
165static BOOL _put_bits (BYTE *OutBuff, ULONG code, UINT nBits, OSD_File& file)
166{
167 BOOL retVal = TRUE;
168 ULONG msk;
169
170 msk = 1;
171
172 while (msk != (ULONG) (1 << nBits)) {
173 if ( msk & code )
174 rack |= mask;
175 mask <<= 1;
176
177 if ((mask & 0xFF) == 0) {
178 OutBuff[ putIdx++ ] = rack;
179 ++OutBuff[ 0 ];
180
181 if (putIdx == BUFF_SIZE) {
182 file.Write (OutBuff, BUFF_SIZE);
183 if (file.Failed ()) {
184 retVal = FALSE;
185 break;
186 }
187 putIdx = 1;
188 OutBuff[ 0 ] = 0;
189 }
190 rack = 0;
191 mask = 0x01;
192 }
193 msk <<= 1;
194 }
195 return retVal;
196}
197
198//====================================================================
199static BOOL _flush_bits (BYTE* OutBuff, OSD_File& file)
200{
201 BOOL retVal = TRUE;
202 BYTE byte;
203
204 if ( mask != 0x01 ) {
205 OutBuff[ putIdx++ ] = rack;
206 ++OutBuff[ 0 ];
207 }
208
209 if (putIdx != 1) {
210 file.Write (OutBuff, putIdx);
211 if (file.Failed ())
212 retVal = FALSE;
213 }
214
215 if (retVal) {
216 byte = 0;
217 file.Write (&byte, 1);
218 if (file.Failed ())
219 retVal = FALSE;
220 }
221 return retVal;
222}
223
224//=============================================================================
225// Functions to convert from 24 to 8 color image
226//=============================================================================
227static int __fastcall quick_check ( PBYTE, int, int, PBYTE, LPRGBQUAD );
228//static int __fastcall quick_quant ( PBYTE, int, int, PBYTE, LPRGBQUAD );
229static int __fastcall ppm_quant ( PBYTE, int, int, PBYTE, LPRGBQUAD );
230
231BOOL __fastcall _convert24to8 (
232 LPRGBQUAD cTable, PBYTE pData24, PBYTE pData8,
233 int w, int h
234 )
235{
236 BOOL retVal = FALSE;
237 while ( 1 ) {
238 if ( quick_check ( pData24, w, h, pData8, cTable ) ) {
239okRet:
240 retVal = TRUE;
241 break;
242 } else if ( ppm_quant ( pData24, w, h, pData8, cTable ) != -1 ) {
243////////////////////
244 for ( int i = 0; i < 256; ++i ) {
245 BYTE b = cTable[ i ].rgbRed;
246 cTable[ i ].rgbRed = cTable[ i ].rgbBlue;
247 cTable[ i ].rgbBlue = b;
248 } // end for
249////////////////////
250 goto okRet;
251 } // end if
252 break;
253 } // end while
254 return retVal;
255} // end _convert24to8
256
257//*************************************************************************//
258//* The following code based on code from the 'pbmplus' package written by //
259//* Jef Poskanzer //
260//*************************************************************************//
261//***//
262#define MAXCOLORS 32767
263
264#define PPM_GETR( p ) ( ( p ).r )
265#define PPM_GETG( p ) ( ( p ).g )
266#define PPM_GETB( p ) ( ( p ).b )
267
268#define PPM_ASSIGN( p, red, grn, blu ) \
269 { ( p ).r = ( red ); ( p ).g = ( grn ); ( p ).b = ( blu ); }
270
271#define PPM_EQUAL( p, q ) \
272 ( ( p ).r == ( q ).r && ( p ).g == ( q ).g && ( p ).b == ( q ).b )
273
274
275#define PPM_DEPTH( newp, p, oldmaxval, newmaxval ) \
276 PPM_ASSIGN( \
277 ( newp ), \
278 ( ( int )PPM_GETR( p ) ) * ( ( int )newmaxval ) / ( ( int )oldmaxval ), \
279 ( ( int )PPM_GETG( p ) ) * ( ( int )newmaxval ) / ( ( int )oldmaxval ), \
280 ( ( int )PPM_GETB( p ) ) * ( ( int )newmaxval ) / ( ( int )oldmaxval ) \
281 )
282
283
284#define HASH_SIZE 6553
285
286#define ppm_hashpixel( p ) \
287 ( ( ( ( int )PPM_GETR( p ) * 33023 + \
288 ( int )PPM_GETG( p ) * 30013 + \
289 ( int )PPM_GETB( p ) * 27011 \
290 ) & 0x7fffffff \
291 ) % HASH_SIZE \
292 )
293
294#define PPM_LUMIN( p ) \
295 ( 77 * PPM_GETR( p ) + 150 * PPM_GETG( p ) + 29 * PPM_GETB( p ) )
296
297typedef struct { BYTE r, g, b; } pixel;
298
299struct chist_item {
300 pixel color;
301 int value;
302 };
303
304typedef struct chist_item* chist_vec;
305
306typedef struct chist_list_item* chist_list;
307typedef chist_list* chash_table;
308
309struct chist_list_item {
310 struct chist_item ch;
311 chist_list next;
312 };
313
314struct box {
315 int index;
316 int colors;
317 int sum;
318 };
319
320typedef struct box* box_vector;
321
322static chist_vec __fastcall ppm_computechist ( pixel**, int, int, int, PINT );
323static void __fastcall ppm_freechist ( chist_vec );
324static chist_vec __fastcall mediancut ( chist_vec, int, int, int, int );
325static chash_table ppm_allocchash ( void );
326static void __fastcall ppm_freechash ( chash_table );
327static chash_table __fastcall ppm_computechash ( pixel**, int, int, int, PINT );
328static chist_vec __fastcall ppm_chashtochist ( chash_table, int );
329
330static int redcompare ( const void*, const void* );
331static int greencompare ( const void*, const void* );
332static int bluecompare ( const void*, const void* );
333static int sumcompare ( const void*, const void* );
334
335static int __fastcall ppm_quant (
336 PBYTE pic24, int cols, int rows, PBYTE pic8, LPRGBQUAD rgbmap
337 ) {
338
339
340 pixel** pixels;
341 pixel* pP;
342 int row;
343 int col, limitcol;
344 BYTE maxval, newmaxval;
345 int colors;
346 int index;
347 chist_vec chv, colormap;
348 chash_table cht;
349 int i;
350 PBYTE picptr;
351 LPRGBQUAD pRGB;
352 int pad;
353
354 index = 0;
355 maxval = 255;
356// pad = PAD( cols * 3 );
357 pad = 0;
358
359 pixels = ( pixel** )MALLOC( rows * sizeof ( pixel* ) );
360
361 if ( pixels == NULL ) return -1;
362
363 for ( row = 0; row < rows; ++row ) {
364
365 pixels[ row ] = ( pixel* )MALLOC( cols * sizeof ( pixel ) );
366
367 if ( pixels[ row ] == NULL ) {
368freeMemory:
369 while ( --row >= 0 ) FREE( pixels[ row ] );
370
371 FREE( pixels );
372
373 return -1;
374
375 } // end if
376
377 for ( col = 0, pP = pixels[ row ]; col < cols; ++col, ++pP ) {
378
379 pP -> r = *pic24++;
380 pP -> g = *pic24++;
381 pP -> b = *pic24++;
382
383 } // end for
384
385 pic24 += pad;
386
387 } // end for
388
389 for ( ;; ) {
390
391 chv = ppm_computechist ( pixels, cols, rows, MAXCOLORS, &colors );
392
393 if ( chv != ( chist_vec )0 ) break;
394
395 newmaxval = maxval / 2;
396
397 for ( row = 0; row < rows; ++row )
398
399 for ( col = 0, pP = pixels[ row ]; col < cols; ++col, ++pP )
400
401 PPM_DEPTH( *pP, *pP, maxval, newmaxval );
402
403 maxval = newmaxval;
404
405 } // end for
406
407 colormap = mediancut ( chv, colors, rows * cols, maxval, 256 );
408
409 if ( colormap == ( chist_vec )NULL ) {
410freeMemory_1:
411 ppm_freechist ( chv );
412 row = rows;
413 goto freeMemory;
414
415 } // end if
416
417 ppm_freechist ( chv );
418
419 cht = ppm_allocchash ();
420
421 picptr = pic8;
422
423 for ( row = 0; row < rows; ++row ) {
424
425 col = 0;
426 limitcol = cols;
427 pP = pixels[ row ];
428
429 do {
430
431 int hash;
432 chist_list chl;
433
434 hash = ppm_hashpixel ( *pP );
435
436 for ( chl = cht[ hash ]; chl; chl = chl -> next )
437
438 if ( PPM_EQUAL( chl -> ch.color, *pP ) ) {
439
440 index = chl -> ch.value;
441 break;
442
443 } // end if
444
445 if ( !chl ) {
446
447 int i, r1, g1, b1, r2, g2, b2;
448 long dist, newdist;
449
450 r1 = PPM_GETR( *pP );
451 g1 = PPM_GETG( *pP );
452 b1 = PPM_GETB( *pP );
453 dist = 2000000000;
454
455 for ( i = 0; i < 256; ++i ) {
456
457 r2 = PPM_GETR( colormap[ i ].color );
458 g2 = PPM_GETG( colormap[ i ].color );
459 b2 = PPM_GETB( colormap[ i ].color );
460
461 newdist = ( r1 - r2 ) * ( r1 - r2 ) +
462 ( g1 - g2 ) * ( g1 - g2 ) +
463 ( b1 - b2 ) * ( b1 - b2 );
464
465 if ( newdist < dist ) {
466
467 index = i;
468 dist = newdist;
469
470 } // end if
471
472 } // end for
473
474 hash = ppm_hashpixel( *pP );
475 chl = ( chist_list )MALLOC( sizeof ( struct chist_list_item ) );
476
477 if ( chl == NULL ) {
478
479 ppm_freechash ( cht );
480 goto freeMemory_1;
481
482 } // end if
483
484 chl -> ch.color = *pP;
485 chl -> ch.value = index;
486 chl -> next = cht[ hash ];
487 cht[ hash ] = chl;
488
489 } // end if
490
491 *picptr++ = index;
492 ++col;
493 ++pP;
494
495 } while ( col != limitcol );
496
497 } // end for
498
499 for ( i = 0, pRGB = rgbmap; i < 256; ++i, ++pRGB ) {
500
501 PPM_DEPTH( colormap[ i ].color, colormap[ i ].color, maxval, 255 );
502
503 pRGB -> rgbRed = PPM_GETR( colormap[ i ].color );
504 pRGB -> rgbGreen = PPM_GETG( colormap[ i ].color );
505 pRGB -> rgbBlue = PPM_GETB( colormap[ i ].color );
506
507 } // end for
508
509 for ( i = 0; i < rows; ++i ) FREE( pixels[ i ] );
510
511 FREE( pixels );
512
513 ppm_freechist ( colormap );
514 ppm_freechash ( cht );
515
516 return 0;
517
518} // end ppm_quant
519
520static void __fastcall ppm_freechist ( chist_vec chv ) {
521
522 FREE( ( LPVOID )chv );
523
524} // end ppm_freechist
525
526static chist_vec __fastcall mediancut (
527 chist_vec chv, int colors, int sum,
528 int maxval, int newcolors
529 ) {
530
531 chist_vec colormap;
532 box_vector bv;
533 int bi, i;
534 int boxes;
535
536 bv = ( box_vector )MALLOC( sizeof( struct box ) * newcolors );
537
538 if ( bv == NULL ) return ( chist_vec )NULL;
539
540 colormap = ( chist_vec )MALLOC( sizeof( struct chist_item ) * newcolors );
541
542 if ( colormap == NULL ) {
543
544 FREE( bv );
545 return ( chist_vec )NULL;
546
547 } // end if
548
549 for ( i = 0; i < newcolors; ++i ) PPM_ASSIGN( colormap[ i ].color, 0, 0, 0 );
550
551 bv[ 0 ].index = 0;
552 bv[ 0 ].colors = colors;
553 bv[ 0 ].sum = sum;
554 boxes = 1;
555
556 while ( boxes < newcolors ) {
557
558 int indx, clrs;
559 int sm;
560 int minr, maxr, ming, maxg, minb, maxb, v;
561 int halfsum, lowersum;
562
563 for ( bi = 0; bv[ bi ].colors < 2 && bi < boxes; ++bi );
564
565 if ( bi == boxes ) break;
566
567 indx = bv[ bi ].index;
568 clrs = bv[ bi ].colors;
569 sm = bv[ bi ].sum;
570
571 minr = maxr = PPM_GETR( chv[ indx ].color );
572 ming = maxg = PPM_GETG( chv[ indx ].color );
573 minb = maxb = PPM_GETB( chv[ indx ].color );
574
575 for ( i = 1; i < clrs; ++i ) {
576
577 v = PPM_GETR( chv[ indx + i ].color );
578
579 if ( v < minr ) minr = v;
580 if ( v > maxr ) maxr = v;
581
582 v = PPM_GETG( chv[ indx + i ].color );
583
584 if ( v < ming ) ming = v;
585 if ( v > maxg ) maxg = v;
586
587 v = PPM_GETB( chv[ indx + i ].color );
588
589 if ( v < minb ) minb = v;
590 if ( v > maxb ) maxb = v;
591
592 } // end for
593
594 { // begin local block
595
596 pixel p;
597 int rl, gl, bl;
598
599 PPM_ASSIGN( p, maxr - minr, 0, 0 );
600 rl = PPM_LUMIN( p );
601
602 PPM_ASSIGN( p, 0, maxg - ming, 0 );
603 gl = PPM_LUMIN( p );
604
605 PPM_ASSIGN( p, 0, 0, maxb - minb );
606 bl = PPM_LUMIN( p );
607
608 if ( rl >= gl && rl >= bl )
609
610 qsort (
611 ( char* )&chv[ indx ], ( size_t )clrs,
612 sizeof ( struct chist_item ), redcompare
613 );
614
615 else if ( gl >= bl )
616
617 qsort (
618 ( char* )&chv[ indx ], ( size_t )clrs,
619 sizeof ( struct chist_item ), greencompare
620 );
621
622 else
623
624 qsort (
625 ( char* )&chv[ indx ], ( size_t )clrs,
626 sizeof ( struct chist_item ), bluecompare
627 );
628
629 } // end local block
630
631 lowersum = chv[ indx ].value;
632 halfsum = sm / 2;
633
634 for ( i = 1; i < clrs - 1; ++i) {
635
636 if ( lowersum >= halfsum ) break;
637
638 lowersum += chv[ indx + i ].value;
639
640 } // end for
641
642 bv[ bi ].colors = i;
643 bv[ bi ].sum = lowersum;
644
645 bv[ boxes ].index = indx + i;
646 bv[ boxes ].colors = clrs - i;
647 bv[ boxes++ ].sum = sm - lowersum;
648
649 qsort (
650 ( char* )bv, ( size_t )boxes, sizeof ( struct box ), sumcompare
651 );
652
653 } // end while
654
655 for ( bi = 0; bi < boxes; ++bi ) {
656
657 int indx = bv[ bi ].index;
658 int clrs = bv[ bi ].colors;
659 long r = 0, g = 0, b = 0, sum = 0;
660
661 for ( i = 0; i < clrs; ++i ) {
662
663 r += PPM_GETR( chv[ indx + i ].color ) * chv[ indx + i ].value;
664 g += PPM_GETG( chv[ indx + i ].color ) * chv[ indx + i ].value;
665 b += PPM_GETB( chv[ indx + i ].color ) * chv[ indx + i ].value;
666
667 sum += chv[ indx + i ].value;
668
669 } // end for ( i . . . )
670
671 r = r / sum; if ( r > maxval ) r = maxval;
672 g = g / sum; if ( g > maxval ) g = maxval;
673 b = b / sum; if ( b > maxval ) b = maxval;
674
675 PPM_ASSIGN( colormap[ bi ].color, ( BYTE )r, ( BYTE )g, ( BYTE )b );
676
677 } // end for ( bi . . . )
678
679 FREE( bv );
680
681 return colormap;
682
683} // end mediancut
684
685static int redcompare ( const void* p1, const void* p2 ) {
686
687 return ( int )PPM_GETR( ( ( chist_vec )p1 ) -> color ) -
688 ( int )PPM_GETR( ( ( chist_vec )p2 ) -> color );
689
690} // end redcompare
691
692static int greencompare ( const void* p1, const void* p2 ) {
693
694 return ( int )PPM_GETG( ( ( chist_vec )p1 ) -> color ) -
695 ( int )PPM_GETG( ( ( chist_vec )p2 ) -> color );
696
697} // end greencompare
698
699static int bluecompare ( const void* p1, const void* p2 ) {
700
701 return ( int )PPM_GETB( ( ( chist_vec )p1 ) -> color ) -
702 ( int )PPM_GETB( ( ( chist_vec )p2 ) -> color );
703
704} // end bluecompare
705
706static int sumcompare ( const void* p1, const void* p2 ) {
707
708 return ( ( box_vector )p2 ) -> sum - ( ( box_vector )p1 ) -> sum;
709
710} // end sumcompare
711
712static chash_table ppm_allocchash ( void ) {
713
714 chash_table cht;
715
716 cht = ( chash_table )MALLOC( HASH_SIZE * sizeof ( chist_list ) );
717
718 return cht;
719
720} // end ppm_allocchash
721
722static chist_vec __fastcall ppm_computechist (
723 pixel** pixels, int cols, int rows, int maxcolors,
724 PINT colorsP
725 ) {
726
727 chash_table cht;
728 chist_vec chv;
729
730 cht = ppm_computechash ( pixels, cols, rows, maxcolors, colorsP );
731
732 if ( cht == NULL ) return ( chist_vec )NULL;
733
734 chv = ppm_chashtochist ( cht, maxcolors );
735
736 ppm_freechash ( cht );
737
738 return chv;
739
740} // end ppm_computechist
741
742static chash_table __fastcall ppm_computechash (
743 pixel** pixels, int cols, int rows, int maxcolors,
744 PINT colorsP
745 ) {
746
747 chash_table cht;
748 register pixel* pP;
749 chist_list chl;
750 int col, row, hash;
751
752 cht = ppm_allocchash ();
753 *colorsP = 0;
754
755 for ( row = 0; row < rows; ++row )
756
757 for ( col = 0, pP = pixels[ row ]; col < cols; ++col, ++pP ) {
758
759 hash = ppm_hashpixel ( *pP );
760
761 for ( chl = cht[ hash ]; chl != ( chist_list )0; chl = chl -> next )
762
763 if ( PPM_EQUAL( chl -> ch.color, *pP ) ) break;
764
765 if ( chl != ( chist_list)0 )
766
767 ++( chl->ch.value );
768
769 else {
770
771 if ( ( *colorsP )++ > maxcolors ) {
772
773 ppm_freechash ( cht );
774
775 return ( chash_table )NULL;
776
777 } // end if
778
779 chl = ( chist_list )MALLOC( sizeof( struct chist_list_item ) );
780
781 if ( chl == NULL ) return ( chash_table )NULL;
782
783 chl -> ch.color = *pP;
784 chl -> ch.value = 1;
785 chl -> next = cht[ hash ];
786 cht[ hash ] = chl;
787
788 } // end else
789
790 } // end for
791
792 return cht;
793
794} // end ppm_computechash
795
796static chist_vec __fastcall ppm_chashtochist ( chash_table cht, int maxcolors ) {
797
798 chist_vec chv;
799 chist_list chl;
800 int i, j;
801
802 chv = ( chist_vec )MALLOC( maxcolors * sizeof ( struct chist_item ) );
803
804 if ( chv == NULL) return chv;
805
806 j = 0;
807
808 for ( i = 0; i < HASH_SIZE; ++i )
809
810 for ( chl = cht[ i ]; chl != ( chist_list )0; chl = chl -> next ) {
811
812 chv[ j ] = chl -> ch;
813 ++j;
814
815 } // end for
816
817 return chv;
818
819} // end ppm_chashtochist
820
821static void __fastcall ppm_freechash ( chash_table cht ) {
822
823 int i;
824 chist_list chl, chlnext;
825
826 for ( i = 0; i < HASH_SIZE; ++i )
827
828 for ( chl = cht[ i ]; chl != ( chist_list )0; chl = chlnext ) {
829
830 chlnext = chl -> next;
831 FREE( chl );
832
833 } // end for
834
835 FREE( cht );
836
837} // end ppm_freechash
838
839static int __fastcall quick_check (
840 PBYTE pic24, int w, int h, PBYTE pic8, LPRGBQUAD rgbmap
841 ) {
842
843 unsigned long colors[ 256 ], col;
844 int i, j, nc, low, high, mid, pad;
845 PBYTE p, pix;
846
847 nc = 0;
848 mid = 0;
849// pad = PAD( w * 3 );
850 pad = 0;
851
852 for ( i = 0, p = pic24; i < h; ++i ) {
853
854 for ( j = 0; j < w; ++j ) {
855
856 col = ( ( ( unsigned long )*p++ ) << 16 );
857 col += ( ( ( unsigned long )*p++ ) << 8 );
858 col += ( ( ( unsigned long )*p++ ) << 0 );
859
860 low = 0; high = nc - 1;
861
862 while ( low <= high ) {
863
864 mid = ( low + high ) / 2;
865
866 if ( col < colors[ mid ] )
867
868 high = mid - 1;
869
870 else if ( col > colors[ mid ] )
871
872 low = mid + 1;
873
874 else break;
875
876 } // end while
877
878 if ( high < low ) {
879
880 if ( nc >= 256 ) return FALSE;
881
882 memcpy (
883 ( char* )&colors[ low + 1 ], ( char* )&colors[ low ],
884 ( nc - low ) * sizeof ( unsigned long )
885 );
886
887 colors[ low ] = col;
888 ++nc;
889
890 } // end if
891
892 } // end for ( j . . . )
893
894 p += pad;
895
896 } // end for ( i . . . )
897
898 for ( i = 0, p = pic24, pix = pic8; i < h; ++i ) {
899
900 for ( j = 0; j < w; ++j ) {
901
902 col = ( ( ( unsigned long )*p++ ) << 16 );
903 col += ( ( ( unsigned long )*p++ ) << 8 );
904 col += *p++;
905
906 low = 0; high = nc - 1;
907
908 while ( low <= high ) {
909
910 mid = ( low + high ) / 2;
911
912 if ( col < colors[ mid ] )
913
914 high = mid - 1;
915
916 else if ( col > colors[ mid ] )
917
918 low = mid + 1;
919
920 else break;
921
922 } // end while
923
924 *pix++ = mid;
925
926 } // end for ( j . . . )
927
928 p += pad;
929
930 } // end for ( i . . . )
931
932 for ( i = 0; i < nc; ++i, ++rgbmap ) {
933
934 rgbmap -> rgbRed = ( BYTE )( colors[ i ] >> 0 ) & 0xFF;
935 rgbmap -> rgbGreen = ( BYTE )( colors[ i ] >> 8 ) & 0xFF;
936 rgbmap -> rgbBlue = ( BYTE )( colors[ i ] >> 16 ) & 0xFF;
937
938 } // end for
939
940 return nc;
941
942} // end quick_check
943
944#ifdef BSHIFT //HPUX COMPATIBILLITY
945#undef BSHIFT
946#endif
947#define RMASK 0xE0
948#define RSHIFT 0
949#define GMASK 0xE0
950#define GSHIFT 3
951#define BMASK 0xC0
952#define BSHIFT 6
953#define RANGE( a, b, c ) { if ( a < b ) a = b; if ( a > c ) a = c; }
954
955//static int __fastcall quick_quant (
956// PBYTE p24, int w, int h, PBYTE p8, LPRGBQUAD rgbmap
957// ) {
958
959// PBYTE pp;
960// int r1, g1, b1;
961// PINT thisline, nextline, thisptr, nextptr, tmpptr;
962// int i, j, val, pwide3;
963// int imax, jmax;
964// int pad;
965
966//// pad = PAD( w * 3 );
967// pad = 0;
968
969// pp = p8;
970// pwide3 = w * 3;
971// imax = h - 1;
972// jmax = w - 1;
973
974// for ( i = 0; i < 256; ++i ) {
975
976// rgbmap[ i ].rgbRed = ( ( ( i << RSHIFT ) & RMASK ) * 255 + RMASK / 2 ) / RMASK;
977// rgbmap[ i ].rgbGreen = ( ( ( i << GSHIFT ) & GMASK ) * 255 + GMASK / 2 ) / GMASK;
978// rgbmap[ i ].rgbBlue = ( ( ( i << BSHIFT ) & BMASK ) * 255 + BMASK / 2 ) / BMASK;
979
980// } // end for
981
982// thisline = ( PINT )MALLOC( pwide3 * sizeof ( int ) );
983
984// if ( thisline == NULL ) return 1;
985
986// nextline = ( PINT )MALLOC( pwide3 * sizeof ( int ) );
987
988// if ( nextline == NULL ) {
989
990// FREE( thisline );
991// return 1;
992
993// } // end if
994
995// for ( j = pwide3, tmpptr = nextline; j; --j ) *tmpptr++ = ( int )*p24++;
996
997// p24 += pad;
998
999// for ( i = 0; i < h; ++i ) {
1000
1001// tmpptr = thisline;
1002// thisline = nextline;
1003// nextline = tmpptr;
1004//
1005// if ( i != imax ) {
1006
1007// for ( j = pwide3, tmpptr = nextline; j; --j ) *tmpptr++ = ( int )*p24++;
1008//
1009// p24 += pad;
1010
1011// } // end if
1012
1013// for ( j = 0, thisptr = thisline, nextptr = nextline; j < w; ++j, ++pp ) {
1014
1015// r1 = *thisptr++;
1016// RANGE( r1, 0, 255 );
1017
1018// g1 = *thisptr++;
1019// RANGE(g1,0,255);
1020
1021// b1 = *thisptr++;
1022// RANGE(b1,0,255);
1023
1024// val = ( ( ( r1 & RMASK ) >> RSHIFT ) |
1025// ( ( g1 & GMASK ) >> GSHIFT ) |
1026// ( ( b1 & BMASK ) >> BSHIFT ) );
1027// *pp = val;
1028
1029// r1 -= rgbmap[ val ].rgbRed;
1030// g1 -= rgbmap[ val ].rgbGreen;
1031// b1 -= rgbmap[ val ].rgbBlue;
1032
1033// if ( j != jmax ) {
1034
1035// thisptr[ 0 ] += ( r1 * 7 ) / 16;
1036// thisptr[ 1 ] += ( g1 * 7 ) / 16;
1037// thisptr[ 2 ] += ( b1 * 7 ) / 16;
1038
1039// } // end if
1040
1041// if ( i != imax ) {
1042
1043// nextptr[ 0 ] += ( r1 * 5 ) / 16;
1044// nextptr[ 1 ] += ( g1 * 5 ) / 16;
1045// nextptr[ 2 ] += ( b1 * 5 ) / 16;
1046
1047// if ( j > 0 ) {
1048
1049// nextptr[ -3 ] += ( r1 * 3 ) / 16;
1050// nextptr[ -2 ] += ( g1 * 3 ) / 16;
1051// nextptr[ -1 ] += ( b1 * 3 ) / 16;
1052
1053// } // end if
1054
1055// if ( j != jmax ) {
1056
1057// nextptr[ 3 ] += ( r1 ) / 16;
1058// nextptr[ 4 ] += ( g1 ) / 16;
1059// nextptr[ 5 ] += ( b1 ) / 16;
1060
1061// } // end if
1062
1063// nextptr += 3;
1064
1065// } // end if
1066
1067// } // end for ( j . . . )
1068
1069// } // end for ( i . . . )
1070
1071// FREE( thisline );
1072// FREE( nextline );
1073
1074// return 0;
1075
1076//} // end quick_quant
1077//***//
1078//*************************************************************************//
1079