Edit

IABSD.fr/xenocara/lib/liblbxutil/src/image/epackbits.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2006-11-25 18:20:25
    Hash : 17a977a3
    Message : import from X.Org 7.2RC2

  • lib/liblbxutil/src/image/epackbits.c
  • /* $Xorg: epackbits.c,v 1.4 2000/08/17 19:46:41 cpqbld Exp $ */
    /*
     * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
     * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
     *
     * Permission to use, copy, modify, distribute, and sell this software and 
     * its documentation for any purpose is hereby granted without fee, provided
     * that (i) the above copyright notices and this permission notice appear in
     * all copies of the software and related documentation, and (ii) the names of
     * Sam Leffler and Silicon Graphics may not be used in any advertising or
     * publicity relating to the software without the specific, prior written
     * permission of Sam Leffler and Silicon Graphics.
     * 
     * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
     * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
     * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
     * 
     * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
     * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
     * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
     * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
     * OF THIS SOFTWARE.
     */
    
    #include <X11/Xfuncproto.h>
    #include <X11/extensions/lbximage.h>
    
    /*
     * -------------------------------------------------------------------------
     *              PackBits encoding for 8 bit color images
     * -------------------------------------------------------------------------
     */
    
    #define PutByte(byte,bufptr,bytesLeft) \
    { \
        if (*bytesLeft < 1) {\
             *outbuf = outptr; \
             return (0); \
        } \
        *bufptr++ = byte; \
        (*bytesLeft)--; \
    }
        
    
    static int
    EncodePackBits (char *inbuf,
    		int numPixels,
    		char **outbuf,
    		int *bytesLeft)
    
    {
        register int pixelsLeft = numPixels;
        register char *outptr = *outbuf;
        register char *lastliteral;
        register int n, b;
        enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
    
        state = BASE;
        lastliteral = 0;
    
        while (pixelsLeft > 0)
        {
    	/*
    	 * Find the longest string of identical bytes.
    	 */
    
    	b = *inbuf++, pixelsLeft--, n = 1;
    	for (; pixelsLeft > 0 && b == *inbuf; pixelsLeft--, inbuf++)
    	    n++;
    
        again:
    
    	switch (state)
    	{
    	case BASE:		/* initial state, set run/literal */
    	    if (n > 1)
    	    {
    		state = RUN;
    
    		if (n > 128)
    		{
    		    PutByte (-127, outptr, bytesLeft);
    		    PutByte (b, outptr, bytesLeft);
    		    n -= 128;
    		    goto again;
    		}
    
    		PutByte (-(n-1), outptr, bytesLeft);
    		PutByte (b, outptr, bytesLeft);
    	    }
    	    else
    	    {
    		lastliteral = outptr;
    		PutByte (0, outptr, bytesLeft);
    		PutByte (b, outptr, bytesLeft);
    		state = LITERAL;
    	    }
    
    	    break;
    
    	case LITERAL:		/* last object was literal string */
    	    if (n > 1)
    	    {
    		state = LITERAL_RUN;
    
    		if (n > 128)
    		{
    		    PutByte (-127, outptr, bytesLeft);
    		    PutByte (b, outptr, bytesLeft);
    		    n -= 128;
    		    goto again;
    		}
    
    		    PutByte (-(n-1), outptr, bytesLeft); /* encode run */
    		    PutByte (b, outptr, bytesLeft);
    	    }
    	    else
    	    {			/* extend literal */
    		if (++(*lastliteral) == 127)
    		    state = BASE;
    		PutByte (b, outptr, bytesLeft);
    	    }
    
    	    break;
    
    	case RUN:		/* last object was run */
    	    if (n > 1)
    	    {
    		if (n > 128)
    		{
    		    PutByte (-127, outptr, bytesLeft);
    		    PutByte (b, outptr, bytesLeft);
    		    n -= 128;
    		    goto again;
    		}
    		PutByte (-(n-1), outptr, bytesLeft);
    		PutByte (b, outptr, bytesLeft);
    	    }
    	    else
    	    {
    		lastliteral = outptr;
    		PutByte (0, outptr, bytesLeft);
    		PutByte (b, outptr, bytesLeft);
    		state = LITERAL;
    	    }
    
    	    break;
    
    	case LITERAL_RUN:	/* literal followed by a run */
    	    /*
    	     * Check to see if previous run should
    	     * be converted to a literal, in which
    	     * case we convert literal-run-literal
    	     * to a single literal.
    	     */
    
    	    if (n == 1 && outptr[-2] == (char)-1 && *lastliteral < 126)
    	    {
    		state = (((*lastliteral) += 2) == 127 ? BASE : LITERAL);
    		outptr[-2] = outptr[-1];	/* replicate */
    	    }
    	    else
    		state = RUN;
    	    goto again;
    	}
        }
    
        *outbuf = outptr;
    
        return (1);
    }
    
    
    int
    LbxImageEncodePackBits (char *inbuf,
    			char *outbuf,
    			int outbufSize,
    			int format,
    			int depth,
    			int num_scan_lines,
    			int scan_line_size,
    			int *bytesCompressed)
    
    {
        char *outbuf_start = outbuf;
        int padded_scan_line_size = (scan_line_size % 4) ?
    	scan_line_size + (4 - scan_line_size % 4) : scan_line_size;
        int bytesLeft = outbufSize;
    
        while (num_scan_lines > 0)
        {
    	if (!EncodePackBits (inbuf, scan_line_size, &outbuf, &bytesLeft))
    	    return (LBX_IMAGE_COMPRESS_NOT_WORTH_IT);
    
    	inbuf += padded_scan_line_size;
    	num_scan_lines--;
        }
    
        *bytesCompressed = outbuf - outbuf_start;
        return (LBX_IMAGE_COMPRESS_SUCCESS);
    }