コード例 #1
0
ファイル: gifdrv.c プロジェクト: carriercomm/VICE-Core
static int gifdrv_open_memmap(const char *filename, int x_size, int y_size, BYTE *palette)
{
    unsigned int i;
    GifColorType ColorMap256[256];
#if GIFLIB_MAJOR >= 5
    int ec;
#endif

    gifdrv_memmap_ext_filename = util_add_extension_const(filename, gif_drv.default_extension);

    gifdrv_memmap_fd = VICE_EGifOpenFileName(gifdrv_memmap_ext_filename, 0, &ec);

    if (gifdrv_memmap_fd == NULL) {
        lib_free(gifdrv_memmap_ext_filename);
        return -1;
    }

    gif_colors = VICE_MakeMapObject(256, ColorMap256);

    for (i = 0; i < 256; i++) {
        gif_colors->Colors[i].Blue = palette[(i * 3) + 2];
        gif_colors->Colors[i].Green = palette[(i * 3) + 1];
        gif_colors->Colors[i].Red = palette[i * 3];
    }

#if GIFLIB_MAJOR < 5
    EGifSetGifVersion("87a");
#endif

    if (EGifPutScreenDesc(gifdrv_memmap_fd, x_size, y_size, 8, 0, gif_colors) == GIF_ERROR ||
        EGifPutImageDesc(gifdrv_memmap_fd, 0, 0, x_size, y_size, 0, NULL) == GIF_ERROR) {
        VICE_EGifCloseFile(gifdrv_memmap_fd);
        VICE_FreeMapObject(gif_colors);
        lib_free(gifdrv_memmap_ext_filename);
        return -1;
    }

    return 0;
}
コード例 #2
0
bool toGif(QImage& img, QString& path)
{
    int errcode;

    if(QFile(path).exists()) // Remove old file
        QFile::remove(path);

    GifFileType* t = EGifOpenFileName(path.toLocal8Bit().data(),true, &errcode);
    if(!t){
        EGifCloseFile(t, &errcode);
        QTextStream(stdout)  << "Can't open\n";
        return false;
    }

    EGifSetGifVersion(t, true);

    GifColorType* colorArr = new GifColorType[256];
    ColorMapObject* cmo = GifMakeMapObject(256, colorArr);

    bool unfinished = false;
    QImage tarQImg(img.width(), img.height(), QImage::Format_Indexed8);
    QVector<QRgb> table;
    for(int y = 0; y < img.height(); y++){
        for(int x = 0; x < img.width(); x++){
            if(table.size() >= 256){
                unfinished = true;
                break;
            }
            QRgb pix;
            if(!table.contains(pix = img.pixel(x,y))){
                table.push_back(pix);
                tarQImg.setColor(tarQImg.colorCount(), pix);
            }
            tarQImg.setPixel(x,y,table.indexOf(pix));
        }
        if(table.size() >= 256){
            unfinished = true;
            break;
        }
    }

    if(unfinished){
        EGifCloseFile(t, &errcode);
        QTextStream(stdout)  << "Unfinished\n";
        return false;
    }


    for(int l = tarQImg.colorCount(); l < 256; l++){
        tarQImg.setColor(l,0);
    }

    if(tarQImg.colorTable().size() != 256){
        EGifCloseFile(t, &errcode);
        QTextStream(stdout)  << "A lot of colors\n";
        return false;
    }

    QVector<QRgb> clTab = tarQImg.colorTable();

    for(int i = 0; i < 255; i++){
        QRgb rgb = clTab[i];
        colorArr[i].Red = qRed(rgb);
        colorArr[i].Green = qGreen(rgb);
        colorArr[i].Blue = qBlue(rgb);
    }
    cmo->Colors = colorArr;

    errcode = EGifPutScreenDesc(t, img.width(), img.height(), 256, 0, cmo);
    if(errcode != GIF_OK){
        EGifCloseFile(t, &errcode);
        QTextStream(stdout)  << "EGifPutScreenDesc error 1\n";
        return false;
    }

    errcode = EGifPutImageDesc(t, 0, 0, img.width(), img.height(), false, 0);
    if(errcode != GIF_OK){
        EGifCloseFile(t, &errcode);
        QTextStream(stdout)  << "EGifPutImageDesc error 2\n";
        return false;
    }

    //gen byte array
    GifByteType* byteArr = tarQImg.bits();

    for(int h = 0; h < tarQImg.height(); h++){
        errcode = EGifPutLine(t, byteArr, tarQImg.width());
        if(errcode != GIF_OK){
            EGifCloseFile(t, &errcode);
            QTextStream(stdout)  << "EGifPutLine error 3\n";
            return false;
        }

        byteArr += tarQImg.width();
        byteArr += ((tarQImg.width() % 4)!=0 ? 4 - (tarQImg.width() % 4) : 0);
    }

    if(errcode != GIF_OK){
        QTextStream(stdout)  << "GIF error 4\n";
        return false;
    }
    EGifCloseFile(t, &errcode);

    return true;
}
コード例 #3
0
static int write_gif_info(const psx_image* image, image_writer_fn func, void* param,
                                                     float quality, psx_image_header* header)
{
    size_t buf_size;
#if GIFLIB_MAJOR >= 5
    int errorcode = 0;
#endif

    struct gif_image_ctx* ctx = (struct gif_image_ctx*)calloc(1, sizeof(struct gif_image_ctx));
    if (!ctx) {
        return -1; // out of memory.
    }

    ctx->writer = func;
    ctx->writer_param = param;

#if GIFLIB_MAJOR >= 5
    if ((ctx->gif = EGifOpen((void*)ctx, write_gif_from_memory, &errorcode)) == NULL) {
        free(ctx);
        return -1;
    }

    if (image->num_frames > 1) {
        EGifSetGifVersion(ctx->gif, true);
    }
#else
    if ((ctx->gif = EGifOpen((void*)ctx, write_gif_from_memory)) == NULL) {
        free(ctx);
        return -1;
    }

    if (image->num_frames > 1) {
        EGifSetGifVersion("89a");
    } else {
        EGifSetGifVersion("87a");
    }
#endif

    if (EGifPutScreenDesc(ctx->gif, image->width, image->height, 8, 0, NULL) == GIF_ERROR) {
        GIF_CLOSE_EFILE(ctx->gif);
        free(ctx);
        return -1;
    }

    if (image->num_frames > 1) { // add netscape2.0 application extension to an animation gif.
#if GIFLIB_MAJOR >= 5
        EGifPutExtensionLeader(ctx->gif, APPLICATION_EXT_FUNC_CODE);
        EGifPutExtensionBlock(ctx->gif, 11, "NETSCAPE2.0");
        EGifPutExtensionBlock(ctx->gif, 3, "\x01\x00\x00");
        EGifPutExtensionTrailer(ctx->gif);
#else
        EGifPutExtensionFirst(ctx->gif, APPLICATION_EXT_FUNC_CODE, 11, "NETSCAPE2.0");
        EGifPutExtensionLast(ctx->gif, APPLICATION_EXT_FUNC_CODE, 3, "\x01\x00\x00");
#endif
    }

    buf_size = image->width * image->height * sizeof(GifByteType);

    ctx->red_buf = (GifByteType*)malloc(buf_size);
    ctx->green_buf = (GifByteType*)malloc(buf_size);
    ctx->blue_buf = (GifByteType*)malloc(buf_size);
    ctx->output_buffer = (GifByteType*)malloc(buf_size);

    if (!ctx->red_buf || !ctx->green_buf || !ctx->blue_buf || !ctx->output_buffer) {
        GIF_CLOSE_EFILE(ctx->gif);

        if (ctx->red_buf) 
            free(ctx->red_buf);
        if (ctx->green_buf)
            free(ctx->green_buf);
        if (ctx->blue_buf)
            free(ctx->blue_buf);
        if (ctx->output_buffer)
            free(ctx->output_buffer);

        free(ctx);
        return -1;
    }

    header->priv = ctx;
    header->width = image->width;
    header->height = image->height;
    header->pitch = image->pitch;
    header->depth = get_depth(image->format);
    header->bpp = get_bpp(image->format);
    header->format = (int)image->format;
    header->alpha = 1;
    header->frames = (int)image->num_frames;
    return 0;
}
コード例 #4
0
bool Graphics::toGif(QImage &img, QString &path)
{
    int errcode;

    if(QFile(path).exists()) // Remove old file
        QFile::remove(path);

    GifFileType *t = EGifOpenFileName(path.toStdString().c_str(), true, &errcode);

    if(!t)
    {
        EGifCloseFile(t, &errcode);
        std::cout << "Can't open\n";
        return false;
    }

    EGifSetGifVersion(t, true);
    std::vector<GifColorType>colorArr;
    colorArr.resize(256);
    ColorMapObject *cmo = GifMakeMapObject(256, colorArr.data());
    bool unfinished = false;
    QImage tarQImg(img.width(), img.height(), QImage::Format_Indexed8);
    QVector<QRgb> table;

    for(int y = 0; y < img.height(); y++)
    {
        for(int x = 0; x < img.width(); x++)
        {
            if(table.size() >= 256)
            {
                unfinished = true;
                break;
            }

            QRgb pix;

            if(!table.contains(pix = img.pixel(x, y)))
            {
                table.push_back(pix);
                tarQImg.setColor(tarQImg.colorCount(), pix);
            }

            tarQImg.setPixel(x, y, static_cast<uint>(table.indexOf(pix)));
        }

        if(table.size() >= 256)
        {
            unfinished = true;
            break;
        }
    }

    if(unfinished)
    {
        GifFreeMapObject(cmo);
        EGifCloseFile(t, &errcode);
        std::cout << "Unfinished\n";
        return false;
    }

    for(int l = tarQImg.colorCount(); l < 256; l++)
        tarQImg.setColor(l, 0);

    if(tarQImg.colorTable().size() != 256)
    {
        GifFreeMapObject(cmo);
        EGifCloseFile(t, &errcode);
        std::cout << "A lot of colors\n";
        return false;
    }

    std::vector<QRgb> clTab = tarQImg.colorTable().toStdVector();

    for(size_t i = 0; i < 255; i++)
    {
        QRgb rgb = clTab[i];
        colorArr[i].Red     = static_cast<unsigned char>(qRed(rgb));
        colorArr[i].Green   = static_cast<unsigned char>(qGreen(rgb));
        colorArr[i].Blue    = static_cast<unsigned char>(qBlue(rgb));
    }

    cmo->Colors = colorArr.data();
    errcode = EGifPutScreenDesc(t, img.width(), img.height(), 256, 0, cmo);

    if(errcode != GIF_OK)
    {
        GifFreeMapObject(cmo);
        EGifCloseFile(t, &errcode);
        std::cout << "EGifPutScreenDesc error 1\n";
        return false;
    }

    errcode = EGifPutImageDesc(t, 0, 0, img.width(), img.height(), false, 0);

    if(errcode != GIF_OK)
    {
        GifFreeMapObject(cmo);
        EGifCloseFile(t, &errcode);
        std::cout << "EGifPutImageDesc error 2\n";
        return false;
    }

    //gen byte array
    GifByteType *byteArr = tarQImg.bits();

    for(int h = 0; h < tarQImg.height(); h++)
    {
        errcode = EGifPutLine(t, byteArr, tarQImg.width());

        if(errcode != GIF_OK)
        {
            GifFreeMapObject(cmo);
            EGifCloseFile(t, &errcode);
            std::cout << "EGifPutLine error 3\n";
            return false;
        }

        byteArr += tarQImg.width();
        byteArr += ((tarQImg.width() % 4) != 0 ? 4 - (tarQImg.width() % 4) : 0);
    }

    GifFreeMapObject(cmo);
    EGifCloseFile(t, &errcode);
    return true;
}
コード例 #5
0
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();
}