Пример #1
0
/*
 * Allocate a color map of given size; initialize with contents of
 * ColorMap if that pointer is non-NULL.
 */
ColorMapObject *
MakeMapObject(int ColorCount,
              const GifColorType * ColorMap) {

    ColorMapObject *Object;

    /*** FIXME: Our ColorCount has to be a power of two.  Is it necessary to
     * make the user know that or should we automatically round up instead? */
    if (ColorCount != (1 << BitSize(ColorCount))) {
        return ((ColorMapObject *) NULL);
    }

    Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
    if (Object == (ColorMapObject *) NULL) {
        return ((ColorMapObject *) NULL);
    }

    Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
    if (Object->Colors == (GifColorType *) NULL) {
        free(Object);
        return ((ColorMapObject *) NULL);
    }

    Object->ColorCount = ColorCount;
    Object->BitsPerPixel = BitSize(ColorCount);

    if (ColorMap) {
        memcpy((char *)Object->Colors,
               (char *)ColorMap, ColorCount * sizeof(GifColorType));
    }

    return (Object);
}
Пример #2
0
static ColorMapObject * MakeMapObject(int ColorCount, const GifColorType * ColorMap)
{
	ColorMapObject *Object;

	if (ColorCount != (1 << BitSize(ColorCount)))
	{
		return ((ColorMapObject *) NULL);
	}

	Object = (ColorMapObject *) gif_malloc(sizeof(ColorMapObject));
	if (Object == (ColorMapObject *) NULL)
	{
		return ((ColorMapObject *) NULL);
	}

	Object->Colors = (GifColorType *) calloc(ColorCount, sizeof(GifColorType));
	if (Object->Colors == (GifColorType *) NULL)
	{
		return ((ColorMapObject *) NULL);
	}

	Object->ColorCount = ColorCount;
	Object->BitsPerPixel = BitSize(ColorCount);

	if (ColorMap)
	{
		memcpy((char *) Object->Colors, (char *) ColorMap, ColorCount * sizeof(GifColorType));
	}

	return (Object);
}
Пример #3
0
ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap)
/*
 * Allocate a color map of given size; initialize with contents of
 * ColorMap if that pointer is non-NULL.
 */
{
    ColorMapObject *Object;

    if (ColorCount != (1 << BitSize(ColorCount)))
	return((ColorMapObject *)NULL);

    Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
    if (Object == (ColorMapObject *)NULL)
	return((ColorMapObject *)NULL);

    Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
    if (Object->Colors == (GifColorType *)NULL)
	return((ColorMapObject *)NULL);

    Object->ColorCount = ColorCount;
    Object->BitsPerPixel = BitSize(ColorCount);

    if (ColorMap)
	memcpy((char *)Object->Colors,
	       (char *)ColorMap, ColorCount * sizeof(GifColorType));

    return(Object);
}
Пример #4
0
void CGeneralHeader::Encode(Int32Bit Signature, Int4Bit Version, EBarcodeType BarcodeType)
{
	size_t NumberOfBits	= BitSize(Signature) 
		+ BitSize(Version) 
		+ BitSize(BarcodeType);
	IncreaseBitBufferSize(NumberOfBits);

	CBitPointer BitPtr = AllocateBitBuffer();
	BitCopyAndContinue(BitPtr, Signature);
	BitCopyAndContinue(BitPtr, Version);
	BitCopyAndContinue(BitPtr, BarcodeType);
}
Пример #5
0
/*
 * Compute the union of two given color maps and return it.  If result can't
 * fit into 256 colors, NULL is returned, the allocated union otherwise.
 * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
 * copied iff they didn't exist before.  ColorTransIn2 maps the old
 * ColorIn2 into ColorUnion color map table.
 */
