Exemplo n.º 1
0
Arquivo: gif.c Projeto: cortex/magick
INLINE void *
gif_save(const Image *image, const ColorMapObject *color_map, Frame *frames, int count, int frame_size, int *size)
{
    GifBuffer buf = {0,};
    int estimated = count * (image->columns * image->rows);
    buf.alloc = estimated;
    buf.data = malloc(estimated);
    GifFileType *gif_file = EGifOpen(&buf, gif_buffer_write, NULL);
    if (!gif_file) {
        return NULL;
    }
    if (EGifPutScreenDesc(gif_file, image->columns, image->rows, NCOLORS, 0, color_map) == GIF_ERROR) {
        EGifCloseFile(gif_file, NULL);
        return NULL;
    }
    if (GIF_BEGIN_APP_EXTENSION(gif_file) == GIF_ERROR) {
        EGifCloseFile(gif_file, NULL);
        return NULL;
    }
    unsigned char meta[] = {
        0x01, //  data sub-block index (always 1)
        0xFF, 0xFF // 65535 repetitions - unsigned
    };
    if (GIF_END_APP_EXTENSION(gif_file, meta) == GIF_ERROR) {
        EGifCloseFile(gif_file, NULL);
        return NULL;
    }
    int ii;
    unsigned char *p = (unsigned char*)frames;
    for (ii = 0; ii < count; ii++, p += frame_size) {
        Frame *frame = (Frame*)p;
        // GCE
        unsigned char gce[] = {
            0x08, // no transparency
            frame->duration % 256, // LSB of delay
            frame->duration / 256, // MSB of delay in millisecs
            0x00, // no transparent color
        };
        if (EGifPutExtension(gif_file, GRAPHICS_EXT_FUNC_CODE, sizeof(gce), gce) == GIF_ERROR) {
            EGifCloseFile(gif_file, NULL);
            return NULL;
        }
        if (EGifPutImageDesc(gif_file, 0, 0, frame->width, frame->height, 0, NULL) == GIF_ERROR) {
            EGifCloseFile(gif_file, NULL);
            return NULL;
        }
        int yy;
        GifPixelType *p = frame->data;
        for (yy = 0; yy < frame->height; yy++, p += frame->width) {
            if (EGifPutLine(gif_file, p, frame->width) == GIF_ERROR) {
                EGifCloseFile(gif_file, NULL);
                return NULL;
            }
        }
    } 
    EGifCloseFile(gif_file, NULL);
    *size = buf.size;
    return buf.data;
}
Exemplo n.º 2
0
/*!
 * \brief   pixWriteMemGif()
 *
 * \param[out]   pdata data of gif compressed image
 * \param[out]   psize size of returned data
 * \param[in]    pix
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) See comments in pixReadMemGif()
 *      (2) For Giflib version >= 5.1, this uses the EGifOpen() buffer
 *          interface.  No temp files are required.
 * </pre>
 */
