示例#1
0
static void * DLL_CALLCONV
Open(FreeImageIO *io, fi_handle handle, BOOL read) {
	WebPMux *mux = NULL;
	int copy_data = 1;	// 1 : copy data into the mux, 0 : keep a link to local data

	if(read) {
		// create the MUX object from the input stream
		WebPData bitstream;
		// read the input file and put it in memory
		if(!ReadFileToWebPData(io, handle, &bitstream)) {
			return NULL;
		}
		// create the MUX object
		mux = WebPMuxCreate(&bitstream, copy_data);
		// no longer needed since copy_data == 1
		free((void*)bitstream.bytes);
		if(mux == NULL) {
			FreeImage_OutputMessageProc(s_format_id, "Failed to create mux object from file");
			return NULL;
		}
	} else {
		// creates an empty mux object
		mux = WebPMuxNew();
		if(mux == NULL) {
			FreeImage_OutputMessageProc(s_format_id, "Failed to create empty mux object");
			return NULL;
		}
	}
	
	return mux;
}
示例#2
0
static int CreateMux(const char* const filename, WebPMux** mux) {
  WebPData bitstream;
  assert(mux != NULL);
  if (!ReadFileToWebPData(filename, &bitstream)) return 0;
  *mux = WebPMuxCreate(&bitstream, 1);
  free((void*)bitstream.bytes);
  if (*mux != NULL) return 1;
  fprintf(stderr, "Failed to create mux object from file %s.\n", filename);
  return 0;
}
示例#3
0
文件: webp.c 项目: beforewind/webp
uint8_t* webpDelXMP(const uint8_t* data, size_t data_size, size_t* new_data_size) {
	WebPData image = {data, data_size};
	WebPData output_data = {NULL, 0};
	WebPMux* mux = WebPMuxCreate(&image, 0);
	if(WebPMuxDeleteChunk(mux, "XMP ") == WEBP_MUX_OK) {
		WebPMuxAssemble(mux, &output_data);
	}
	WebPMuxDelete(mux);
	*new_data_size = output_data.size;
	return (uint8_t*)(output_data.bytes);
}
示例#4
0
文件: webp.c 项目: beforewind/webp
uint8_t* webpSetXMP(
	const uint8_t* data, size_t data_size,
	const char* metadata, size_t metadata_size,
	size_t* new_data_size
) {
	WebPData image = {data, data_size};
	WebPData profile = {metadata, metadata_size};
	WebPData output_data = {NULL, 0};
	WebPMux* mux = WebPMuxCreate(&image, 0);
	if(WebPMuxSetChunk(mux, "XMP ", &profile, 0) == WEBP_MUX_OK) {
		WebPMuxAssemble(mux, &output_data);
	}
	WebPMuxDelete(mux);
	*new_data_size = output_data.size;
	return (uint8_t*)(output_data.bytes);
}
示例#5
0
// Outputs image data given a bitstream. The bitstream can either be a
// single-image WebP file or raw VP8/VP8L data.
// Also outputs 'is_lossless' to be true if the given bitstream is lossless.
static WebPMuxError GetImageData(const WebPData* const bitstream,
                                 WebPData* const image, WebPData* const alpha,
                                 int* const is_lossless) {
  WebPDataInit(alpha);  // Default: no alpha.
  if (bitstream->size < TAG_SIZE ||
      memcmp(bitstream->bytes, "RIFF", TAG_SIZE)) {
    // It is NOT webp file data. Return input data as is.
    *image = *bitstream;
  } else {
    // It is webp file data. Extract image data from it.
    const WebPMuxImage* wpi;
    WebPMux* const mux = WebPMuxCreate(bitstream, 0);
    if (mux == NULL) return WEBP_MUX_BAD_DATA;
    wpi = mux->images_;
    assert(wpi != NULL && wpi->img_ != NULL);
    *image = wpi->img_->data_;
    if (wpi->alpha_ != NULL) {
      *alpha = wpi->alpha_->data_;
    }
    WebPMuxDelete(mux);
  }
  *is_lossless = VP8LCheckSignature(image->bytes, image->size);
  return WEBP_MUX_OK;
}
示例#6
0
static int
read_header( Read *read, VipsImage *out )
{
	vips_image_init_fields( out,
		read->width, read->height,
		read->config.input.has_alpha ? 4 : 3,
		VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
		VIPS_INTERPRETATION_sRGB,
		1.0, 1.0 );

	vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );

#ifdef HAVE_LIBWEBPMUX
{
	WebPData bitstream;
	WebPMux *mux;
	int i;

	/* We have to parse the whole file again to get the metadata out.
	 *
	 * Don't make parse failure an error. We don't want to refuse to read
	 * any pixels because of some malformed metadata.
	 */
	bitstream.bytes = read->data;
	bitstream.size = read->length;
	if( !(mux = WebPMuxCreate( &bitstream, 0 )) ) {
		vips_warn( "webp", "%s", _( "unable to read image metadata" ) ); 
		return( 0 ); 
	}

	for( i = 0; i < vips__n_webp_names; i++ ) { 
		const char *vips = vips__webp_names[i].vips;
		const char *webp = vips__webp_names[i].webp;

		WebPData data;

		if( WebPMuxGetChunk( mux, webp, &data ) == WEBP_MUX_OK ) { 
			void *blob;

			if( !(blob = vips_malloc( NULL, data.size )) ) {
				WebPMuxDelete( mux ); 
				return( -1 ); 
			}

			memcpy( blob, data.bytes, data.size );
			vips_image_set_blob( out, vips, 
				(VipsCallbackFn) vips_free, blob, data.size );
		}
	}

	WebPMuxDelete( mux ); 

	/* We may have read some exif ... parse into the header.
	 */
	if( vips__exif_parse( out ) )
		return( -1 ); 
}
#endif /*HAVE_LIBWEBPMUX*/

	return( 0 );
}
示例#7
0
PyObject* WebPDecode_wrapper(PyObject* self, PyObject* args)
{
    PyBytesObject *webp_string;
    uint8_t *webp;
    Py_ssize_t size;
    PyObject *ret, *bytes, *pymode, *icc_profile = Py_None, *exif = Py_None;
    WebPDecoderConfig config;
    VP8StatusCode vp8_status_code = VP8_STATUS_OK;
    char* mode = "RGB";

    if (!PyArg_ParseTuple(args, "S", &webp_string)) {
        Py_RETURN_NONE;
    }

    if (!WebPInitDecoderConfig(&config)) {
        Py_RETURN_NONE;
    }

    PyBytes_AsStringAndSize((PyObject *) webp_string, (char**)&webp, &size);

    vp8_status_code = WebPGetFeatures(webp, size, &config.input);
    if (vp8_status_code == VP8_STATUS_OK) {
        // If we don't set it, we don't get alpha.
        // Initialized to MODE_RGB
        if (config.input.has_alpha) {
            config.output.colorspace = MODE_RGBA;
            mode = "RGBA";
        }

#ifndef HAVE_WEBPMUX
        vp8_status_code = WebPDecode(webp, size, &config);
#else
       {
        int copy_data = 0;
        WebPData data = { webp, size };
        WebPMuxFrameInfo image;
        WebPData icc_profile_data = {0};
        WebPData exif_data = {0};

        WebPMux* mux = WebPMuxCreate(&data, copy_data);
        WebPMuxGetFrame(mux, 1, &image);
        webp = (uint8_t*)image.bitstream.bytes;
        size = image.bitstream.size;

        vp8_status_code = WebPDecode(webp, size, &config);

        WebPMuxGetChunk(mux, "ICCP", &icc_profile_data);
        if (icc_profile_data.size > 0) {
            icc_profile = PyBytes_FromStringAndSize((const char*)icc_profile_data.bytes, icc_profile_data.size);
        }

        WebPMuxGetChunk(mux, "EXIF", &exif_data);
        if (exif_data.size > 0) {
            exif = PyBytes_FromStringAndSize((const char*)exif_data.bytes, exif_data.size);
        }

        WebPMuxDelete(mux);
        }
#endif
    }

    if (vp8_status_code != VP8_STATUS_OK) {
        WebPFreeDecBuffer(&config.output);
        Py_RETURN_NONE;
    }

    if (config.output.colorspace < MODE_YUV) {
        bytes = PyBytes_FromStringAndSize((char *)config.output.u.RGBA.rgba,
                                          config.output.u.RGBA.size);
    } else {
        // Skipping YUV for now. Need Test Images.
        // UNDONE -- unclear if we'll ever get here if we set mode_rgb*
        bytes = PyBytes_FromStringAndSize((char *)config.output.u.YUVA.y,
                                          config.output.u.YUVA.y_size);
    }

#if PY_VERSION_HEX >= 0x03000000
    pymode = PyUnicode_FromString(mode);
#else
    pymode = PyString_FromString(mode);
#endif
    ret = Py_BuildValue("SiiSSS", bytes, config.output.width,
                        config.output.height, pymode, icc_profile, exif);
    WebPFreeDecBuffer(&config.output);
    return ret;
}
示例#8
0
gboolean load_image(const gchar *filename,
                    gint32      *image_ID,
                    GError     **error)
{
    gboolean              status      = FALSE;
    gchar                *indata      = NULL;
    gsize                 indatalen;
    gint                  width;
    gint                  height;
    WebPMux              *mux         = NULL;
    WebPData              wp_data;
    uint32_t              flags;
    uint8_t              *outdata     = NULL;

#ifdef GIMP_2_9
    /* Initialize GEGL */
    gegl_init(NULL, NULL);
#endif

    do {

        /* Attempt to read the file contents from disk */
        if (g_file_get_contents(filename,
                                &indata,
                                &indatalen,
                                error) == FALSE) {
            break;
        }

        /* Validate WebP data, grabbing the width and height */
        if (!WebPGetInfo(indata, indatalen, &width, &height)) {
            break;
        }

        /* Create a WebPMux from the contents of the file */
        wp_data.bytes = (uint8_t*)indata;
        wp_data.size = indatalen;

        mux = WebPMuxCreate(&wp_data, 1);
        if (mux == NULL) {
            break;
        }

        /* Retrieve the features present */
        if (WebPMuxGetFeatures(mux, &flags) != WEBP_MUX_OK) {
            break;
        }

        /* TODO: decode the image in "chunks" or "tiles" */
        /* TODO: check if an alpha channel is present */

        /* Create the new image and associated layer */
        *image_ID = gimp_image_new(width, height, GIMP_RGB);

#ifdef WEBP_0_5
        if (flags & ANIMATION_FLAG) {
            int frames, i;

            /* Retrieve the number of frames */
            WebPMuxNumChunks(mux, WEBP_CHUNK_ANMF, &frames);

            /* Loop over each of the frames */
            for (i = 0; i < frames; ++i) {
                WebPMuxFrameInfo frame = {0};

                /* Retrieve the data for the frame */
                if (WebPMuxGetFrame(mux, i, &frame) != WEBP_MUX_OK) {
                    goto error;
                }

                /* Decode the frame */
                outdata = WebPDecodeRGBA(frame.bitstream.bytes,
                                         frame.bitstream.size,
                                         &width, &height);

                /* Free the compressed data */
                WebPDataClear(&frame.bitstream);

                if (!outdata) {
                    goto error;
                }

                /* Create a layer for the frame */
                char name[255];
                snprintf(name, 255, "Frame %d", (i + 1));

                if (create_layer(*image_ID,
                                 outdata,
                                 0,
                                 (gchar*)name,
                                 width, height,
                                 frame.x_offset,
                                 frame.y_offset) == FALSE) {
                    goto error;
                }
            }

            /* If all is well, jump *over* the error label - otherwise
               leave the loop and begin cleaning things up */

            goto success;

        error:
            break;

        success: ;

        } else {
#endif

            /* Attempt to decode the data as a WebP image */
            outdata = WebPDecodeRGBA(indata, indatalen, &width, &height);
            if (!outdata) {
                break;
            }

            /* Create a single layer */
            status = create_layer(*image_ID,
                                  outdata,
                                  0,
                                  "Background",
                                  width, height,
                                  0, 0);

#ifdef WEBP_0_5
        }

#ifdef GIMP_2_9
        /* Load a color profile if one was provided */
        if (flags & ICCP_FLAG) {
            WebPData          icc_profile;
            GimpColorProfile *profile;

            /* Load the ICC profile from the file */
            WebPMuxGetChunk(mux, "ICCP", &icc_profile);

            /* Have Gimp load the color profile */
            profile = gimp_color_profile_new_from_icc_profile(
                        icc_profile.bytes, icc_profile.size, NULL);
            if (profile) {
                gimp_image_set_color_profile(image_ID, profile);
                g_object_unref(profile);
            }
        }
#endif
#endif
        /* Set the filename for the image */
        gimp_image_set_filename(*image_ID, filename);

    } while(0);

    /* Delete the mux object */
    if (mux) {
        WebPMuxDelete(mux);
    }

    /* Free the data read from disk */
    if (indata) {
        g_free(indata);
    }

    return status;
}
示例#9
0
文件: _webp.c 项目: dvska/Pillow
PyObject* _anim_encoder_assemble(PyObject* self, PyObject* args)
{
    uint8_t* icc_bytes;
    uint8_t* exif_bytes;
    uint8_t* xmp_bytes;
    Py_ssize_t icc_size;
    Py_ssize_t exif_size;
    Py_ssize_t xmp_size;
    WebPData webp_data;
    WebPAnimEncoderObject* encp = (WebPAnimEncoderObject*)self;
    WebPAnimEncoder* enc = encp->enc;
    WebPMux* mux = NULL;
    PyObject* ret = NULL;

    if (!PyArg_ParseTuple(args, "s#s#s#",
    &icc_bytes, &icc_size, &exif_bytes, &exif_size, &xmp_bytes, &xmp_size)) {
        return NULL;
    }

    // Init the output buffer
    WebPDataInit(&webp_data);

    // Assemble everything into the output buffer
    if (!WebPAnimEncoderAssemble(enc, &webp_data)) {
        PyErr_SetString(PyExc_RuntimeError, WebPAnimEncoderGetError(enc));
        return NULL;
    }

    // Re-mux to add metadata as needed
    if (icc_size > 0 || exif_size > 0 || xmp_size > 0) {
        WebPMuxError err = WEBP_MUX_OK;
        int i_icc_size = (int)icc_size;
        int i_exif_size = (int)exif_size;
        int i_xmp_size = (int)xmp_size;
        WebPData icc_profile = { icc_bytes, i_icc_size };
        WebPData exif = { exif_bytes, i_exif_size };
        WebPData xmp = { xmp_bytes, i_xmp_size };

        mux = WebPMuxCreate(&webp_data, 1);
        if (mux == NULL) {
            PyErr_SetString(PyExc_RuntimeError, "could not re-mux to add metadata");
            return NULL;
        }
        WebPDataClear(&webp_data);

        // Add ICCP chunk
        if (i_icc_size > 0) {
            err = WebPMuxSetChunk(mux, "ICCP", &icc_profile, 1);
            if (err != WEBP_MUX_OK) {
                return HandleMuxError(err, "ICCP");
            }
        }

        // Add EXIF chunk
        if (i_exif_size > 0) {
            err = WebPMuxSetChunk(mux, "EXIF", &exif, 1);
            if (err != WEBP_MUX_OK) {
                return HandleMuxError(err, "EXIF");
            }
        }

        // Add XMP chunk
        if (i_xmp_size > 0) {
            err = WebPMuxSetChunk(mux, "XMP ", &xmp, 1);
            if (err != WEBP_MUX_OK) {
                return HandleMuxError(err, "XMP");
            }
        }

        err = WebPMuxAssemble(mux, &webp_data);
        if (err != WEBP_MUX_OK) {
            return HandleMuxError(err, NULL);
        }
    }

    // Convert to Python bytes
    ret = PyBytes_FromStringAndSize((char*)webp_data.bytes, webp_data.size);
    WebPDataClear(&webp_data);

    // If we had to re-mux, we should free it now that we're done with it
    if (mux != NULL) {
        WebPMuxDelete(mux);
    }

    return ret;
}
示例#10
0
/* 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;
}