Example #1
0
/*
 * Allocate a color map of given size; initialize with contents of
 * ColorMap if that pointer is non-NULL.
 */
ColorMapObject *
GifMakeMapObject(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 << GifBitSize(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 = GifBitSize(ColorCount);
    Object->SortFlag = false;

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

    return (Object);
}
Example #2
0
ColorMapObject *QGifImagePrivate::colorTableToColorMapObject(QVector<QRgb> colorTable) const
{
    if (colorTable.isEmpty())
        return 0;

    ColorMapObject *cmap = (ColorMapObject *)malloc(sizeof(ColorMapObject));
    // num of colors must be a power of 2
    int numColors = 1 << GifBitSize(colorTable.size());
    cmap->ColorCount = numColors;
    //Maybe a bug of giflib, BitsPerPixel is used as size of the color table size.
    cmap->BitsPerPixel = GifBitSize(colorTable.size()); //Todo!
    cmap->SortFlag = false;

    GifColorType* colorValues = (GifColorType*)calloc(numColors, sizeof(GifColorType));
    for(int idx=0; idx < colorTable.size(); ++idx) {
        colorValues[idx].Red = qRed(colorTable[idx]);
        colorValues[idx].Green = qGreen(colorTable[idx]);
        colorValues[idx].Blue = qBlue(colorTable[idx]);
    }

    cmap->Colors = colorValues;

    return cmap;
}
Example #3
0
bool MCImageEncodeGIF(MCImageIndexedBitmap *p_indexed, IO_handle p_stream, uindex_t &r_bytes_written)
{
	bool t_success = true;

	int32_t t_transparent = -1;
	uindex_t t_palette_size;
	uindex_t t_depth;


	t_depth = GifBitSize(p_indexed->palette_size);
	// GIF requires palette size to be 2^depth
	t_palette_size = 1 << t_depth;

	int t_err = 0;
	GifFileType *t_gif = nil;
	ColorMapObject *t_colormap = nil;
	
	MCGIFWriteContext t_context;
	t_context.stream = p_stream;
	t_context.byte_count = 0;

	t_success = nil != (t_gif = EGifOpen(&t_context, gif_writeFunc, &t_err));

	if (t_success)
		t_success = nil != (t_colormap = GifMakeMapObject(t_palette_size, nil));

	if (t_success)
	{
		for (uindex_t i = 0; i < p_indexed->palette_size; i++)
		{
			t_colormap->Colors[i].Red = p_indexed->palette[i].red;
			t_colormap->Colors[i].Green = p_indexed->palette[i].green;
			t_colormap->Colors[i].Blue = p_indexed->palette[i].blue;
		}
		for (uindex_t i = p_indexed->palette_size; i < t_palette_size; i++)
		{
			t_colormap->Colors[i].Red =
				t_colormap->Colors[i].Green =
				t_colormap->Colors[i].Blue = 0;
		}

		if (MCImageIndexedBitmapHasTransparency(p_indexed))
		{
			t_transparent = p_indexed->transparent_index;
			t_colormap->Colors[t_transparent].Red =
				t_colormap->Colors[t_transparent].Green = 
				t_colormap->Colors[t_transparent].Blue = 0xFF;
		}

		t_success = GIF_OK == EGifPutScreenDesc(t_gif, p_indexed->width, p_indexed->height, t_depth, 0, t_colormap);
	}

	if (t_success)
	{
		if (t_transparent != -1)
		{
			GraphicsControlBlock t_gcb;
			MCMemoryClear(&t_gcb, sizeof(t_gcb));
			t_gcb.TransparentColor = t_transparent;

			GifByteType t_extension[4];

			uindex_t t_extension_size;
			t_extension_size = EGifGCBToExtension(&t_gcb, t_extension);

			// Should always be 4 bytes
			MCAssert(t_extension_size == sizeof(t_extension));

			t_success = GIF_OK == EGifPutExtension(t_gif, GRAPHICS_EXT_FUNC_CODE, sizeof(t_extension), t_extension);
		}
	}

	if (t_success)
		t_success = GIF_OK == EGifPutImageDesc(t_gif, 0, 0, p_indexed->width, p_indexed->height, false, nil);

	for (uindex_t y = 0; t_success && y < p_indexed->height; y++)
		t_success = GIF_OK == EGifPutLine(t_gif, (uint8_t*)p_indexed->data + y * p_indexed->stride, p_indexed->width);

	int t_error_code;
	if (GIF_ERROR == EGifCloseFile(t_gif, &t_error_code))
		t_success = false;

	GifFreeMapObject(t_colormap);

	if (t_success)
		r_bytes_written = t_context.byte_count;

	return t_success;
}
Example #4
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 the ColorUnion color map table./
*******************************************************************************/
ColorMapObject *
GifUnionColorMap(const ColorMapObject *ColorIn1,
              const ColorMapObject *ColorIn2,
              GifPixelType ColorTransIn2[])
{
    int i, j, CrntSlot, RoundUpTo, NewGifBitSize;
    ColorMapObject *ColorUnion;

    /*
     * We don't worry about duplicates within either color map; if
     * the caller wants to resolve those, he can perform unions
     * with an empty color map.
     */

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

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

    /*
     * Copy ColorIn1 to ColorUnion.
     */
    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 ColorUnion (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) {
        GifFreeMapObject(ColorUnion);
        return ((ColorMapObject *) NULL);
    }

    NewGifBitSize = GifBitSize(CrntSlot);
    RoundUpTo = (1 << NewGifBitSize);

    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) {
            GifColorType *new_map = (GifColorType *)realloc(Map,
                                 sizeof(GifColorType) * RoundUpTo);
            if( new_map == NULL ) {
                GifFreeMapObject(ColorUnion);
                return ((ColorMapObject *) NULL);
            }
            ColorUnion->Colors = new_map;
        }
    }

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

    return (ColorUnion);
}
Example #5
0
/******************************************************************************
 Modify the given colormap according to global variables setting.
******************************************************************************/
static ColorMapObject *ModifyColorMap(ColorMapObject *ColorMap)
{
    int i, Dummy, Red, Green, Blue;

    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.");
	    if (fscanf(ColorFile, "%3d %3d %3d %3d\n", &Dummy, &Red, &Green, &Blue) == 4) {
		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: */
	double 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;
	int Max = 0;

	/* 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.");
	    if (fscanf(TranslateFile, "%3d %3d\n", &Dummy, &tmp) == 2) {
		Translation[i] = tmp & 0xff;
		if (Translation[i] > Max)
		    Max = Translation[i];
	    }
	}

	if ((NewMap = GifMakeMapObject(1 << GifBitSize(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);
    }
}
Example #6
0
/******************************************************************************
 Interpret the command line and generate the given GIF file.
******************************************************************************/
int main(int argc, char **argv)
{
    int	i, j, l, GifNoisyPrint, ColorMapSize, ErrorCode;
    bool Error, BackGroundFlag = false, HelpFlag = false;
    char Line[LINE_LEN];
    GifRowType RasterBuffer[GIF_FONT_HEIGHT];
    ColorMapObject *ColorMap;
    GifFileType *GifFile;
    GifColorType	ScratchMap[256];
    int red, green, blue;

    if ((Error = GAGetArgs(argc, argv, CtrlStr,
			   &GifNoisyPrint,
			   &BackGroundFlag, &BackGround,
			   &HelpFlag)) != false) {
	GAPrintErrMsg(Error);
	GAPrintHowTo(CtrlStr);
	exit(EXIT_FAILURE);
    }

    if (HelpFlag) {
	(void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR);
	GAPrintHowTo(CtrlStr);
	exit(EXIT_SUCCESS);
    }

    /* Allocate the raster buffer for GIF_FONT_HEIGHT scan lines. */
    for (i = 0; i < GIF_FONT_HEIGHT; i++)
    {
	if ((RasterBuffer[i] = (GifRowType) malloc(sizeof(GifPixelType) *
							IMAGEWIDTH)) == NULL)
	    GIF_EXIT("Failed to allocate memory required, aborted.");
    }

    /* Open stdout for the output file: */
    if ((GifFile = EGifOpenFileHandle(1, &ErrorCode)) == NULL) {
	PrintGifError(ErrorCode);
	exit(EXIT_FAILURE);
    }

    /* Read the color map in ColorFile into this color map: */
    ColorMapSize = 0;
    while (fscanf(stdin,
		  "%*3d %3d %3d %3d\n",
		  &red, &green, &blue) == 3) {
	    ScratchMap[ColorMapSize].Red = red;
	    ScratchMap[ColorMapSize].Green = green;
	    ScratchMap[ColorMapSize].Blue = blue;
	    ColorMapSize++;
	}

    if ((ColorMap = GifMakeMapObject(1 << GifBitSize(ColorMapSize), ScratchMap)) == NULL)
	GIF_EXIT("Failed to allocate memory required, aborted.");

    if (EGifPutScreenDesc(GifFile,
			  IMAGEWIDTH, ColorMapSize * GIF_FONT_HEIGHT,
			  GifBitSize(ColorMapSize),
			  BackGround, ColorMap) == GIF_ERROR)
	QuitGifError(GifFile);

    /* Dump out the image descriptor: */
    if (EGifPutImageDesc(GifFile,
	0, 0, IMAGEWIDTH, ColorMapSize * GIF_FONT_HEIGHT, false, NULL) == GIF_ERROR)
	QuitGifError(GifFile);

    GifQprintf("\n%s: Image 1 at (%d, %d) [%dx%d]:     ",
		    PROGRAM_NAME, GifFile->Image.Left, GifFile->Image.Top,
		    GifFile->Image.Width, GifFile->Image.Height);

    for (i = l = 0; i < ColorMap->ColorCount; i++) {
	(void)snprintf(Line, sizeof(Line),
		       "Color %-3d: [%-3d, %-3d, %-3d] ", i,
		       ColorMap->Colors[i].Red,
		       ColorMap->Colors[i].Green,
		       ColorMap->Colors[i].Blue);
	GenRasterTextLine(RasterBuffer, Line, IMAGEWIDTH, i);
	for (j = 0; j < GIF_FONT_HEIGHT; j++) {
	    if (EGifPutLine(GifFile, RasterBuffer[j], IMAGEWIDTH) == GIF_ERROR)
		QuitGifError(GifFile);
	    GifQprintf("\b\b\b\b%-4d", l++);
	}
    }

    if (EGifCloseFile(GifFile, &ErrorCode) == GIF_ERROR)
    {
	PrintGifError(ErrorCode);
	if (GifFile != NULL) {
	    EGifCloseFile(GifFile, NULL);
	}
	exit(EXIT_FAILURE);
    }

    return 0;
}