mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 07:57:27 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			149 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * The Python Imaging Library.
 | |
|  * $Id$
 | |
|  *
 | |
|  * encoder for PCX data
 | |
|  *
 | |
|  * history:
 | |
|  * 99-02-07 fl	created
 | |
|  *
 | |
|  * Copyright (c) Fredrik Lundh 1999.
 | |
|  * Copyright (c) Secret Labs AB 1999.
 | |
|  *
 | |
|  * See the README file for information on usage and redistribution.
 | |
|  */
 | |
| 
 | |
| 
 | |
| #include "Imaging.h"
 | |
| 
 | |
| enum { INIT, FETCH, ENCODE };
 | |
| 
 | |
| /* we're reusing "ystep" to store the last value */
 | |
| #define LAST ystep
 | |
| 
 | |
| int
 | |
| ImagingPcxEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
 | |
| {
 | |
|     UINT8* ptr;
 | |
|     int this;
 | |
| 
 | |
|     ptr = buf;
 | |
| 
 | |
|     if (!state->state) {
 | |
| 
 | |
|         /* sanity check */
 | |
|         if (state->xsize <= 0 || state->ysize <= 0) {
 | |
|             state->errcode = IMAGING_CODEC_END;
 | |
|             return 0;
 | |
|         }
 | |
| 
 | |
| 	state->bytes = (state->xsize*state->bits + 7) / 8;
 | |
|         state->state = FETCH;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     for (;;)
 | |
| 
 | |
|         switch (state->state) {
 | |
|         case FETCH:
 | |
| 
 | |
|             /* get a line of data */
 | |
|             if (state->y >= state->ysize) {
 | |
|                 state->errcode = IMAGING_CODEC_END;
 | |
|                 return ptr - buf;
 | |
|             }
 | |
| 
 | |
|             state->shuffle(state->buffer,
 | |
|                            (UINT8*) im->image[state->y + state->yoff] +
 | |
|                            state->xoff * im->pixelsize, state->xsize);
 | |
| 
 | |
|             state->y++;
 | |
| 
 | |
|             state->count = 1;
 | |
|             state->LAST = state->buffer[0];
 | |
| 
 | |
|             state->x = 1;
 | |
| 
 | |
|             state->state = ENCODE;
 | |
|             /* fall through */
 | |
| 
 | |
|         case ENCODE:
 | |
| 
 | |
|             /* compress this line */
 | |
| 
 | |
|             /* when we arrive here, "count" contains the number of
 | |
|                bytes having the value of "LAST" that we've already
 | |
|                seen */
 | |
| 
 | |
|             while (state->x < state->bytes) {
 | |
| 
 | |
|                 if (state->count == 63) {
 | |
| 
 | |
|                     /* this run is full; flush it */
 | |
|                     if (bytes < 2)
 | |
|                         return ptr - buf;
 | |
|                     *ptr++ = 0xff;
 | |
|                     *ptr++ = state->LAST;
 | |
|                     bytes -= 2;
 | |
| 
 | |
|                     state->count = 0;
 | |
| 
 | |
|                 }
 | |
| 
 | |
|                 this = state->buffer[state->x];
 | |
| 
 | |
|                 if (this == state->LAST) {
 | |
| 
 | |
|                     /* extend the current run */
 | |
|                     state->x++;
 | |
|                     state->count++;
 | |
| 
 | |
|                 } else {
 | |
| 
 | |
|                     /* start a new run */
 | |
|                     if (state->count == 1 && (state->LAST < 0xc0)) {
 | |
|                         if (bytes < 1)
 | |
|                             return ptr - buf;
 | |
|                         *ptr++ = state->LAST;
 | |
|                         bytes--;
 | |
|                     } else {
 | |
|                         if (state->count > 0) {
 | |
|                             if (bytes < 2)
 | |
|                                 return ptr - buf;
 | |
|                             *ptr++ = 0xc0 | state->count;
 | |
|                             *ptr++ = state->LAST;
 | |
|                             bytes -= 2;
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     state->LAST = this;
 | |
|                     state->count = 1;
 | |
| 
 | |
|                     state->x++;
 | |
| 
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             /* end of line; flush the current run */
 | |
|             if (state->count == 1 && (state->LAST < 0xc0)) {
 | |
|                 if (bytes < 1)
 | |
|                     return ptr - buf;
 | |
|                 *ptr++ = state->LAST;
 | |
|                 bytes--;
 | |
|             } else {
 | |
|                 if (state->count > 0) {
 | |
|                     if (bytes < 2)
 | |
|                         return ptr - buf;
 | |
|                     *ptr++ = 0xc0 | state->count;
 | |
|                     *ptr++ = state->LAST;
 | |
|                     bytes -= 2;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             /* read next line */
 | |
|             state->state = FETCH;
 | |
|             break;
 | |
| 
 | |
|         }
 | |
| }
 |