l_int32
pixWriteMemGif(l_uint8  **pdata,
               size_t    *psize,
               PIX       *pix)
{
#if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5
int           giferr;
l_int32       result;
GifFileType  *gif;
L_BBUFFER     *buffer;
#else
char         *fname;
#endif  /* 5.1 and beyond */

    PROCNAME("pixWriteMemGif");

    if (!pdata)
        return ERROR_INT("&data not defined", procName, 1 );
    *pdata = NULL;
    if (!psize)
        return ERROR_INT("&size not defined", procName, 1 );
    *psize = 0;
    if (!pix)
        return ERROR_INT("&pix not defined", procName, 1 );

#if (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1) || GIFLIB_MAJOR > 5
    if((buffer = bbufferCreate(NULL, 0)) == NULL) {
        return ERROR_INT("failed to create buffer", procName, 1);
    }

    if ((gif = EGifOpen((void*)buffer, gifWriteFunc, NULL)) == NULL) {
        bbufferDestroy(&buffer);
        return ERROR_INT("failed to create GIF image handle", procName, 1);
    }

    result = pixToGif(pix, gif);
    EGifCloseFile(gif, &giferr);

    if(result == 0) {
        *pdata = bbufferDestroyAndSaveData(&buffer, psize);
    } else {
        bbufferDestroy(&buffer);
    }
    return result;
#else
    L_INFO("writing to a temp file, not directly to memory\n", procName);

        /* Write to a temp file */
    fname = l_makeTempFilename(NULL);
    pixWrite(fname, pix, IFF_GIF);

        /* Read back into memory */
    *pdata = l_binaryRead(fname, psize);
    lept_rmfile(fname);
    LEPT_FREE(fname);
    return 0;
#endif
}
Exemplo n.º 3
0
bool compress_custom(void* input_data, InputFunc input_func,
    void* output_data, OutputFunc output_func, int sample_size)
{
  GifFileType* input_gif = NULL;
  GifFileType* output_gif = NULL;
  int result = GIF_ERROR;

  // Check sample
  if (sample_size <= 0) {
    return false;
  }

  input_gif = DGifOpen(input_data, input_func, &error_code);
  if (input_gif == NULL) {
    LOGE(EMSG("Can't open input gif"));
    return false;
  }

  DGifSlurp(input_gif);

  if (input_gif->ImageCount == 0) {
    LOGE(EMSG("Gif frame count is 0"));
    DGifCloseFile(input_gif, &error_code);
    return false;
  }

  // Save gif
  output_gif = EGifOpen(output_data, output_func, &error_code);
  if (output_gif == NULL) {
    LOGE(EMSG("Can't open output gif"));
    DGifCloseFile(input_gif, &error_code);
    return false;
  }

  if (do_compress(input_gif, output_gif, sample_size)) {
    result = EGifSpew(output_gif);
  }

  // Free
  GifFreeExtensions(&output_gif->ExtensionBlockCount, &output_gif->ExtensionBlocks);
  if (output_gif->SavedImages) {
    GifFreeSavedImages(output_gif);
    output_gif->SavedImages = NULL;
  }

  // Close gif
  DGifCloseFile(input_gif, &error_code);

  return result == GIF_OK;
}
Exemplo n.º 4
0
/*!
 * \brief   pixWriteMemGif()
 *
 * \param[out]   pdata data of gif compressed image
 * \param[out]   psize size of returned data
 * \param[in]    pix
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) See comments in pixReadMemGif()
 * </pre>
 */
l_int32
pixWriteMemGif(l_uint8  **pdata,
               size_t    *psize,
               PIX       *pix)
{
int           giferr;
l_int32       result;
GifFileType  *gif;
L_BBUFFER    *buffer;

    PROCNAME("pixWriteMemGif");

        /* 5.1+ and not 5.1.2 */
#if (GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0))
    L_ERROR("Require giflib-5.1 or later\n", procName);
    return 1;
#endif  /* < 5.1 */
#if GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 1 && GIFLIB_RELEASE == 2  /* 5.1.2 */
    L_ERROR("Can't use giflib-5.1.2; suggest 5.1.3 or later\n", procName);
    return 1;
#endif  /* 5.1.2 */

    if (!pdata)
        return ERROR_INT("&data not defined", procName, 1 );
    *pdata = NULL;
    if (!psize)
        return ERROR_INT("&size not defined", procName, 1 );
    *psize = 0;
    if (!pix)
        return ERROR_INT("&pix not defined", procName, 1 );

    if ((buffer = bbufferCreate(NULL, 0)) == NULL)
        return ERROR_INT("failed to create buffer", procName, 1);

    if ((gif = EGifOpen((void*)buffer, gifWriteFunc, NULL)) == NULL) {
        bbufferDestroy(&buffer);
        return ERROR_INT("failed to create GIF image handle", procName, 1);
    }

    result = pixToGif(pix, gif);
    EGifCloseFile(gif, &giferr);

    if (result == 0) {
        *pdata = bbufferDestroyAndSaveData(&buffer, psize);
    } else {
        bbufferDestroy(&buffer);
    }
    return result;
}
Exemplo n.º 5
0
static void saveGif(ByteOutputStream &out, GifFileType *gf) {
  int error;

  GifFileType *gifOut = NULL;
  try {
    gifOut = EGifOpen(&out, writeGifStreamFunction, &error);
    if(gifOut == NULL) {
      THROWGIFERROR(error);
    }
    gifOut->SWidth           = gf->SWidth;
    gifOut->SHeight          = gf->SHeight;
    gifOut->SColorResolution = gf->SColorResolution;
    gifOut->SBackGroundColor = gf->SBackGroundColor;
    gifOut->SColorMap        = GifMakeMapObject(gf->SColorMap->ColorCount
                                               ,gf->SColorMap->Colors);

    for(int i = 0; i < gf->ImageCount; i++) {
      GifMakeSavedImage(gifOut, &gf->SavedImages[i]);
    }
    if(gifOut->ImageCount > 0) {
      SavedImage *image0 = gifOut->SavedImages;
      addNetscapeBlock(image0);
    }

    EGifSetGifVersion(gifOut, true);
    if(EGifSpew(gifOut) != GIF_OK) {
      THROWGIFERROR(gifOut->Error);
    }
  } catch(Exception e) {
    if(gifOut != NULL) {
      EGifCloseFile(gifOut, &error);
    }
    throw e;
  } catch(...) {
    if(gifOut != NULL) {
      EGifCloseFile(gifOut, &error);
    }
    throw;
  }
}
GDALDataset *
GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
               int bStrict, char ** papszOptions, 
               GDALProgressFunc pfnProgress, void * pProgressData )

