2 This file is part of libkdepim.
5 Copyright (c) James Ashton - Sydney University - June 1990. //krazy:exclude=copyright
8 Copyright (c) 2004 Jakob Schröter <js@camaya.net>
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Library General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Library General Public License
21 along with this library; see the file COPYING.LIB. If not, write to
22 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA.
39 #define GEN(g) F[h] ^= G.g[k]; break
42 #define DIGITS (PIXELS / BITSPERDIG)
44 #define WORDSPERLINE (WIDTH / DIGSPERWORD / BITSPERDIG)
46 /* compressed output uses the full range of printable characters.
47 * in ascii these are in a contiguous block so we just need to know
48 * the first and last. The total number of printables is needed too */
49 #define FIRSTPRINT '!'
51 #define NUMPRINTS (LASTPRINT - FIRSTPRINT + 1)
53 /* output line length for compressed data */
56 /* Portable, very large unsigned integer arithmetic is needed.
57 * Implementation uses arrays of WORDs. COMPs must have at least
58 * twice as many bits as WORDs to handle intermediate results */
59 #define COMP unsigned long
60 #define WORDCARRY (1 << BITSPERWORD)
61 #define WORDMASK (WORDCARRY - 1)
63 #define ERR_OK 0 /* successful completion */
64 #define ERR_EXCESS 1 /* completed OK but some input was ignored */
65 #define ERR_INSUFF -1 /* insufficient input. Bad face format? */
66 #define ERR_INTERNAL -2 /* Arithmetic overflow or buffer overflow */
72 #define MAX_XFACE_LENGTH 2048
85 QString
KXFace::fromImage( const QImage
&image
)
90 QImage scaledImg
= image
.scaled( 48, 48, Qt::IgnoreAspectRatio
, Qt::SmoothTransformation
);
92 QBuffer
buffer( &ba
, this );
93 buffer
.open( QIODevice::WriteOnly
);
94 scaledImg
.save( &buffer
, "XBM" );
96 xbm
.remove( 0, xbm
.indexOf( "{" ) + 1 );
97 xbm
.truncate( xbm
.indexOf( "}" ) );
103 QString tmp
= xbm
.toLatin1();
104 int len
= tmp
.length();
105 for( int i
=0; i
<len
; ++i
)
107 switch( tmp
[i
].toLatin1() )
109 case '1': tmp
[i
] = '8'; break;
110 case '2': tmp
[i
] = '4'; break;
111 case '3': tmp
[i
] = 'c'; break;
112 case '4': tmp
[i
] = '2'; break;
113 case '5': tmp
[i
] = 'a'; break;
114 case '7': tmp
[i
] = 'e'; break;
115 case '8': tmp
[i
] = '1'; break;
117 case 'a': tmp
[i
] = '5'; break;
119 case 'b': tmp
[i
] = 'd'; break;
121 case 'c': tmp
[i
] = '3'; break;
123 case 'd': tmp
[i
] = 'b'; break;
125 case 'e': tmp
[i
] = '7'; break;
134 tmp
.replace( QRegExp( "(\\w{12})" ), "\\1\n" );
135 tmp
.replace( QRegExp( "(\\w{4})" ), "0x\\1," );
137 char *fbuf
= (char *)malloc( len
+ 1 );
138 strncpy( fbuf
, (const char *)tmp
.toLatin1(), len
);
140 if ( !( status
= setjmp( comp_env
) ) )
152 QImage
KXFace::toImage(const QString
&xface
)
154 if ( xface
.length() > MAX_XFACE_LENGTH
)
157 char *fbuf
= (char *)malloc( MAX_XFACE_LENGTH
);
158 memset( fbuf
, '\0', MAX_XFACE_LENGTH
);
159 strncpy( fbuf
, xface
.toLatin1(), xface
.length() );
161 if ( !( status
= setjmp( comp_env
) ) )
163 UnCompAll( fbuf
);/* compress otherwise */
169 p
.loadFromData( img
, "XBM" );
174 //============================================================================
175 // more or less original compface 1.4 source
177 void KXFace::RevPush(const Prob
*p
)
179 if (NumProbs
>= PIXELS
* 2 - 1)
180 longjmp(comp_env
, ERR_INTERNAL
);
181 ProbBuf
[NumProbs
++] = (Prob
*) p
;
184 void KXFace::BigPush(Prob
*p
)
186 static unsigned char tmp
;
188 BigDiv(p
->p_range
, &tmp
);
190 BigAdd(tmp
+ p
->p_offset
);
193 int KXFace::BigPop(register const Prob
*p
)
195 static unsigned char tmp
;
200 while ((tmp
< p
->p_offset
) || (tmp
>= p
->p_range
+ p
->p_offset
))
206 BigAdd(tmp
- p
->p_offset
);
211 /* Divide B by a storing the result in B and the remainder in the word
214 void KXFace::BigDiv(register unsigned char a
, register unsigned char *r
)
217 register unsigned char *w
;
221 if ((a
== 1) || (B
.b_words
== 0))
226 if (a
== 0) /* treat this as a == WORDCARRY */
227 { /* and just shift everything right a WORD (unsigned char)*/
239 w
= B
.b_word
+ (i
= B
.b_words
);
247 *w
= (unsigned char)(d
& WORDMASK
);
250 if (B
.b_word
[B
.b_words
- 1] == 0)
254 /* Multiply a by B storing the result in B
256 void KXFace::BigMul(register unsigned char a
)
259 register unsigned char *w
;
263 if ((a
== 1) || (B
.b_words
== 0))
265 if (a
== 0) /* treat this as a == WORDCARRY */
266 { /* and just shift everything left a WORD (unsigned char) */
267 if ((i
= B
.b_words
++) >= MAXWORDS
- 1)
268 longjmp(comp_env
, ERR_INTERNAL
);
283 c
+= (COMP
)*w
* (COMP
)a
;
284 *(w
++) = (unsigned char)(c
& WORDMASK
);
289 if (B
.b_words
++ >= MAXWORDS
)
290 longjmp(comp_env
, ERR_INTERNAL
);
291 *w
= (COMP
)(c
& WORDMASK
);
295 /* Add to a to B storing the result in B
297 void KXFace::BigAdd(unsigned char a
)
300 register unsigned char *w
;
309 while ((i
< B
.b_words
) && c
)
312 *w
++ = (unsigned char)(c
& WORDMASK
);
316 if ((i
== B
.b_words
) && c
)
318 if (B
.b_words
++ >= MAXWORDS
)
319 longjmp(comp_env
, ERR_INTERNAL
);
320 *w
= (COMP
)(c
& WORDMASK
);
324 void KXFace::BigClear()
329 QByteArray
KXFace::WriteFace()
332 register int i
, j
, bits
, digits
, words
;
333 int digsperword
= DIGSPERWORD
;
334 int wordsperline
= WORDSPERLINE
;
335 QByteArray
t( "#define noname_width 48\n#define noname_height 48\nstatic char noname_bits[] = {\n " );
339 bits
= digits
= words
= i
= 0;
340 t
.resize( MAX_XFACE_LENGTH
);
343 while ( s
< F
+ PIXELS
)
345 if ( ( bits
== 0 ) && ( digits
== 0 ) )
351 i
= ( i
>> 1 ) | 0x8;
354 if ( ++bits
== BITSPERDIG
)
357 t
[j
-( ( digits
& 1 ) * 2 )] = *(i
+ HexDigits
);
359 if ( ++digits
== digsperword
)
361 if ( s
>= F
+ PIXELS
)
365 if ( ++words
== wordsperline
)
379 void KXFace::UnCompAll(char *fbuf
)
386 while (p
< F
+ PIXELS
)
388 UnCompress(F
, 16, 16, 0);
389 UnCompress(F
+ 16, 16, 16, 0);
390 UnCompress(F
+ 32, 16, 16, 0);
391 UnCompress(F
+ WIDTH
* 16, 16, 16, 0);
392 UnCompress(F
+ WIDTH
* 16 + 16, 16, 16, 0);
393 UnCompress(F
+ WIDTH
* 16 + 32, 16, 16, 0);
394 UnCompress(F
+ WIDTH
* 32, 16, 16, 0);
395 UnCompress(F
+ WIDTH
* 32 + 16, 16, 16, 0);
396 UnCompress(F
+ WIDTH
* 32 + 32, 16, 16, 0);
399 void KXFace::UnCompress(char *f
, int wid
, int hei
, int lev
)
401 switch (BigPop(&levels
[lev
][0]))
406 PopGreys(f
, wid
, hei
);
412 UnCompress(f
, wid
, hei
, lev
);
413 UnCompress(f
+ wid
, wid
, hei
, lev
);
414 UnCompress(f
+ hei
* WIDTH
, wid
, hei
, lev
);
415 UnCompress(f
+ wid
+ hei
* WIDTH
, wid
, hei
, lev
);
420 void KXFace::BigWrite(register char *fbuf
)
422 static unsigned char tmp
;
423 static char buf
[DIGITS
];
428 while (B
.b_words
> 0)
430 BigDiv(NUMPRINTS
, &tmp
);
431 *(s
++) = tmp
+ FIRSTPRINT
;
433 i
= 7; // leave room for the field name on the first line
440 if (++i
>= MAXLINELEN
)
451 void KXFace::BigRead(register char *fbuf
)
455 while (*fbuf
!= '\0')
458 if ((c
< FIRSTPRINT
) || (c
> LASTPRINT
))
461 BigAdd((unsigned char)(c
- FIRSTPRINT
));
465 void KXFace::ReadFace(char *fbuf
)
468 register char *s
, *t
;
471 for(i
= strlen(s
); i
> 0; i
--)
474 if ((c
>= '0') && (c
<= '9'))
476 if (t
>= fbuf
+ DIGITS
)
483 else if ((c
>= 'A') && (c
<= 'F'))
485 if (t
>= fbuf
+ DIGITS
)
490 *(t
++) = c
- 'A' + 10;
492 else if ((c
>= 'a') && (c
<= 'f'))
494 if (t
>= fbuf
+ DIGITS
)
499 *(t
++) = c
- 'a' + 10;
501 else if (((c
== 'x') || (c
== 'X')) && (t
> fbuf
) && (*(t
-1) == 0))
504 if (t
< fbuf
+ DIGITS
)
505 longjmp(comp_env
, ERR_INSUFF
);
508 c
= 1 << (BITSPERDIG
- 1);
509 while (t
< F
+ PIXELS
)
511 *(t
++) = (*s
& c
) ? 1 : 0;
515 c
= 1 << (BITSPERDIG
- 1);
520 void KXFace::GenFace()
522 static char newp
[PIXELS
];
535 void KXFace::UnGenFace()
541 void KXFace::Gen(register char *f
)
543 register int m
, l
, k
, j
, i
, h
;
545 for (j
= 0; j
< HEIGHT
; j
++)
547 for (i
= 0; i
< WIDTH
; i
++)
551 for (l
= i
- 2; l
<= i
+ 2; l
++)
552 for (m
= j
- 2; m
<= j
; m
++)
554 if ((l
>= i
) && (m
== j
))
556 if ((l
> 0) && (l
<= WIDTH
) && (m
> 0))
557 k
= *(f
+ l
+ m
* WIDTH
) ? k
* 2 + 1 : k
* 2;
585 /* i runs from 0 to WIDTH-1, so case can never occur. I leave the code in
586 because it appears exactly like this in the original compface code.
609 void KXFace::PopGreys(char *f
, int wid
, int hei
)
615 PopGreys(f
, wid
, hei
);
616 PopGreys(f
+ wid
, wid
, hei
);
617 PopGreys(f
+ WIDTH
* hei
, wid
, hei
);
618 PopGreys(f
+ WIDTH
* hei
+ wid
, wid
, hei
);
630 *(f
+ WIDTH
+ 1) = 1;
634 void KXFace::CompAll(char *fbuf
)
636 Compress(F
, 16, 16, 0);
637 Compress(F
+ 16, 16, 16, 0);
638 Compress(F
+ 32, 16, 16, 0);
639 Compress(F
+ WIDTH
* 16, 16, 16, 0);
640 Compress(F
+ WIDTH
* 16 + 16, 16, 16, 0);
641 Compress(F
+ WIDTH
* 16 + 32, 16, 16, 0);
642 Compress(F
+ WIDTH
* 32, 16, 16, 0);
643 Compress(F
+ WIDTH
* 32 + 16, 16, 16, 0);
644 Compress(F
+ WIDTH
* 32 + 32, 16, 16, 0);
647 BigPush(ProbBuf
[--NumProbs
]);
651 void KXFace::Compress(register char *f
, register int wid
, register int hei
, register int lev
)
653 if (AllWhite(f
, wid
, hei
))
655 RevPush(&levels
[lev
][WHITE
]);
658 if (AllBlack(f
, wid
, hei
))
660 RevPush(&levels
[lev
][BLACK
]);
661 PushGreys(f
, wid
, hei
);
664 RevPush(&levels
[lev
][GREY
]);
668 Compress(f
, wid
, hei
, lev
);
669 Compress(f
+ wid
, wid
, hei
, lev
);
670 Compress(f
+ hei
* WIDTH
, wid
, hei
, lev
);
671 Compress(f
+ wid
+ hei
* WIDTH
, wid
, hei
, lev
);
674 int KXFace::AllWhite(char *f
, int wid
, int hei
)
676 return ((*f
== 0) && Same(f
, wid
, hei
));
679 int KXFace::AllBlack(char *f
, int wid
, int hei
)
685 return (AllBlack(f
, wid
, hei
) && AllBlack(f
+ wid
, wid
, hei
) &&
686 AllBlack(f
+ WIDTH
* hei
, wid
, hei
) &&
687 AllBlack(f
+ WIDTH
* hei
+ wid
, wid
, hei
));
690 return (*f
|| *(f
+ 1) || *(f
+ WIDTH
) || *(f
+ WIDTH
+ 1));
693 int KXFace::Same(register char *f
, register int wid
, register int hei
)
695 register char val
, *row
;
711 void KXFace::PushGreys(char *f
, int wid
, int hei
)
717 PushGreys(f
, wid
, hei
);
718 PushGreys(f
+ wid
, wid
, hei
);
719 PushGreys(f
+ WIDTH
* hei
, wid
, hei
);
720 PushGreys(f
+ WIDTH
* hei
+ wid
, wid
, hei
);
723 RevPush(freqs
+ *f
+ 2 * *(f
+ 1) + 4 * *(f
+ WIDTH
) +
724 8 * *(f
+ WIDTH
+ 1));
728 #include "kxface.moc"