Пример #1
0
/******************************************************************************
* Interpret the command line and scan the given GIF file.		      *
******************************************************************************/
int main(int argc, char **argv)
{
    int	i, j, Error, NumFiles, Width, Height;
    char **FileName = NULL;
    GifByteType *RedBuffer = NULL, *GreenBuffer = NULL, *BlueBuffer = NULL,
        *OutputBuffer = NULL;
    ColorMapObject *OutputColorMap = NULL;

    if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifQuietPrint,
		&ColorFlag, &ExpNumOfColors, &HelpFlag,
		&NumFiles, &FileName)) != FALSE ||
		(NumFiles > 1 && !HelpFlag)) {
	if (Error)
	    GAPrintErrMsg(Error);
	else if (NumFiles > 1)
	    GIF_MESSAGE("Error in command line parsing - one GIF file please.");
	GAPrintHowTo(CtrlStr);
	exit(EXIT_FAILURE);
    }

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

    ColorMapSize = 1 << ExpNumOfColors;

    if (NumFiles == 1) {
	LoadRle(*FileName,
		&RedBuffer, &GreenBuffer, &BlueBuffer, &Width, &Height);
    }
    else {
	LoadRle(NULL,
		&RedBuffer, &GreenBuffer, &BlueBuffer, &Width, &Height);
    }
    if ((OutputColorMap = MakeMapObject(ColorMapSize, NULL)) == NULL ||
	    (OutputBuffer = (GifByteType *) malloc(Width * Height *
					    sizeof(GifByteType))) == NULL)
	GIF_EXIT("Failed to allocate memory required, aborted.");

    if (QuantizeBuffer(Width, Height, &ColorMapSize,
		       RedBuffer, GreenBuffer, BlueBuffer,
		       OutputBuffer, OutputColorMap->Colors) == GIF_ERROR)
	QuitGifError(NULL);
    free((char *) RedBuffer);
    free((char *) GreenBuffer);
    free((char *) BlueBuffer);

    SaveGif(OutputBuffer, OutputColorMap, ExpNumOfColors, Width, Height);

    return 0;
}
Пример #2
0
int 
write_gif(const char *filename, int width, int height, char *rgb)
{
    int i;
    int colormap_size = 256;
    GifByteType *red, *green, *blue, *buffer, *ptr;
    GifFileType *outfile;
    ColorMapObject *colormap;

    red = malloc(width * height * sizeof(GifByteType));
    green = malloc(width * height * sizeof(GifByteType));
    blue = malloc(width * height * sizeof(GifByteType));
    buffer = malloc(width * height * sizeof(GifByteType));

    if (red == NULL || green == NULL || blue == NULL || buffer == NULL)
    {
        fprintf(stderr, "Can't allocate memory for GIF file.\n");
        return(0);
    }

    colormap = MakeMapObject(colormap_size, NULL);

    for (i = 0; i < width * height; i++)
    {
        red[i]   = (GifByteType) rgb[3*i  ];
        green[i] = (GifByteType) rgb[3*i+1];
        blue[i]  = (GifByteType) rgb[3*i+2];
    }
  
    if (QuantizeBuffer(width, height, &colormap_size, red, green, blue,   
                       buffer, colormap->Colors) == GIF_ERROR)
    {
        PrintGifError();
        return(0);
    }

    free(red);
    free(green);
    free(blue);

    outfile = EGifOpenFileName((char *) filename, FALSE);
    if (outfile == NULL)
    {
        PrintGifError();
        return(0);
    }

    if (EGifPutScreenDesc(outfile, width, height, colormap_size, 0, colormap)
        == GIF_ERROR)
    {
        PrintGifError();
        return(0);
    }

    if (EGifPutImageDesc(outfile, 0, 0, width, height, FALSE, NULL)
        == GIF_ERROR)
    {
        PrintGifError();
        return(0);
    }

    ptr = buffer;
    for (i = 0; i < height; i++)
    {
        if (EGifPutLine(outfile, ptr, width) == GIF_ERROR)
        {
            PrintGifError();
            return(0);
        }
        ptr += width;
    }

    EGifSpew(outfile);

    if (EGifCloseFile(outfile) == GIF_ERROR) 
        PrintGifError();

    free(buffer);

    return(1);
}
Пример #3
0
static int encode_gif_data(psx_image_header* header, psx_image_frame* frame, int idx, const ps_byte* buffer, size_t buffer_len, int* ret)
{
    int x, y;
    ColorMapObject *output_map = NULL;
    int map_size = 256;

    struct gif_image_ctx* ctx = (struct gif_image_ctx*)header->priv;

    if ((output_map = MakeMapObject(map_size, NULL)) == NULL) {
        if (ret) *ret = S_FAILURE;
        return -1;
    }

    for (y = 0; y < header->height; y++) {
        ps_byte* row = (ps_byte*)(buffer + header->pitch * y);
        for (x = 0; x < header->width; x++) {
            uint32_t rgba[4] = {0}; // r, g, b, a 
            gif_get_pixel_rgba_premultiply(header->format, row, x, rgba);
            ctx->red_buf[header->width * y + x] = rgba[0];
            ctx->green_buf[header->width * y + x] = rgba[1];
            ctx->blue_buf[header->width * y + x] = rgba[2];
        }
    }
    
    if (QuantizeBuffer(header->width, header->height, &map_size,
		ctx->red_buf, ctx->green_buf, ctx->blue_buf, ctx->output_buffer, output_map->Colors) == GIF_ERROR) {
        FreeMapObject(output_map);
        if (ret) *ret = S_FAILURE;
        return -1;
    }

    if (frame->duration > 0) {
        GifByteType extension[4];
#if GIFLIB_MAJOR >= 5
        GraphicsControlBlock gcb;
        gcb.DisposalMode = DISPOSAL_UNSPECIFIED; // FIXME: need specified ?
        gcb.UserInputFlag = false;
        gcb.DelayTime = frame->duration / 10;
        gcb.TransparentColor = -1; // FIXME: need specified ?

        EGifGCBToExtension(&gcb, extension);
#else
        int delay = frame->duration / 10;
        extension[0] = 0;
        extension[1] = LOBYTE(delay);
        extension[2] = HIBYTE(delay);
        extension[3] = (char)-1;
#endif
        if (EGifPutExtension(ctx->gif, GRAPHICS_EXT_FUNC_CODE, 4, extension) == GIF_ERROR) {
            FreeMapObject(output_map);
            if (ret) *ret = S_FAILURE;
            return -1;
        }
    }

    if (EGifPutImageDesc(ctx->gif, 0, 0, header->width, header->height, FALSE, output_map) == GIF_ERROR) {
        FreeMapObject(output_map);
        if (ret) *ret = S_FAILURE;
        return -1;
    }

    for (y = 0; y < header->height; y++) {
        EGifPutLine(ctx->gif, ctx->output_buffer + y * header->width, header->width);
    }
    FreeMapObject(output_map);
    return 0;
}
Пример #4
0
void *
gif_encode(Image *image, int single, int *size)
{
    int width = image->columns;
    int height = image->rows;
    int total = width * height;
    GifByteType output[total];
    GifByteType red[total];
    GifByteType green[total];
    GifByteType blue[total];

    // Quantize the images using IM/GM first, to reduce
    // their number of colors to 256.
    int count = GetImageListLength(image);
    QuantizeInfo info;
    GetQuantizeInfo(&info);
    info.dither = 1;
    info.number_colors = NCOLORS;
    QuantizeImage(&info, image);
    if (count > 1) {
#ifdef _MAGICK_USES_IM
        RemapImages(&info, image->next, image);
#else
        MapImages(image->next, image, 0);
#endif
    }

    if (!acquire_image_pixels(image, red, green, blue)) {
        return NULL;
    }

    Frame *frames = calloc(count, sizeof(*frames));

    ColorMapObject *palette = MakeMapObject(NCOLORS, NULL);
    int palette_size = NCOLORS;

    // Quantize again using giflib, since it yields a palette which produces
    // better compression, reducing the file size by 20%. Note that this second
    // quantization is very fast, because the image already has 256 colors, so
    // its effect on performance is negligible.
    if (QuantizeBuffer(width, height, &palette_size, red, green, blue, output, palette->Colors) == GIF_ERROR) {
        FreeMapObject(palette);
        gif_frames_free(frames, count);
        return NULL;
    }

    frames[0].data = malloc(total);
    memcpy(frames[0].data, output, total);
    frames[0].width = width;
    frames[0].height = height;
    frames[0].duration = image->delay;
    GifColorType *colors = palette->Colors;

    Image *cur = image->next;
    PixelCache *cache = pixel_cache_new();
    int ii;
    for (ii = 1; ii < count; ii++, cur = cur->next) {
        frames[ii].width = width;
        frames[ii].height = height;
        frames[ii].duration = cur->delay;
        GifPixelType *data = malloc(total);
        frames[ii].data = data;
        
        if (!aprox_image_pixels(cur, colors, palette_size, cache, data)) {
            FreeMapObject(palette);
            gif_frames_free(frames, count);
            pixel_cache_free(cache);
            return NULL;
        }
    }
    pixel_cache_free(cache);
    void *ret = gif_save(image, palette, frames, count, size);
    FreeMapObject(palette);
    gif_frames_free(frames, count);
    return ret;
}