{
    int  nBands = poSrcDS->GetRasterCount();
    int  nXSize = poSrcDS->GetRasterXSize();
    int  nYSize = poSrcDS->GetRasterYSize();
    int	 bInterlace = FALSE;

/* -------------------------------------------------------------------- */
/*      Check for interlaced option.                                    */
/* -------------------------------------------------------------------- */
    bInterlace = CSLFetchBoolean(papszOptions, "INTERLACING", FALSE);

/* -------------------------------------------------------------------- */
/*      Some some rudimentary checks                                    */
/* -------------------------------------------------------------------- */
    if( nBands != 1 )
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "GIF driver only supports one band images.\n" );

        return NULL;
    }

    if (nXSize > 65535 || nYSize > 65535)
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "GIF driver only supports datasets up to 65535x65535 size.\n" );

        return NULL;
    }

    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte 
        && bStrict )
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "GIF driver doesn't support data type %s. "
                  "Only eight bit bands supported.\n", 
                  GDALGetDataTypeName( 
                      poSrcDS->GetRasterBand(1)->GetRasterDataType()) );

        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Open the output file.                                           */
/* -------------------------------------------------------------------- */
    GifFileType *hGifFile;
    VSILFILE *fp;

    fp = VSIFOpenL( pszFilename, "wb" );
    if( fp == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "Failed to create %s:\n%s", 
                  pszFilename, VSIStrerror( errno ) );
        return NULL;
    }

#if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
    int nError;
    hGifFile = EGifOpen( fp, VSIGIFWriteFunc, &nError );
#else
    hGifFile = EGifOpen( fp, VSIGIFWriteFunc );
#endif
    if( hGifFile == NULL )
    {
        VSIFCloseL( fp );
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "EGifOpenFilename(%s) failed.  Does file already exist?",
                  pszFilename );

        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Prepare colortable.                                             */
/* -------------------------------------------------------------------- */
    GDALRasterBand	*poBand = poSrcDS->GetRasterBand(1);
    ColorMapObject	*psGifCT;
    int			iColor;

    if( poBand->GetColorTable() == NULL )
    {
        psGifCT = GifMakeMapObject( 256, NULL );
        for( iColor = 0; iColor < 256; iColor++ )
        {
            psGifCT->Colors[iColor].Red = (GifByteType) iColor;
            psGifCT->Colors[iColor].Green = (GifByteType) iColor;
            psGifCT->Colors[iColor].Blue = (GifByteType) iColor;
        }
    }
    else
    {
        GDALColorTable	*poCT = poBand->GetColorTable();
        int nFullCount = 1;

        while( nFullCount < poCT->GetColorEntryCount() )
            nFullCount = nFullCount * 2;

        psGifCT = GifMakeMapObject( nFullCount, NULL );
        for( iColor = 0; iColor < poCT->GetColorEntryCount(); iColor++ )
        {
            GDALColorEntry	sEntry;

            poCT->GetColorEntryAsRGB( iColor, &sEntry );
            psGifCT->Colors[iColor].Red = (GifByteType) sEntry.c1;
            psGifCT->Colors[iColor].Green = (GifByteType) sEntry.c2;
            psGifCT->Colors[iColor].Blue = (GifByteType) sEntry.c3;
        }
        for( ; iColor < nFullCount; iColor++ )
        {
            psGifCT->Colors[iColor].Red = 0;
            psGifCT->Colors[iColor].Green = 0;
            psGifCT->Colors[iColor].Blue = 0;
        }
    }