ColorMapObject *
UnionColorMap(const ColorMapObject * ColorIn1,
              const ColorMapObject * ColorIn2,
              GifPixelType ColorTransIn2[]) {

    int i, j, CrntSlot, RoundUpTo, NewBitSize;
    ColorMapObject *ColorUnion;

    /*
     * Allocate table which will hold the result for sure.
     */
    ColorUnion = MakeMapObject(MAX(ColorIn1->ColorCount,
                                   ColorIn2->ColorCount) * 2, NULL);

    if (ColorUnion == NULL)
        return (NULL);

    /* Copy ColorIn1 to ColorUnionSize; */
    /*** FIXME: What if there are duplicate entries into the colormap to begin
     * with? */
    for (i = 0; i < ColorIn1->ColorCount; i++)
        ColorUnion->Colors[i] = ColorIn1->Colors[i];
    CrntSlot = ColorIn1->ColorCount;

    /*
     * Potentially obnoxious hack:
     *
     * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
     * of table 1.  This is very useful if your display is limited to
     * 16 colors.
     */
    while (ColorIn1->Colors[CrntSlot - 1].Red == 0
            && ColorIn1->Colors[CrntSlot - 1].Green == 0
            && ColorIn1->Colors[CrntSlot - 1].Blue == 0)
        CrntSlot--;

    /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */
    for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) {
        /* Let's see if this color already exists: */
        /*** FIXME: Will it ever occur that ColorIn2 will contain duplicate
         * entries?  So we should search from 0 to CrntSlot rather than
         * ColorIn1->ColorCount?
         */
        for (j = 0; j < ColorIn1->ColorCount; j++)
            if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i],
                        sizeof(GifColorType)) == 0)
                break;

        if (j < ColorIn1->ColorCount)
            ColorTransIn2[i] = j;    /* color exists in Color1 */
        else {
            /* Color is new - copy it to a new slot: */
            ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
            ColorTransIn2[i] = CrntSlot++;
        }
    }

    if (CrntSlot > 256) {
        FreeMapObject(ColorUnion);
        return ((ColorMapObject *) NULL);
    }

    NewBitSize = BitSize(CrntSlot);
    RoundUpTo = (1 << NewBitSize);

    if (RoundUpTo > 0 && RoundUpTo != ColorUnion->ColorCount) {
        register GifColorType *Map = ColorUnion->Colors;

        /*
         * Zero out slots up to next power of 2.
         * We know these slots exist because of the way ColorUnion's
         * start dimension was computed.
         */
        for (j = CrntSlot; j < RoundUpTo; j++)
            Map[j].Red = Map[j].Green = Map[j].Blue = 0;

        /* perhaps we can shrink the map? */
        if (RoundUpTo < ColorUnion->ColorCount) {
            GifColorType *new_map = (GifColorType *)realloc(Map,
                                    RoundUpTo * sizeof(GifColorType));
            if( new_map == NULL ) {
                FreeMapObject(ColorUnion);
                return ((ColorMapObject *) NULL);
            }
            ColorUnion->Colors = new_map;
        }
    }

    ColorUnion->ColorCount = RoundUpTo;
    ColorUnion->BitsPerPixel = NewBitSize;

    return (ColorUnion);
}
Пример #6
0
/******************************************************************************
* Modify the given colormap according to global variables setting.	      *
******************************************************************************/
static ColorMapObject *ModifyColorMap(ColorMapObject *ColorMap)
{
    int i, Dummy, Red, Green, Blue, Max = 0;
    double Gamma1;

    if (SaveFlag) {
	/* Save this color map to ColorFile: */
	for (i = 0; i < ColorMap->ColorCount; i++)
	    fprintf(ColorFile, "%3d %3d %3d %3d\n", i,
		    ColorMap->Colors[i].Red,
		    ColorMap->Colors[i].Green,
		    ColorMap->Colors[i].Blue);
	return(ColorMap);
    }
    else if (LoadFlag) {
	/* Read the color map in ColorFile into this color map: */
	for (i = 0; i < ColorMap->ColorCount; i++) {
	    if (feof(ColorFile))
		GIF_EXIT("Color file to load color map from, too small.");
	    fscanf(ColorFile, "%3d %3d %3d %3d\n", &Dummy, &Red, &Green, &Blue);
	    ColorMap->Colors[i].Red = Red;
	    ColorMap->Colors[i].Green = Green;
	    ColorMap->Colors[i].Blue = Blue;
	}
	return(ColorMap);
    }
    else if (GammaFlag) {
	/* Apply gamma correction to this color map: */
	Gamma1 = 1.0 / Gamma;
	for (i = 0; i < ColorMap->ColorCount; i++) {
	    ColorMap->Colors[i].Red =
		((int) (255 * pow(ColorMap->Colors[i].Red / 255.0, Gamma1)));
	    ColorMap->Colors[i].Green =
		((int) (255 * pow(ColorMap->Colors[i].Green / 255.0, Gamma1)));
	    ColorMap->Colors[i].Blue =
		((int) (255 * pow(ColorMap->Colors[i].Blue / 255.0, Gamma1)));
	}
	return(ColorMap);
    }
    else if (TranslateFlag) {
	ColorMapObject *NewMap;

	/* Read the translation table in TranslateFile: */
	for (i = 0; i < ColorMap->ColorCount; i++) {
	    int tmp;
	    if (feof(TranslateFile))
		GIF_EXIT("Color file to load color map from, too small.");
	    fscanf(TranslateFile, "%3d %3d\n", &Dummy, &tmp);
	    Translation[i] = tmp;
	    if (Translation[i] > Max)
		Max = Translation[i];
	}

	if ((NewMap = MakeMapObject(1 << BitSize(Max+1), NULL)) == NULL)
	    GIF_EXIT("Out of memory while allocating color map!");

	/* Apply the translation; we'll do it to the pixels, too */
	for (i = 0; i < ColorMap->ColorCount; i++) {
	    NewMap->Colors[i] = ColorMap->Colors[Translation[i]];
	}
	
	return(NewMap);
    }
    else
    {
	GIF_EXIT("Nothing to do!");
	return(ColorMap);
    }
}
Пример #7
0
void CPavementItem::Encode(	EShapeType ShapeType, ETextureType TextureType, Int4Bit FillType,
						   bool IsAdjacentToParking, USizeOrSide SizeOrSide, std::vector<SVertexParameters> ListOfVertices,
						   SCurvatureParameters SpecialVertexCurvature, Int6Bit ShortenVertexCoordinate)
{

// Note, this is a hack!:
// Normally Encode does not touch local members, but it does fill up the following
// member for the sake of GetItemBitBufferParsedString accurate interpretation.
	m_IsAdjacentToParking = IsAdjacentToParking; 

	Int2Bit ShapeID;
	bool ListOfVerticesSizeCheck = false;  //Checking if number of given vertexes is correct
	switch (ShapeType)
	{
		case Wall:
			ShapeID = ConvertIntToInt2Bit(0);
			if ((IsAdjacentToParking && (ListOfVertices.size() == 0)) || (!IsAdjacentToParking && (ListOfVertices.size() == 1)))
				ListOfVerticesSizeCheck = true;
			break;
		case Right_Triangle:
			ShapeID = ConvertIntToInt2Bit(((IsAdjacentToParking) ? 1 : 0));
			if ((IsAdjacentToParking && (ListOfVertices.size() == 0)) || (!IsAdjacentToParking && (ListOfVertices.size() == 1)))
				ListOfVerticesSizeCheck = true;
			break;
		case Triangle:
			ShapeID = ConvertIntToInt2Bit(1);
			if ((IsAdjacentToParking && (ListOfVertices.size() == 0)) || (!IsAdjacentToParking && (ListOfVertices.size() == 2)))
				ListOfVerticesSizeCheck = true;
			break;
		case Rect:
			ShapeID = ConvertIntToInt2Bit(((IsAdjacentToParking) ? 1 : 0));
			if ((IsAdjacentToParking && (ListOfVertices.size() == 0)) || (!IsAdjacentToParking && (ListOfVertices.size() == 1)))
				ListOfVerticesSizeCheck = true;
			break;
		case Quadrangle:
			ShapeID = ConvertIntToInt2Bit(2);
			if ((IsAdjacentToParking && (ListOfVertices.size() == 2)) || (!IsAdjacentToParking && (ListOfVertices.size() == 3)))
				ListOfVerticesSizeCheck = true;
			break;
		case Pentagon:
			ShapeID = ConvertIntToInt2Bit(3);
			if ((IsAdjacentToParking && (ListOfVertices.size() == 3)) || (!IsAdjacentToParking && (ListOfVertices.size() == 4)))
				ListOfVerticesSizeCheck = true;
			break;
		default:
			ShapeID = ConvertIntToInt2Bit(0);
	}


	if (ListOfVerticesSizeCheck)
	{
		size_t NumberOfBits	= BitSize(ShapeID)
							+ ((!(ShapeType == Wall) && IsAdjacentToParking) ? BitSize(ShortenVertexCoordinate) : 0)
							+ ((!IsAdjacentToParking) ? BitSize(TextureType) : 0 )
							+ (((TextureType == SolidFill) && (!IsAdjacentToParking)) ? BitSize(FillType) : 0)
	//						+ BitSize(IsAdjacentToParking)
							+ ((IsAdjacentToParking) ? 0 : BitSize(SizeOrSide.ReducedSize));

		if (!((ShapeType == Wall) && IsAdjacentToParking))
		{
			NumberOfBits += BitSize(SpecialVertexCurvature.Type);
			if ((SpecialVertexCurvature.Type == Convex) || (SpecialVertexCurvature.Type == Concave))
				NumberOfBits += BitSize(SpecialVertexCurvature.IsCircular);
		}

		if (IsAdjacentToParking && (!(ShapeType == Wall)))
			NumberOfBits += BitSize(SizeOrSide.Side);
		
		if ((ShapeType == Quadrangle) || (ShapeType == Pentagon) || (! IsAdjacentToParking))
		{
			NumberOfBits += BitSize(ListOfVertices[0].CurvatureType);
			if ((ListOfVertices[0].CurvatureType == Convex) || (ListOfVertices[0].CurvatureType == Concave))
				NumberOfBits += BitSize(ListOfVertices[0].IsCircular);

			if (IsAdjacentToParking || SizeOrSide.ReducedSize)
			{	//6 bit
				NumberOfBits += ListOfVertices.size() * (  BitSize(ListOfVertices[0].X.Size6bits)
														 + BitSize(ListOfVertices[0].Y.Size6bits));
			}
			else  
			{	// 8 bit
				NumberOfBits += ListOfVertices.size() * (  BitSize(ListOfVertices[0].X.Size8bits)
														 + BitSize(ListOfVertices[0].Y.Size8bits));
			}
		}
		


		IncreaseBitBufferSize(NumberOfBits);

		CBitPointer BitPtr = AllocateBitBuffer();
	//	BitCopyAndContinue(BitPtr, IsAdjacentToParking);

		BitCopyAndContinue(BitPtr, ShapeID);

		if (!((ShapeType == Wall) && IsAdjacentToParking))
		{
			BitCopyAndContinue(BitPtr, SpecialVertexCurvature.Type);
			if ((SpecialVertexCurvature.Type == Convex) || (SpecialVertexCurvature.Type == Concave))
				BitCopyAndContinue(BitPtr, SpecialVertexCurvature.IsCircular);
		}

		if ((!(ShapeType == Wall) && IsAdjacentToParking))
			BitCopyAndContinue(BitPtr, ShortenVertexCoordinate);
		
		if (IsAdjacentToParking)
		{
			if (!(ShapeType == Wall))
				BitCopyAndContinue(BitPtr, SizeOrSide.Side);
		}
		else
			BitCopyAndContinue(BitPtr, SizeOrSide.ReducedSize);


		for (unsigned int i =0; i < ListOfVertices.size(); i++)
		{
			if (IsAdjacentToParking || SizeOrSide.ReducedSize)
			{ //6 bit
				BitCopyAndContinue(BitPtr, ListOfVertices[i].X.Size6bits);
				BitCopyAndContinue(BitPtr, ListOfVertices[i].Y.Size6bits);
			}
			else
			{ //8 bit
				BitCopyAndContinue(BitPtr, ListOfVertices[i].X.Size8bits);
				BitCopyAndContinue(BitPtr, ListOfVertices[i].Y.Size8bits);
			}

			BitCopyAndContinue(BitPtr, ListOfVertices[i].CurvatureType);
			if ((ListOfVertices[i].CurvatureType == Convex) || (ListOfVertices[i].CurvatureType == Concave))
				BitCopyAndContinue(BitPtr, ListOfVertices[i].IsCircular);
		}

		if (!IsAdjacentToParking && (ShapeType != Wall))
		{
			BitCopyAndContinue(BitPtr, TextureType);
			if (TextureType == SolidFill)
				BitCopyAndContinue(BitPtr, FillType);
		}
	}
}
Пример #8
0
/*virtual*/ void CPavementItem::Decode(IN const CBitPointer &Data, IN OUT int &UsedBits, IN int *Context)
{
	bool m_IsAdjacentToParking = *(bool *)Context;

	Int2Bit m_ShapeID;

	int BitsToRead = UsedBits; BitsToRead;
	CBitPointer BitPtr = Data + BitSize(GetType());

//	BitPasteAndContinue(BitPtr, m_IsAdjacentToParking);


	BitPasteAndContinue(BitPtr, m_ShapeID);
	int m_ShapeID_int = m_ShapeID;

	if (!((m_ShapeID_int == 0) && m_IsAdjacentToParking))
	{
		BitPasteAndContinue(BitPtr, m_SpecialVertexCurvature.Type);
		if ((m_SpecialVertexCurvature.Type == Convex) || (m_SpecialVertexCurvature.Type == Concave))
			BitPasteAndContinue(BitPtr, m_SpecialVertexCurvature.IsCircular);
	}

	if ((!(m_ShapeID_int == 0) && m_IsAdjacentToParking))
		BitPasteAndContinue(BitPtr, m_ShortenVertexCoordinate);


	if (m_IsAdjacentToParking)
	{
		if (!(m_ShapeID_int == 0))
			BitPasteAndContinue(BitPtr, m_SizeOrSide.Side);
	}
	else
		BitPasteAndContinue(BitPtr, m_SizeOrSide.ReducedSize);


	unsigned int ListOfVerticesSize;
	if (m_IsAdjacentToParking)
		ListOfVerticesSize = ((m_ShapeID_int < 2) ? 0 : m_ShapeID_int);
	else
		ListOfVerticesSize = m_ShapeID_int + 1;

	for (unsigned int i =0; i < ListOfVerticesSize; i++)
	{
		SVertexParameters FullVertex;

		if (m_IsAdjacentToParking || m_SizeOrSide.ReducedSize)
		{ //6 bit
			BitPasteAndContinue(BitPtr, FullVertex.X.Size6bits);
			BitPasteAndContinue(BitPtr, FullVertex.Y.Size6bits);
		}
		else
		{ //8 bit
			BitPasteAndContinue(BitPtr, FullVertex.X.Size8bits);
			BitPasteAndContinue(BitPtr, FullVertex.Y.Size8bits);
		}

		BitPasteAndContinue(BitPtr, FullVertex.CurvatureType);
		if ((FullVertex.CurvatureType == Convex) || (FullVertex.CurvatureType == Concave))
			BitPasteAndContinue(BitPtr, FullVertex.IsCircular);

		m_ListOfVertices.push_back(FullVertex);
	}

	switch (m_ShapeID_int)
	{
	case 0:
		if (m_IsAdjacentToParking)
			m_ShapeType = Wall;
		else
			if (m_SpecialVertexCurvature.Type != m_ListOfVertices[0].CurvatureType)
				m_ShapeType = Right_Triangle;
			else
				((m_SpecialVertexCurvature.Type == Rectangular) ? m_ShapeType = Rect : m_ShapeType = Wall);
		break;
	case 1:
		if (!m_IsAdjacentToParking)
			m_ShapeType = Triangle;
		else
			if (m_SpecialVertexCurvature.Type == Rectangular) 
				m_ShapeType = Rect;
			else 
				m_ShapeType = Triangle;
		break;
	case 2:
		m_ShapeType = Quadrangle;
		break;
	case 3:
		m_ShapeType = Pentagon;
		break;
	default:
		m_ShapeType = Wall;
	}

	if (!m_IsAdjacentToParking && (m_ShapeType != Wall))
	{
		BitPasteAndContinue(BitPtr, m_TextureType);
		if (m_TextureType == SolidFill)
			BitPasteAndContinue(BitPtr, m_FillType);
	}

	UsedBits = (int)(BitPtr - Data);
}
Пример #9
0
static void Icon2Gif(char *FileName, FILE *txtin, int fdout)
{
    unsigned int	ExtCode, ColorMapSize = 0;
    GifColorType GlobalColorMap[256], LocalColorMap[256],
	*ColorMap = GlobalColorMap;
    char GlobalColorKeys[PRINTABLES], LocalColorKeys[PRINTABLES],
	*KeyTable = GlobalColorKeys;
    int red, green, blue;

    char buf[BUFSIZ * 2], InclusionFile[64];
    GifFileType *GifFileOut;
    SavedImage *NewImage = NULL;
    int n, LineNum = 0;

    if ((GifFileOut = EGifOpenFileHandle(fdout)) == NULL) {
	(void) HandleGifError(GifFileOut);
    }

    /* OK, interpret directives */
    while (fgets(buf, sizeof(buf), txtin) != (char *)NULL)
    {
	char	*cp;

	++LineNum;

	/*
	 * Skip lines consisting only of whitespace and comments
	 */
	for (cp = buf; isspace((int)(*cp)); cp++)
	    continue;
	if (*cp == '#' || *cp == '\0')
	    continue;

	/*
	 * If there's a trailing comment, nuke it and all preceding whitespace.
	 * But preserve the EOL.
	 */
	if ((cp = strchr(buf, '#')) && (cp == strrchr(cp, '#')))
	{
	    while (isspace((int)(*--cp)))
		continue;
	    *++cp = '\n';
	    *++cp = '\0';
	}

	/*
	 * Explicit header declarations
	 */

	if (sscanf(buf, "screen width %d\n", &GifFileOut->SWidth) == 1)
	    continue;

	else if (sscanf(buf, "screen height %d\n", &GifFileOut->SHeight) == 1)
	    continue;

	else if (sscanf(buf, "screen colors %d\n", &n) == 1)
	{
	    int	ResBits = BitSize(n);

	    if (n > 256 || n < 0 || n != (1 << ResBits))
	    {
		PARSE_ERROR("Invalid color resolution value.");
		exit(EXIT_FAILURE);
	    }

	    GifFileOut->SColorResolution = ResBits;
	    continue;
	}

	else if (sscanf(buf,
			"screen background %d\n",
			&GifFileOut->SBackGroundColor) == 1)
	    continue;

	/*
	 * Color table parsing
	 */

	else if (strcmp(buf, "screen map\n") == 0)
	{
	    if (GifFileOut->SColorMap != NULL)
	    {
		PARSE_ERROR("You've already declared a global color map.");
		exit(EXIT_FAILURE);
	    }

	    ColorMapSize = 0;
	    ColorMap = GlobalColorMap;
	    KeyTable = GlobalColorKeys;
	    memset(GlobalColorKeys, '\0', sizeof(GlobalColorKeys));
	}

	else if (strcmp(buf, "image map\n") == 0)
	{
	    if (NewImage == NULL)
	    {
		PARSE_ERROR("No previous image declaration.");
		exit(EXIT_FAILURE);
	    }

	    ColorMapSize = 0;
	    ColorMap = LocalColorMap;
	    KeyTable = LocalColorKeys;
	    memset(LocalColorKeys, '\0', sizeof(LocalColorKeys));
	}

	else if (sscanf(buf, "	rgb %d %d %d is %c",
		   &red, &green, &blue, &KeyTable[ColorMapSize]) == 4)
	{
	    ColorMap[ColorMapSize].Red = red;
	    ColorMap[ColorMapSize].Green = green;
	    ColorMap[ColorMapSize].Blue = blue;
	    ColorMapSize++;
	}

	else if (strcmp(buf, "end\n") == 0)
	{
	    ColorMapObject	*NewMap;


	    NewMap = MakeMapObject(1 << BitSize(ColorMapSize), ColorMap);
	    if (NewMap == (ColorMapObject *)NULL)
	    {
		PARSE_ERROR("Out of memory while allocating new color map.");
		exit(EXIT_FAILURE);
	    }

	    if (NewImage)
		NewImage->ImageDesc.ColorMap = NewMap;
	    else
		GifFileOut->SColorMap = NewMap;
	}

	/* GIF inclusion */
	else if (sscanf(buf, "include %s", InclusionFile) == 1)
	{
	    GifBooleanType	DoTranslation;
	    GifPixelType	Translation[256];

	    GifFileType	*Inclusion;
	    SavedImage	*NewImage, *CopyFrom;

	    if ((Inclusion = DGifOpenFileName(InclusionFile)) == NULL
		|| DGifSlurp(Inclusion) == GIF_ERROR)
	    {
		PARSE_ERROR("Inclusion read failed.");
        QuitGifError(Inclusion, GifFileOut);
	    }

	    if ((DoTranslation = (GifFileOut->SColorMap!=(ColorMapObject*)NULL)))
	    {
		ColorMapObject	*UnionMap;

		UnionMap = UnionColorMap(GifFileOut->SColorMap,
					 Inclusion->SColorMap, Translation);

		if (UnionMap == NULL)
		{
		    PARSE_ERROR("Inclusion failed --- global map conflict.");
            QuitGifError(Inclusion, GifFileOut);
		}

		FreeMapObject(GifFileOut->SColorMap);
		GifFileOut->SColorMap = UnionMap;
	    }

	    for (CopyFrom = Inclusion->SavedImages;
		 CopyFrom < Inclusion->SavedImages + Inclusion->ImageCount;
		 CopyFrom++)
	    {
		if ((NewImage = MakeSavedImage(GifFileOut, CopyFrom)) == NULL)
		{
		    PARSE_ERROR("Inclusion failed --- out of memory.");
            QuitGifError(Inclusion, GifFileOut);
		}
		else if (DoTranslation)
		    ApplyTranslation(NewImage, Translation);

		GifQprintf(
		        "%s: Image %d at (%d, %d) [%dx%d]: from %s\n",
			PROGRAM_NAME, GifFileOut->ImageCount,
			NewImage->ImageDesc.Left, NewImage->ImageDesc.Top,
			NewImage->ImageDesc.Width, NewImage->ImageDesc.Height,
			InclusionFile);
	    }

	    (void) DGifCloseFile(Inclusion);
	}

	/*
	 * Explicit image declarations 
	 */

	else if (strcmp(buf, "image\n") == 0)
	{
	    if ((NewImage = MakeSavedImage(GifFileOut, NULL)) == (SavedImage *)NULL)
	    {
		PARSE_ERROR("Out of memory while allocating image block.");
		exit(EXIT_FAILURE);
	    }

	    /* use global table unless user specifies a local one */
	    ColorMap = GlobalColorMap;
	    KeyTable = GlobalColorKeys;
	}

	/*
	 * Nothing past this point is valid unless we've seen a previous
	 * image declaration.
	 */
	else if (NewImage == (SavedImage *)NULL)
	{
	    (void) fputs(buf, stderr);
	    PARSE_ERROR("Syntax error in header block.");
	    exit(EXIT_FAILURE);
	}

	/*
	 * Accept image attributes
	 */
	else if (sscanf(buf, "image top %d\n", &NewImage->ImageDesc.Top) == 1)
	    continue;

	else if (sscanf(buf, "image left %d\n", &NewImage->ImageDesc.Left)== 1)
	    continue;

	else if (strcmp(buf, "image interlaced\n") == 0)
	{
	    NewImage->ImageDesc.Interlace = TRUE;
	    continue;
	}

	else if (sscanf(buf,
			"image bits %d by %d\n",
			&NewImage->ImageDesc.Width,
			&NewImage->ImageDesc.Height) == 2)
	{
	    int i, j;
	    static GifPixelType *Raster, *cp;
	    int c;

	    if ((Raster = (GifPixelType *) malloc(sizeof(GifPixelType) * NewImage->ImageDesc.Width * NewImage->ImageDesc.Height))
		== NULL) {
		PARSE_ERROR("Failed to allocate raster block, aborted.");
		exit(EXIT_FAILURE);
	    }

	    if (!GifQuietPrint)
		fprintf(stderr, "%s: Image %d at (%d, %d) [%dx%d]:     ",
		    PROGRAM_NAME, GifFileOut->ImageCount,
		    NewImage->ImageDesc.Left, NewImage->ImageDesc.Top,
		    NewImage->ImageDesc.Width, NewImage->ImageDesc.Height);

	    cp = Raster;
	    for (i = 0; i < NewImage->ImageDesc.Height; i++) {

		char	*dp;

		for (j = 0; j < NewImage->ImageDesc.Width; j++)
		    if ((c = fgetc(txtin)) == EOF) {
			PARSE_ERROR("input file ended prematurely.");
			exit(EXIT_FAILURE);
		    }
		    else if (c == '\n')
		    {
			--j;
			++LineNum;
		    }
		    else if (isspace(c))
			--j;
		    else if ((dp = strchr(KeyTable, c)))
			*cp++ = (dp - KeyTable);
		    else {
			PARSE_ERROR("Invalid pixel value.");
			exit(EXIT_FAILURE);
		    }

		if (!GifQuietPrint)
		    fprintf(stderr, "\b\b\b\b%-4d", i);
	    }

	    if (!GifQuietPrint)
		putc('\n', stderr);

	    NewImage->RasterBits = (unsigned char *) Raster;
	}
	else if (sscanf(buf, "comment"))
	{
	    MakeExtension(NewImage, COMMENT_EXT_FUNC_CODE);
	    while (fgets(buf, sizeof(buf), txtin) != (char *)NULL)
		if (strcmp(buf, "end\n") == 0)
		    break;
	        else
		{
		    int Len;

		    buf[strlen(buf) - 1] = '\0';
		    Len = EscapeString(buf, buf);
		    if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) {
			PARSE_ERROR("out of memory while adding comment block.");
			exit(EXIT_FAILURE);
		    }
		}
	}
	else if (sscanf(buf, "plaintext"))
	{
	    MakeExtension(NewImage, PLAINTEXT_EXT_FUNC_CODE);
	    while (fgets(buf, sizeof(buf), txtin) != (char *)NULL)
		if (strcmp(buf, "end\n") == 0)
		    break;
	        else
		{
		    int Len;

		    buf[strlen(buf) - 1] = '\0';
		    Len = EscapeString(buf, buf);
		    if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) {
			PARSE_ERROR("out of memory while adding plaintext block.");
			exit(EXIT_FAILURE);
		    }
		}
	}
	else if (sscanf(buf, "extension %02x", &ExtCode))
	{
	    MakeExtension(NewImage, ExtCode);
	    while (fgets(buf, sizeof(buf), txtin) != (char *)NULL)
		if (strcmp(buf, "end\n") == 0)
		    break;
	        else
		{
		    int Len;

		    buf[strlen(buf) - 1] = '\0';
		    Len = EscapeString(buf, buf);
		    if (AddExtensionBlock(NewImage, Len, (unsigned char *)buf) == GIF_ERROR) {
			PARSE_ERROR("out of memory while adding extension block.");
			exit(EXIT_FAILURE);
		    }
		}
	}
	else
	{
	    (void) fputs(buf, stderr);
	    PARSE_ERROR("Syntax error in image description.");
	    exit(EXIT_FAILURE);
	}
    }

    if (EGifSpew(GifFileOut) == GIF_ERROR)
	HandleGifError(GifFileOut);
}
bool ParupaintPanvasInputOutput::exportGIF(ParupaintPanvas * panvas, const QString & filename, QString & errorStr)
{
	Q_ASSERT(panvas);
	if(filename.isEmpty())
		return (errorStr = "Enter a filename to save to.").isEmpty();

#ifndef PARUPAINT_NOGIF
	int error = 0;
	GifFileType * gif = EGifOpenFileName(filename.toStdString().c_str(), false, &error);

	foreach(const QImage & image, panvas->mergedImageFrames(true)){

		error = 0;
		bool alpha = false;
		QImage toWrite = convertToIndexed8(image, &alpha);

		QVector<QRgb> colorTable = toWrite.colorTable();
		ColorMapObject cmap;

		int numColors = 1 << BitSize(toWrite.colorCount());
		numColors = 256;

		cmap.ColorCount = numColors;
		cmap.BitsPerPixel = 8;	/// @todo based on numColors (or not? we did ask for Format_Indexed8, so the data is always 8-bit, right?)
		GifColorType* colorValues = (GifColorType*)malloc(cmap.ColorCount * sizeof(GifColorType));
		cmap.Colors = colorValues;
		int c = 0;
		for(; c < toWrite.colorCount(); ++c)
		{
			//qDebug("color %d has %02X%02X%02X", c, qRed(colorTable[c]), qGreen(colorTable[c]), qBlue(colorTable[c]));
			colorValues[c].Red = qRed(colorTable[c]);
			colorValues[c].Green = qGreen(colorTable[c]);
			colorValues[c].Blue = qBlue(colorTable[c]);
		}
		// In case we had an actual number of colors that's not a power of 2,
		// fill the rest with something (black perhaps).
		for (; c < numColors; ++c)
		{
			colorValues[c].Red = 0;
			colorValues[c].Green = 0;
			colorValues[c].Blue = 0;
		}

		/// @todo how to specify which version, or decide based on features in use
		// Because of this call, libgif is not re-entrant
		EGifSetGifVersion(gif, true);

		if ((error = EGifPutScreenDesc(gif, toWrite.width(), toWrite.height(), numColors, 0, &cmap)) == GIF_ERROR)
			qCritical("EGifPutScreenDesc returned error %d", error);

		int fps = (100.0/panvas->frameRate());

		char flags = 1 << 3;
		if(alpha) flags |= 1;

		char graphics_ext[] = {
			flags,
			(char)(fps % 256), (char)(fps / 256),
			(char)(alpha ? 0x00 : 0xff)
		};
		EGifPutExtension(gif, GRAPHICS_EXT_FUNC_CODE, 4, graphics_ext);

		if ((error = EGifPutImageDesc(gif, 0, 0, toWrite.width(), toWrite.height(), 0, &cmap)) == GIF_ERROR)
			qCritical("EGifPutImageDesc returned error %d", error);

		int lc = toWrite.height();
		int llen = toWrite.bytesPerLine();
		for (int l = 0; l < lc; ++l) {
			uchar* line = toWrite.scanLine(l);
			if ((error = EGifPutLine(gif, (GifPixelType*)line, llen)) == GIF_ERROR) {
				qCritical("EGifPutLine returned error %d", error);
			}
		}

		if(true){
			// loop forever
			unsigned char loopblock[3] = {1, 0, 0};
			EGifPutExtensionLeader(gif, APPLICATION_EXT_FUNC_CODE);
			EGifPutExtensionBlock(gif, 11, "NETSCAPE2.0");
			EGifPutExtensionBlock(gif, 3, loopblock);
			EGifPutExtensionTrailer(gif);
		}
	}

	EGifCloseFile(gif, &error);
	return true;
#endif
	return (errorStr = "GIF export not available.").isEmpty();
}
Пример #11
0
ColorMapObject *UnionColorMap(
			 ColorMapObject *ColorIn1,
			 ColorMapObject *ColorIn2,
			 GifPixelType ColorTransIn2[])
