Exemple #1
0
static int DGifDecompressLine(GifFileType * GifFile, GifPixelType * Line, int LineLen)
{
	int i = 0;
	int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
	GifByteType *Stack, *Suffix;
	GifPrefixType *Prefix;
	GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;

	StackPtr = Private->StackPtr;
	Prefix = Private->Prefix;
	Suffix = Private->Suffix;
	Stack = Private->Stack;
	EOFCode = Private->EOFCode;
	ClearCode = Private->ClearCode;
	LastCode = Private->LastCode;

	if (StackPtr > LZ_MAX_CODE)
	{
		return GIF_ERROR;
	}

	if (StackPtr != 0)
	{
		while (StackPtr != 0 && i < LineLen)
			Line[i++] = Stack[--StackPtr];
	}

	while (i < LineLen)
	{
		if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
			return GIF_ERROR;

		if (CrntCode == EOFCode)
		{
			if (i != LineLen - 1 || Private->PixelCount != 0)
			{
				_GifError = D_GIF_ERR_EOF_TOO_SOON;
				return GIF_ERROR;
			}
			i++;
		}
		else if (CrntCode == ClearCode)
		{
			for (j = 0; j <= LZ_MAX_CODE; j++)
				Prefix[j] = NO_SUCH_CODE;
			Private->RunningCode = Private->EOFCode + 1;
			Private->RunningBits = Private->BitsPerPixel + 1;
			Private->MaxCode1 = 1 << Private->RunningBits;
			LastCode = Private->LastCode = NO_SUCH_CODE;
		}
		else
		{
			if (CrntCode < ClearCode)
			{
				Line[i++] = CrntCode;
			}
			else
			{
				if (Prefix[CrntCode] == NO_SUCH_CODE)
				{
					if (CrntCode == Private->RunningCode - 2)
					{
						CrntPrefix = LastCode;
						Suffix[Private->RunningCode - 2] = Stack[StackPtr++] = DGifGetPrefixChar(Prefix, LastCode, ClearCode);
					}
					else
					{
						_GifError = D_GIF_ERR_IMAGE_DEFECT;
						return GIF_ERROR;
					}
				}
				else
					CrntPrefix = CrntCode;

				j = 0;
				while (j++ <= LZ_MAX_CODE && CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE)
				{
					Stack[StackPtr++] = Suffix[CrntPrefix];
					CrntPrefix = Prefix[CrntPrefix];
				}
				if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE)
				{
					_GifError = D_GIF_ERR_IMAGE_DEFECT;
					return GIF_ERROR;
				}
				Stack[StackPtr++] = CrntPrefix;

				while (StackPtr != 0 && i < LineLen)
					Line[i++] = Stack[--StackPtr];
			}
			if (LastCode != NO_SUCH_CODE)
			{
				Prefix[Private->RunningCode - 2] = LastCode;

				if (CrntCode == Private->RunningCode - 2)
				{
					Suffix[Private->RunningCode - 2] = DGifGetPrefixChar(Prefix, LastCode, ClearCode);
				}
				else
				{
					Suffix[Private->RunningCode - 2] = DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
				}
			}
			LastCode = CrntCode;
		}
	}
	Private->LastCode = LastCode;
	Private->StackPtr = StackPtr;
	return GIF_OK;
}
Exemple #2
0
/******************************************************************************
 The LZ decompression routine:
 This version decompress the given GIF file into Line of length LineLen.
 This routine can be called few times (one per scan line, for example), in
 order the complete the whole image.
******************************************************************************/
static int
DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
{
    int i = 0;
    int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
    GifByteType *Stack, *Suffix;
    GifPrefixType *Prefix;
    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;

    StackPtr = Private->StackPtr;
    Prefix = Private->Prefix;
    Suffix = Private->Suffix;
    Stack = Private->Stack;
    EOFCode = Private->EOFCode;
    ClearCode = Private->ClearCode;
    LastCode = Private->LastCode;

    if (StackPtr > LZ_MAX_CODE) {
        return GIF_ERROR;
    }

    if (StackPtr != 0) {
        /* Let pop the stack off before continueing to read the GIF file: */
        while (StackPtr != 0 && i < LineLen)
            Line[i++] = Stack[--StackPtr];
    }

    while (i < LineLen) {    /* Decode LineLen items. */
        if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
            return GIF_ERROR;

        if (CrntCode == EOFCode) {
            /* Note however that usually we will not be here as we will stop
             * decoding as soon as we got all the pixel, or EOF code will
             * not be read at all, and DGifGetLine/Pixel clean everything.  */
	    GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
	    return GIF_ERROR;
        } else if (CrntCode == ClearCode) {
            /* We need to start over again: */
            for (j = 0; j <= LZ_MAX_CODE; j++)
                Prefix[j] = NO_SUCH_CODE;
            Private->RunningCode = Private->EOFCode + 1;
            Private->RunningBits = Private->BitsPerPixel + 1;
            Private->MaxCode1 = 1 << Private->RunningBits;
            LastCode = Private->LastCode = NO_SUCH_CODE;
        } else {
            /* Its regular code - if in pixel range simply add it to output
             * stream, otherwise trace to codes linked list until the prefix
             * is in pixel range: */
            if (CrntCode < ClearCode) {
                /* This is simple - its pixel scalar, so add it to output: */
                Line[i++] = CrntCode;
            } else {
                /* Its a code to needed to be traced: trace the linked list
                 * until the prefix is a pixel, while pushing the suffix
                 * pixels on our stack. If we done, pop the stack in reverse
                 * (thats what stack is good for!) order to output.  */
                if (Prefix[CrntCode] == NO_SUCH_CODE) {
                    /* Only allowed if CrntCode is exactly the running code:
                     * In that case CrntCode = XXXCode, CrntCode or the
                     * prefix code is last code and the suffix char is
                     * exactly the prefix of last code! */
                    if (CrntCode == Private->RunningCode - 2) {
                        CrntPrefix = LastCode;
                        Suffix[Private->RunningCode - 2] =
                           Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
                                                                 LastCode,
                                                                 ClearCode);
                    } else {
                        GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
                        return GIF_ERROR;
                    }
                } else
                    CrntPrefix = CrntCode;

                /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
                 * during the trace. As we might loop forever, in case of
                 * defective image, we use StackPtr as loop counter and stop
                 * before overflowing Stack[]. */
                while (StackPtr < LZ_MAX_CODE &&
                       CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
                    Stack[StackPtr++] = Suffix[CrntPrefix];
                    CrntPrefix = Prefix[CrntPrefix];
                }
                if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
                    GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
                    return GIF_ERROR;
                }
                /* Push the last character on stack: */
                Stack[StackPtr++] = CrntPrefix;

                /* Now lets pop all the stack into output: */
                while (StackPtr != 0 && i < LineLen)
                    Line[i++] = Stack[--StackPtr];
            }
            if (LastCode != NO_SUCH_CODE) {
                Prefix[Private->RunningCode - 2] = LastCode;

                if (CrntCode == Private->RunningCode - 2) {
                    /* Only allowed if CrntCode is exactly the running code:
                     * In that case CrntCode = XXXCode, CrntCode or the
                     * prefix code is last code and the suffix char is
                     * exactly the prefix of last code! */
                    Suffix[Private->RunningCode - 2] =
                       DGifGetPrefixChar(Prefix, LastCode, ClearCode);
                } else {
                    Suffix[Private->RunningCode - 2] =
                       DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
                }
            }
            LastCode = CrntCode;
        }
    }

    Private->LastCode = LastCode;
    Private->StackPtr = StackPtr;

    return GIF_OK;
}