/* -------------------------------------------------------------------- */
/*      Setup parameters.                                               */
/* -------------------------------------------------------------------- */
    if (EGifPutScreenDesc(hGifFile, nXSize, nYSize, 
                          psGifCT->ColorCount, 255, psGifCT) == GIF_ERROR)
    {
        GifFreeMapObject(psGifCT);
        GDALPrintGifError(hGifFile, "Error writing gif file.");
        GIFAbstractDataset::myEGifCloseFile(hGifFile);
        VSIFCloseL( fp );
        return NULL;
    }
    
    GifFreeMapObject(psGifCT);
    psGifCT = NULL;

    /* Support for transparency */
    int bNoDataValue;
    double noDataValue = poBand->GetNoDataValue(&bNoDataValue);
    if (bNoDataValue && noDataValue >= 0 && noDataValue <= 255)
    {
        unsigned char extensionData[4];
        extensionData[0] = 1; /*  Transparent Color Flag */
        extensionData[1] = 0;
        extensionData[2] = 0;
        extensionData[3] = (unsigned char)noDataValue;
        EGifPutExtension(hGifFile, 0xf9, 4, extensionData);
    }

    if (EGifPutImageDesc(hGifFile, 0, 0, nXSize, nYSize, bInterlace, NULL) == GIF_ERROR )
    {
        GDALPrintGifError(hGifFile, "Error writing gif file.");
        GIFAbstractDataset::myEGifCloseFile(hGifFile);
        VSIFCloseL( fp );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Loop over image, copying image data.                            */
/* -------------------------------------------------------------------- */
    CPLErr      eErr;
    GDALPamDataset *poDS;
    GByte      *pabyScanline;

    pabyScanline = (GByte *) CPLMalloc( nXSize );

    if( !pfnProgress( 0.0, NULL, pProgressData ) )
        eErr = CE_Failure;

    if( !bInterlace )
    {
        for( int iLine = 0; iLine < nYSize; iLine++ )
        {
            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
                                     pabyScanline, nXSize, 1, GDT_Byte,
                                     nBands, nBands * nXSize );

            if( eErr != CE_None || EGifPutLine( hGifFile, pabyScanline, nXSize ) == GIF_ERROR )
            {
                CPLError( CE_Failure, CPLE_AppDefined, 
                          "Error writing gif file." );
                goto error;
            }

            if( !pfnProgress( (iLine + 1) * 1.0 / nYSize, NULL, pProgressData ) )
            {
                goto error;
            }

        }
    }
    else
    {
        int 	i, j;
        int nLinesRead = 0;
        int nLinesToRead = 0;
        for ( i = 0; i < 4; i++)
        {
            for (j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i]) 
            {
                nLinesToRead ++;
            }
        }

        /* Need to perform 4 passes on the images: */
        for ( i = 0; i < 4; i++)
        {
            for (j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i]) 
            {
                eErr= poBand->RasterIO( GF_Read, 0, j, nXSize, 1, 
                                        pabyScanline, nXSize, 1, GDT_Byte,
                                        1, nXSize );

                if (eErr != CE_None || EGifPutLine(hGifFile, pabyScanline, nXSize) == GIF_ERROR)
                {
                    CPLError( CE_Failure, CPLE_AppDefined, 
                            "Error writing gif file." );
                    goto error;
                }

                nLinesRead ++;
                if( !pfnProgress( nLinesRead * 1.0 / nYSize, NULL, pProgressData ) )
                {
                    goto error;
                }
            }
        }
    }

    CPLFree( pabyScanline );
    pabyScanline = NULL;

/* -------------------------------------------------------------------- */
/*      cleanup                                                         */
/* -------------------------------------------------------------------- */
    if (GIFAbstractDataset::myEGifCloseFile(hGifFile) == GIF_ERROR)
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "EGifCloseFile() failed.\n" );
        hGifFile = NULL;
        goto error;
    }
    hGifFile = NULL;

    VSIFCloseL( fp );
    fp = NULL;

