/* * 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); }
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); }
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); }
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); }
/* * 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); }
/****************************************************************************** * 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); } }
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); } } }
/*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); }
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(); }
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); }