/*
 * Compute the union of two given color maps and return it.  If result can't 
 * fit into 256 colors, NULL is returned, the allocated union otherwise.
 * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
 * copied iff they didn't exist before.  ColorTransIn2 maps the old
 * ColorIn2 into ColorUnion color map table.
 */
{
    int i, j, CrntSlot, RoundUpTo, NewBitSize;
    ColorMapObject *ColorUnion;

    /*
     * Allocate table which will hold the result for sure.
     */
    ColorUnion
	= MakeMapObject(MAX(ColorIn1->ColorCount,ColorIn2->ColorCount)*2,NULL);

    if (ColorUnion == NULL)
	return(NULL);

    /* Copy ColorIn1 to ColorUnionSize; */
    for (i = 0; i < ColorIn1->ColorCount; i++)
	ColorUnion->Colors[i] = ColorIn1->Colors[i];
    CrntSlot = ColorIn1->ColorCount;

    /*
     * Potentially obnoxious hack:
     *
     * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
     * of table 1.  This is very useful if your display is limited to
     * 16 colors.
     */
    while (ColorIn1->Colors[CrntSlot-1].Red == 0
	   && ColorIn1->Colors[CrntSlot-1].Green == 0
	   && ColorIn1->Colors[CrntSlot-1].Red == 0)
	CrntSlot--;

    /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */
    for (i = 0; i < ColorIn2->ColorCount && CrntSlot<=256; i++)
    {
	/* Let's see if this color already exists: */
	for (j = 0; j < ColorIn1->ColorCount; j++)
	    if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0)
		break;

	if (j < ColorIn1->ColorCount)
	    ColorTransIn2[i] = j;	/* color exists in Color1 */
	else
	{
	    /* Color is new - copy it to a new slot: */
	    ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
	    ColorTransIn2[i] = CrntSlot++;
	}
    }

    if (CrntSlot > 256)
    {
	FreeMapObject(ColorUnion);
	return((ColorMapObject *)NULL);
    }

    NewBitSize = BitSize(CrntSlot);
    RoundUpTo = (1 << NewBitSize);

    if (RoundUpTo != ColorUnion->ColorCount)
    {
	register GifColorType	*Map = ColorUnion->Colors;

	/*
	 * Zero out slots up to next power of 2.
	 * We know these slots exist because of the way ColorUnion's
	 * start dimension was computed.
	 */
	for (j = CrntSlot; j < RoundUpTo; j++)
	    Map[j].Red = Map[j].Green = Map[j].Blue = 0;

	/* perhaps we can shrink the map? */
	if (RoundUpTo < ColorUnion->ColorCount)
	    ColorUnion->Colors 
		= (GifColorType *)realloc(Map, sizeof(GifColorType)*RoundUpTo);
    }

    ColorUnion->ColorCount = RoundUpTo;
    ColorUnion->BitsPerPixel = NewBitSize;

    return(ColorUnion);
}