/* -------------------------------------------------------------------- */
/*      Do we need a world file?                                          */
/* -------------------------------------------------------------------- */
    if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
    {
    	double      adfGeoTransform[6];
	
	if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
            GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
    }

/* -------------------------------------------------------------------- */
/*      Re-open dataset, and copy any auxilary pam information.         */
/* -------------------------------------------------------------------- */

    /* If outputing to stdout, we can't reopen it, so we'll return */
    /* a fake dataset to make the caller happy */
    CPLPushErrorHandler(CPLQuietErrorHandler);
    poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly);
    CPLPopErrorHandler();
    if (poDS)
    {
        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
        return poDS;
    }
    else
    {
        CPLErrorReset();

        GIFDataset* poGIF_DS = new GIFDataset();
        poGIF_DS->nRasterXSize = nXSize;
        poGIF_DS->nRasterYSize = nYSize;
        for(int i=0;i<nBands;i++)
            poGIF_DS->SetBand( i+1, new GIFRasterBand( poGIF_DS, i+1, NULL, 0 ) );
        return poGIF_DS;
    }

error:
    if (hGifFile)
        GIFAbstractDataset::myEGifCloseFile(hGifFile);
    if (fp)
        VSIFCloseL( fp );
    if (pabyScanline)
        CPLFree( pabyScanline );
    return NULL;
}
Exemplo n.º 7
0
unsigned char *
gifconv_lossless2gif(void *image_data,
                     unsigned short width, unsigned short height,
                     void *index_data,
                     unsigned short index_data_count,
                     int tag_no, int format,
                     unsigned long *length) {
    GifFileType *GifFile = NULL;
    GifColorType *Colors = NULL;
    int ColorCount;
    my_gif_buffer gif_buff;
    gif_uint_32 gif_width = 0, gif_height = 0;
    int bpp;
    gif_bytep gif_image_data = NULL;
    gif_uint_32 x, y;
    gif_colorp gif_palette = NULL;
//    int trans_index = -1;
    int i;
    if (format != 3) {
        fprintf(stderr, "jpegconv_lossless2gif: format=%d not implemented yes.\n", format);
        return NULL;
    }
    bpp = 8;
    gif_width = width;
    gif_height = height;
    ColorCount = 256;
    Colors = calloc(sizeof(GifColorType), ColorCount);

    gif_buff.data = NULL;
    gif_buff.data_len = 0;
    gif_buff.data_offset = 0;
#if GIFLIB_MAJOR >= 5
    GifFile = EGifOpen(& gif_buff, gif_data_write_func, NULL);
#else
    GifFile = EGifOpen(& gif_buff, gif_data_write_func);
#endif
    if (GifFile == NULL) {
        fprintf(stderr, "gifconv_lossless2gif: can't open GIFFile\n");
        return NULL;
    }
    GifFile->SWidth  = gif_width;
    GifFile->SHeight = gif_height;
    GifFile->SColorResolution = bpp;

    gif_palette = (gif_colorp) malloc(sizeof(gif_color)*index_data_count);

    if (tag_no == 20) {
        swf_rgb_t *rgb_list  = index_data;
        for (i=0 ; i < index_data_count ; i++) {
            Colors[i].Red   = rgb_list[i].red;
            Colors[i].Green = rgb_list[i].green;
            Colors[i].Blue  = rgb_list[i].blue;
        }
    } else {
        swf_rgba_t *rgba_list  = index_data;
        for (i=0 ; i < index_data_count ; i++) {
//            if (rgba_list[i].alpha)
            Colors[i].Red   = rgba_list[i].red;
            Colors[i].Green = rgba_list[i].green;
            Colors[i].Blue  = rgba_list[i].blue;
//                gif_palette[i].alpha = ;
        }
    }
    GifFile->SBackGroundColor = 0; // XXX
    gif_image_data = (gif_bytep) calloc(sizeof(unsigned char), gif_width * gif_height);
    i = 0;
    for (y=0 ; y < gif_height ; y++) {
        for (x=0 ; x < gif_width ; x++) {
            unsigned char *data = image_data;
            gif_image_data[i] = data[x + y*((gif_width +3) & -4)];
            i++;
        }
    }

    GifFile->SavedImages[0].RasterBits = gif_image_data;
#if GIFLIB_MAJOR >= 5
    GifFile->SColorMap = GifMakeMapObject(ColorCount, Colors);
#else
    GifFile->SColorMap = MakeMapObject(ColorCount, Colors);
#endif
    EGifSpew(GifFile); // XXX

    free(gif_image_data);

    if (GifFile) {
#if GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1 || GIFLIB_MAJOR > 5
        EGifCloseFile(GifFile, NULL);
#else
        EGifCloseFile(GifFile);
#endif
    }
    *length = gif_buff.data_offset;
    return gif_buff.data;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
0
bool CxImageGIF::Encode(CxFile * fp)
{
	if (EncodeSafeCheck(fp)) return false;

	GifFileType *GifFile = NULL;
	ColorMapObject *OutputColorMap = NULL;
	int i, ColorMapSize;

	if(head.biBitCount != 8)
	{
		if(head.biBitCount < 8)IncreaseBpp(8);
		else DecreaseBpp(8, true);
	}

	try
	{
		GifFile = EGifOpen(fp, writeCxFile);

		ColorMapSize = head.biClrUsed;
		OutputColorMap = MakeMapObject(ColorMapSize, NULL);

		RGBQUAD* pPal = GetPalette();
		for(i=0; i<ColorMapSize; ++i) 
		{
			OutputColorMap->Colors[i].Red = pPal[i].rgbRed;
			OutputColorMap->Colors[i].Green = pPal[i].rgbGreen;
			OutputColorMap->Colors[i].Blue = pPal[i].rgbBlue;
		}

		EGifPutScreenDesc(GifFile, head.biWidth, head.biHeight, OutputColorMap->ColorCount, info.nBkgndIndex== -1 ? 0 : info.nBkgndIndex, OutputColorMap);

		FreeMapObject(OutputColorMap);
		OutputColorMap = NULL;

		if(info.nBkgndIndex != -1)
		{
			unsigned char ExtStr[4] = { 1, 0, 0, info.nBkgndIndex };
			EGifPutExtension(GifFile, GRAPHICS_EXT_FUNC_CODE, 4, ExtStr);
		}

		EGifPutImageDesc(GifFile, 0, 0, head.biWidth, head.biHeight, FALSE, NULL);

		for (i = 0; i < head.biHeight; i++)
			EGifPutLine(GifFile, GetBits(head.biHeight - i - 1), head.biWidth);

		EGifCloseFile(GifFile);
		GifFile = NULL;
	} catch (int errid) {
		strncpy(info.szLastError,GifGetErrorMessage(errid),255);
		if(OutputColorMap)
		{
			FreeMapObject(OutputColorMap);
			OutputColorMap = NULL;
		}
		if(GifFile)
		{
			EGifCloseFile(GifFile);
			GifFile = NULL;
		}
		return false;
	} catch (char *message) {
		strncpy(info.szLastError,message,255);
		if(OutputColorMap)
		{
			FreeMapObject(OutputColorMap);
			OutputColorMap = NULL;
		}
		if(GifFile)
		{
			EGifCloseFile(GifFile);
			GifFile = NULL;
		}
		return false;
	}

	return true;
}
Exemplo n.º 11
0
void EncodeToGifBufferWorker::Execute () {
    GifByteType
        * redBuff = (GifByteType *) _pixbuf,
        * greenBuff = (GifByteType *) _pixbuf + _width * _height,
        * blueBuff = (GifByteType *) _pixbuf + 2 * _width * _height,
        * alphaBuff = (GifByteType *) _pixbuf + 3 * _width * _height,
        * gifimgbuf = (GifByteType *) malloc(_width * _height * sizeof(GifByteType)); // the indexed image
    ColorMapObject *cmap;
    SavedImage * simg;

    if (NULL == gifimgbuf){
        SetErrorMessage("Out of memory");
        return;
    }

    cmap = GifMakeMapObject(_cmapSize, NULL);

    if (NULL == cmap){
        free(gifimgbuf);
        SetErrorMessage("Out of memory");
        return;
    }

    if (GIF_ERROR == GifQuantizeBuffer(
                _width, _height, &_colors,
               redBuff, greenBuff, blueBuff,
               gifimgbuf, cmap->Colors
        )){
        free(gifimgbuf);
        GifFreeMapObject(cmap);
        SetErrorMessage("Unable to quantize image");
        return;
    }

    int errcode;
    gifWriteCbData buffinf = {NULL, 0};
    GifFileType * gif;

    gif = EGifOpen((void *) &buffinf, gifWriteCB, &errcode);

    if (NULL == gif){
        free(gifimgbuf);
        GifFreeMapObject(cmap);
        SetErrorMessage(GifErrorString(errcode));
        return;
    }

    gif->SWidth = _width;
    gif->SHeight = _height;
    gif->SColorResolution = _cmapSize;

    simg = GifMakeSavedImage(gif, NULL);

    if (NULL == simg){
        free(gifimgbuf);
        EGifCloseFile(gif, &errcode); // will also free cmap
        SetErrorMessage("Out of memory");
        return;
    }

    simg->ImageDesc.Left = 0;
    simg->ImageDesc.Top = 0;
    simg->ImageDesc.Width = _width;
    simg->ImageDesc.Height = _height;
    simg->ImageDesc.Interlace = _interlaced;
    simg->ImageDesc.ColorMap = cmap;
    simg->RasterBits = gifimgbuf;

    // for some reason giflib sometimes creates an invalid file if the global
    // color table is not set as well
    gif->SColorMap = cmap;

    if (_trans){
        ExtensionBlock ext;
        // 1. assign transparent color index in color table
        GraphicsControlBlock gcb = {0, false, 0, _colors++};
        // 2. replace transparent pixels above threshold with this color
        remapTransparentPixels(gifimgbuf, alphaBuff, _width, _height, gcb.TransparentColor, _threshold);
        // 3. create a control block
        size_t extlen = EGifGCBToExtension(&gcb, (GifByteType *) &ext);
        if (GIF_ERROR == GifAddExtensionBlock(
                &(simg->ExtensionBlockCount),
                &(simg->ExtensionBlocks),
                GRAPHICS_EXT_FUNC_CODE,
                extlen,
                (unsigned char *) &ext)
            ) {
            EGifCloseFile(gif, &errcode);
            SetErrorMessage("Out of memory");
            return;
        }
    }


    if (GIF_ERROR == EGifSpew(gif)){
        EGifCloseFile(gif, &errcode);
        SetErrorMessage(GifErrorString(gif->Error));
        return;
    }

    _gifbuf = (char *) buffinf.buff;
    _gifbufsize = buffinf.buffsize;

    return;
}
Exemplo n.º 12
0
void
AnimatedGifEncoder::new_frame(unsigned char *data, int delay)
{
    if (!gif_file) {
       if (write_func != NULL) {
            int nError;
            gif_file = EGifOpen(write_user_data, write_func, &nError);
            if (!gif_file) throw "EGifOpen in AnimatedGifEncoder::new_frame failed";
        } else if (file_name.empty()) { // memory writer
            int nError;
            gif_file = EGifOpen(&gif, gif_writer, &nError);
            if (!gif_file) throw "EGifOpen in AnimatedGifEncoder::new_frame failed";
        } else {
            int nError;
            gif_file = EGifOpenFileName(file_name.c_str(), FALSE, &nError);
            if (!gif_file) throw "EGifOpenFileName in AnimatedGifEncoder::new_frame failed";
        }
        output_color_map = GifMakeMapObject(color_map_size, ext_web_safe_palette);
        if (!output_color_map) throw "MakeMapObject in AnimatedGifEncoder::new_frame failed";

        gif_buf = (GifByteType *)malloc(sizeof(GifByteType)*width*height);
        if (!gif_buf) throw "malloc in AnimatedGifEncoder::new_frame failed";
    }

    RGBator rgb(data, width, height, buf_type);

    if (web_safe_quantize(width, height, rgb.red, rgb.green, rgb.blue, gif_buf) == GIF_ERROR)
        throw "web_safe_quantize in AnimatedGifEncoder::new_frame failed";

    /*
    if (QuantizeBuffer(width, height, &color_map_size,
        rgb.red, rgb.green, rgb.blue,
        gif_buf, output_color_map->Colors) == GIF_ERROR)
    {
        throw "QuantizeBuffer in AnimatedGifEncoder::new_frame failed";
    }
    */

    if (!headers_set) {
        if (EGifPutScreenDesc(gif_file, width, height,
            color_map_size, 0, output_color_map) == GIF_ERROR)
        {
            throw "EGifPutScreenDesc in AnimatedGifEncoder::new_frame failed";
        }
        char netscape_extension[] = "NETSCAPE2.0";
        EGifPutExtension(gif_file, APPLICATION_EXT_FUNC_CODE, 11, netscape_extension);
        char animation_extension[] = { 1, 1, 0 }; // repeat one time
        EGifPutExtension(gif_file, APPLICATION_EXT_FUNC_CODE, 3, animation_extension);
        headers_set = true;
    }

    char frame_flags = 1 << 2;
    char transp_color_idx = 0;
    if (transparency_color.color_present) {
        int i = find_color_index(output_color_map, color_map_size, transparency_color);
        if (i>=0) {
            frame_flags |= 1;
            transp_color_idx = i;
        }
    }

    char extension[] = {
        frame_flags,
        delay%256, delay/256,
        transp_color_idx
    };
    EGifPutExtension(gif_file, GRAPHICS_EXT_FUNC_CODE, 4, extension);

    if (EGifPutImageDesc(gif_file, 0, 0, width, height, FALSE, NULL) == GIF_ERROR) {
        throw "EGifPutImageDesc in AnimatedGifEncoder::new_frame failed";
    }

    GifByteType *gif_bufp = gif_buf;
    for (int i = 0; i < height; i++) {
        if (EGifPutLine(gif_file, gif_bufp, width) == GIF_ERROR) {
            throw "EGifPutLine in AnimatedGifEncoder::new_frame failed";
        }
        gif_bufp += width;
    }
}
Exemplo n.º 13
0
void
GifEncoder::encode()
{
    RGBator rgb(data, width, height, buf_type);

    int color_map_size = 256;
    ColorMapObject *output_color_map = GifMakeMapObject(256, ext_web_safe_palette);
    LOKI_ON_BLOCK_EXIT(GifFreeMapObject, output_color_map);
    if (!output_color_map)
        throw "MakeMapObject in GifEncoder::encode failed";

    GifByteType *gif_buf = (GifByteType *)malloc(sizeof(GifByteType)*width*height);
    LOKI_ON_BLOCK_EXIT(free, gif_buf);
    if (!gif_buf)
        throw "malloc in GifEncoder::encode failed";

    if (web_safe_quantize(width, height, rgb.red, rgb.green, rgb.blue, gif_buf) == GIF_ERROR)
        throw "web_safe_quantize in GifEncoder::encode failed";

    /*
    if (QuantizeBuffer(width, height, &color_map_size,
        rgb.red, rgb.green, rgb.blue,
        gif_buf, output_color_map->Colors) == GIF_ERROR)
    {
        throw "QuantizeBuffer in GifEncoder::encode failed";
    }
    */

    int nError;
    GifFileType *gif_file = EGifOpen(&gif, gif_writer, &nError);
    LOKI_ON_BLOCK_EXIT(EGifCloseFile, gif_file);
    if (!gif_file)
        throw "EGifOpen in GifEncoder::encode failed";

    if (EGifPutScreenDesc(gif_file, width, height,
        color_map_size, 0, output_color_map) == GIF_ERROR)
    {
        throw "EGifPutScreenDesc in GifEncoder::encode failed";
    }

    if (transparency_color.color_present) {
        int i = find_color_index(output_color_map, color_map_size, transparency_color);
        if (i) {
            char extension[] = {
                1, // enable transparency
                0, 0, // no time delay
                i // transparency color index
            };
            EGifPutExtension(gif_file, GRAPHICS_EXT_FUNC_CODE, 4, extension);
        }
    }

    if (EGifPutImageDesc(gif_file, 0, 0, width, height, FALSE, NULL) == GIF_ERROR) {
        throw "EGifPutImageDesc in GifEncoder::encode failed";
    }

    GifByteType *gif_bufp = gif_buf;
    for (int i = 0; i < height; i++) {
        if (EGifPutLine(gif_file, gif_bufp, width) == GIF_ERROR)
            throw "EGifPutLine in GifEncoder::encode failed";
        gif_bufp += width;
    }
}