static WebPMux* DuplicateMuxHeader(const WebPMux* const mux) { WebPMux* new_mux = WebPMuxNew(); WebPMuxAnimParams p; WebPMuxError err; int i; int ok = 1; if (new_mux == NULL) return NULL; err = WebPMuxGetAnimationParams(mux, &p); if (err == WEBP_MUX_OK) { err = WebPMuxSetAnimationParams(new_mux, &p); if (err != WEBP_MUX_OK) { ERROR_GOTO2("Error (%s) handling animation params.\n", ErrorString(err), End); } } else { /* it might not be an animation. Just keep moving. */ } for (i = 1; i <= 3; ++i) { WebPData metadata; err = WebPMuxGetChunk(mux, kFourccList[i], &metadata); if (err == WEBP_MUX_OK && metadata.size > 0) { err = WebPMuxSetChunk(new_mux, kFourccList[i], &metadata, 1); if (err != WEBP_MUX_OK) { ERROR_GOTO1("Error transferring metadata in DuplicateMux().", End); } } } End: if (!ok) { WebPMuxDelete(new_mux); new_mux = NULL; } return new_mux; }
/* Save an animation to disk */ gboolean save_animation(gint32 nLayers, gint32 *allLayers, FILE *outfile, WebPSaveParams *params, GError **error) { gboolean status = FALSE; gboolean innerStatus = TRUE; WebPAnimEncoderOptions enc_options; WebPAnimEncoder *enc = NULL; int frame_timestamp = 0; WebPData webp_data = {0}; WebPMux *mux; WebPMuxAnimParams anim_params = {0}; /* Prepare for encoding an animation */ WebPAnimEncoderOptionsInit(&enc_options); do { int i; gint32 drawable_ID = allLayers[0]; /* Create the encoder */ enc = WebPAnimEncoderNew(gimp_drawable_width(drawable_ID), gimp_drawable_height(drawable_ID), &enc_options); /* Encode each layer */ for (i = 0; i < nLayers; i++) { if ((innerStatus = save_layer(allLayers[i], NULL, NULL, TRUE, enc, frame_timestamp, params, error)) == FALSE) { break; } } /* Check to make sure each layer was encoded correctly */ if (innerStatus == FALSE) { break; } /* Add NULL frame */ WebPAnimEncoderAdd(enc, NULL, frame_timestamp, NULL); /* Initialize the WebP image structure */ WebPDataInit(&webp_data); /* Write the animation to the image */ if (!WebPAnimEncoderAssemble(enc, &webp_data)) { g_set_error(error, G_FILE_ERROR, 0, "Encoding error: '%s'", WebPAnimEncoderGetError(enc)); break; } /* Create a Mux */ mux = WebPMuxCreate(&webp_data, 1); /* Set animation parameters */ anim_params.loop_count = params->loop == TRUE ? 0 : 1; WebPMuxSetAnimationParams(mux, &anim_params); /* Assemble the image */ WebPMuxAssemble(mux, &webp_data); /* Write to disk */ if (fwrite(webp_data.bytes, webp_data.size, 1, outfile) != 1) { break; } /* Everything succeeded */ status = TRUE; } while(0); /* Free image data */ WebPDataClear(&webp_data); /* Free the animation encoder */ if (enc) { WebPAnimEncoderDelete(enc); } return status; }