Beispiel #1
0
PyObject* WebPEncodeRGBA_wrapper(PyObject* self, PyObject* args)
{
    PyBytesObject *rgba_string;
    int width;
    int height;
    int stride;
    float quality_factor;
    uint8_t *rgba;
    uint8_t *output;
    Py_ssize_t size;
    size_t ret_size;

    if (!PyArg_ParseTuple(args, "Siiif", &rgba_string, &width, &height, &stride, &quality_factor)) {
        Py_INCREF(Py_None);
        return Py_None;
    }

    PyBytes_AsStringAndSize((PyObject *) rgba_string, (char**)&rgba, &size);

    if (stride * height > size) {
        Py_INCREF(Py_None);
        return Py_None;
    }

    ret_size = WebPEncodeRGBA(rgba, width, height, stride, quality_factor, &output);
    if (ret_size > 0) {
        PyObject *ret = PyBytes_FromStringAndSize((char*)output, ret_size);
        free(output);
        return ret;
    }
    Py_INCREF(Py_None);
    return Py_None;

}
Beispiel #2
0
uint8_t* webpEncodeRGBA(
	const uint8_t* rgba, int width, int height, int stride, float quality_factor,
	size_t* output_size
) {
	uint8_t* output = NULL;
	*output_size = WebPEncodeRGBA(rgba, width, height, stride, quality_factor, &output);
	return output;
}
Beispiel #3
0
PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
{
    int width;
    int height;
    float quality_factor;
    uint8_t *rgb;
    uint8_t *output;
	char *mode;
    Py_ssize_t size;
    size_t ret_size;

    if (!PyArg_ParseTuple(args, "s#iifs",(char**)&rgb, &size, &width, &height, &quality_factor, &mode)) {
        Py_RETURN_NONE;
    }

	if (strcmp(mode, "RGBA")==0){
		if (size < width * height * 4){
			Py_RETURN_NONE;
		}
		ret_size = WebPEncodeRGBA(rgb, width, height, 4* width, quality_factor, &output);
	} else if (strcmp(mode, "RGB")==0){
		if (size < width * height * 3){
			Py_RETURN_NONE;
		}
		ret_size = WebPEncodeRGB(rgb, width, height, 3* width, quality_factor, &output);
	} else {
		Py_RETURN_NONE;
	}

    if (ret_size > 0) {
        PyObject *ret = PyBytes_FromStringAndSize((char*)output, ret_size);
        free(output);
        return ret;
    }
    Py_RETURN_NONE;
}
Beispiel #4
0
static PoolVector<uint8_t> _webp_lossy_pack(const Ref<Image> &p_image, float p_quality) {

	ERR_FAIL_COND_V(p_image.is_null() || p_image->empty(), PoolVector<uint8_t>());

	Ref<Image> img = p_image->duplicate();
	if (img->detect_alpha())
		img->convert(Image::FORMAT_RGBA8);
	else
		img->convert(Image::FORMAT_RGB8);

	Size2 s(img->get_width(), img->get_height());
	PoolVector<uint8_t> data = img->get_data();
	PoolVector<uint8_t>::Read r = data.read();

	uint8_t *dst_buff = NULL;
	size_t dst_size = 0;
	if (img->get_format() == Image::FORMAT_RGB8) {

		dst_size = WebPEncodeRGB(r.ptr(), s.width, s.height, 3 * s.width, CLAMP(p_quality * 100.0, 0, 100.0), &dst_buff);
	} else {
		dst_size = WebPEncodeRGBA(r.ptr(), s.width, s.height, 4 * s.width, CLAMP(p_quality * 100.0, 0, 100.0), &dst_buff);
	}

	ERR_FAIL_COND_V(dst_size == 0, PoolVector<uint8_t>());
	PoolVector<uint8_t> dst;
	dst.resize(4 + dst_size);
	PoolVector<uint8_t>::Write w = dst.write();
	w[0] = 'W';
	w[1] = 'E';
	w[2] = 'B';
	w[3] = 'P';
	copymem(&w[4], dst_buff, dst_size);
	free(dst_buff);
	w = PoolVector<uint8_t>::Write();
	return dst;
}
Beispiel #5
0
size_t webpEncodeRGBA(
	const uint8_t* rgba, int width, int height, int stride, float quality_factor,
	uint8_t** output
) {
	return WebPEncodeRGBA(rgba, width, height, stride, quality_factor, output);
}
Beispiel #6
0
/*!
 *  pixWriteMemWebP()
 *
 *      Input:  &encdata (<return> webp encoded data of pixs)
 *              &encsize (<return> size of webp encoded data)
 *              pixs (any depth, cmapped OK)
 *              quality (0 - 100; default ~80)
 *              lossless (use 1 for lossless; 0 for lossy)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) Lossless and lossy encoding are entirely different in webp.
 *          @quality applies to lossy, and is ignored for lossless.
 *      (2) The input image is converted to RGB if necessary.  If spp == 3,
 *          we set the alpha channel to fully opaque (255), and
 *          WebPEncodeRGBA() then removes the alpha chunk when encoding,
 *          setting the internal header field has_alpha to 0.
 */
l_int32
pixWriteMemWebP(l_uint8  **pencdata,
                size_t    *pencsize,
                PIX       *pixs,
                l_int32    quality,
                l_int32    lossless)
{
l_int32    w, h, d, wpl, stride;
l_uint32  *data;
PIX       *pix1, *pix2;

    PROCNAME("pixWriteMemWebP");

    if (!pencdata)
        return ERROR_INT("&encdata not defined", procName, 1);
    *pencdata = NULL;
    if (!pencsize)
        return ERROR_INT("&encsize not defined", procName, 1);
    *pencsize = 0;
    if (!pixs)
        return ERROR_INT("&pixs not defined", procName, 1);
    if (lossless == 0 && (quality < 0 || quality > 100))
        return ERROR_INT("quality not in [0 ... 100]", procName, 1);

    if ((pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR)) == NULL)
        return ERROR_INT("failure to remove color map", procName, 1);

        /* Convert to rgb if not 32 bpp; pix2 must not be a clone of pixs. */
    if (pixGetDepth(pix1) != 32)
        pix2 = pixConvertTo32(pix1);
    else
        pix2 = pixCopy(NULL, pix1);
    pixDestroy(&pix1);
    pixGetDimensions(pix2, &w, &h, &d);
    if (w <= 0 || h <= 0 || d != 32) {
        pixDestroy(&pix2);
        return ERROR_INT("pix2 not 32 bpp or of 0 size", procName, 1);
    }

        /* If spp == 3, need to set alpha layer to opaque (all 1s). */
    if (pixGetSpp(pix2) == 3)
        pixSetComponentArbitrary(pix2, L_ALPHA_CHANNEL, 255);

        /* Webp encoder assumes big-endian byte order for RGBA components */
    pixEndianByteSwap(pix2);
    wpl = pixGetWpl(pix2);
    data = pixGetData(pix2);
    stride = wpl * 4;
    if (lossless) {
        *pencsize = WebPEncodeLosslessRGBA((uint8_t *)data, w, h,
                                           stride, pencdata);
    } else {
        *pencsize = WebPEncodeRGBA((uint8_t *)data, w, h, stride,
                                   quality, pencdata);
    }
    pixDestroy(&pix2);

    if (*pencsize == 0) {
        free(pencdata);
        *pencdata = NULL;
        return ERROR_INT("webp encoding failed", procName, 1);
    }

    return 0;
}
Beispiel #7
0
virtual void HandleMessage(const pp::Var& var_message) {
        if (!var_message.is_dictionary ()) {
                return;
        }
        pp::VarDictionary::VarDictionary dic = pp::VarDictionary::VarDictionary (var_message);
        pp::Var s_rgba= dic.Get("rgba");
        pp::Var s_width  = dic.Get("width");
        pp::Var s_height = dic.Get("height");
        pp::Var s_quality= dic.Get("quality");
        pp::Var id = dic.Get("id");

        if (!s_rgba.is_array_buffer()) {
                PostMessage(ErrorMsg("ArrayBuffer no find"));
                return;
        }
        if( !s_width.is_int ()) {
                PostMessage(ErrorMsg("width is not int"));
                return;
        }
        int width = s_width.AsInt ();

        if (!s_height.is_int ()) {
                PostMessage(ErrorMsg("height is not int"));
                return;
        }
        int height = s_height.AsInt ();

        double quality = 80.0f;
        bool lossless = false;
        if (s_quality.is_string()) {
                if (s_quality.AsString() == "lossless") {
                        lossless = true;
                }
        }else if (s_quality.is_number()) {
                double q = s_quality.AsDouble();
                if (q <= 100.0 && q >= 0 ) {
                        quality = (float)q;
                }
        }

        std::unique_ptr<pp::VarArrayBuffer::VarArrayBuffer> array_buffer_var(new pp::VarArrayBuffer::VarArrayBuffer(s_rgba));

        uint8_t* data = static_cast<uint8_t *>(array_buffer_var->Map());
        int byte_length = static_cast<int>(array_buffer_var->ByteLength());

        if (byte_length != (width * height * 4)) {
                PostMessage(ErrorMsg("ArrayBuffer length error :"+ std::to_string(byte_length)));
                return;
        }

        std::shared_ptr<uint8_t> outdata(new uint8_t[byte_length]());
        uint8_t * r_outdata = outdata.get();

        size_t ret;
        if (lossless) {
                ret = WebPEncodeLosslessRGBA(data,width,height,width*4,&r_outdata);
        }else{
                ret = WebPEncodeRGBA(data,width,height,width*4,quality,&r_outdata);
        }
        if (ret == 0) {
                PostMessage(ErrorMsg("encoder  error "));
                return;
        }
        pp::VarArrayBuffer::VarArrayBuffer data_value = pp::VarArrayBuffer::VarArrayBuffer (ret);
        uint8_t* r_data_value = static_cast<uint8_t*>(data_value.Map());
        for (uint32_t i = 0; i < ret; ++i) {
                r_data_value[i] = r_outdata[i];
        }
        data_value.Unmap();

        pp::VarDictionary::VarDictionary ret_msg = pp::VarDictionary::VarDictionary ();
        pp::Var id_key = pp::Var::Var("id");
        ret_msg.Set (id_key,id);
        pp::Var data_key = pp::Var::Var("data");
        ret_msg.Set (data_key,data_value);

        PostMessage(ret_msg);
}
Beispiel #8
0
PyObject* WebPEncode_wrapper(PyObject* self, PyObject* args)
{
    int width;
    int height;
    int lossless;
    float quality_factor;
    uint8_t *rgb;
    uint8_t *icc_bytes;
    uint8_t *exif_bytes;
    uint8_t *output;
    char *mode;
    Py_ssize_t size;
    Py_ssize_t icc_size;
    Py_ssize_t  exif_size;
    size_t ret_size;

    if (!PyArg_ParseTuple(args, "s#iiifss#s#",
                (char**)&rgb, &size, &width, &height, &lossless, &quality_factor, &mode,
                &icc_bytes, &icc_size, &exif_bytes, &exif_size)) {
        Py_RETURN_NONE;
    }
    if (strcmp(mode, "RGBA")==0){
        if (size < width * height * 4){
            Py_RETURN_NONE;
        }
        if (lossless) {
            ret_size = WebPEncodeLosslessRGBA(rgb, width, height, 4* width, &output);
        } else {
            ret_size = WebPEncodeRGBA(rgb, width, height, 4* width, quality_factor, &output);
        }
    } else if (strcmp(mode, "RGB")==0){
        if (size < width * height * 3){
            Py_RETURN_NONE;
        }
        if (lossless) {
            ret_size = WebPEncodeLosslessRGB(rgb, width, height, 3* width, &output);
        } else {
            ret_size = WebPEncodeRGB(rgb, width, height, 3* width, quality_factor, &output);
        }
    } else {
        Py_RETURN_NONE;
    }

#ifndef HAVE_WEBPMUX
    if (ret_size > 0) {
        PyObject *ret = PyBytes_FromStringAndSize((char*)output, ret_size);
        free(output);
        return ret;
    }
#else
   {
    /* I want to truncate the *_size items that get passed into webp
       data. Pypy2.1.0 had some issues where the Py_ssize_t items had
       data in the upper byte. (Not sure why, it shouldn't have been there)
    */
    int i_icc_size = (int)icc_size;
    int i_exif_size = (int)exif_size;
    WebPData output_data = {0};
    WebPData image = { output, ret_size };
    WebPData icc_profile = { icc_bytes, i_icc_size };
    WebPData exif = { exif_bytes, i_exif_size };
    WebPMuxError err;
    int dbg = 0;

    int copy_data = 0;  // value 1 indicates given data WILL be copied to the mux
                        // and value 0 indicates data will NOT be copied.

    WebPMux* mux = WebPMuxNew();
    WebPMuxSetImage(mux, &image, copy_data);

    if (dbg) {
        /* was getting %ld icc_size == 0, icc_size>0 was true */
        fprintf(stderr, "icc size %d, %d \n", i_icc_size, i_icc_size > 0);
    }

    if (i_icc_size > 0) {
        if (dbg) {
            fprintf (stderr, "Adding ICC Profile\n");
        }
        err = WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
        if (dbg && err == WEBP_MUX_INVALID_ARGUMENT) {
            fprintf(stderr, "Invalid ICC Argument\n");
        } else if (dbg && err == WEBP_MUX_MEMORY_ERROR) {
            fprintf(stderr, "ICC Memory Error\n");
        }
    }

    if (dbg) {
        fprintf(stderr, "exif size %d \n", i_exif_size);
    }
    if (i_exif_size > 0) {
        if (dbg){
            fprintf (stderr, "Adding Exif Data\n");
        }
        err = WebPMuxSetChunk(mux, "EXIF", &exif, copy_data);
        if (dbg && err == WEBP_MUX_INVALID_ARGUMENT) {
            fprintf(stderr, "Invalid Exif Argument\n");
        } else if (dbg && err == WEBP_MUX_MEMORY_ERROR) {
            fprintf(stderr, "Exif Memory Error\n");
        }
    }

    WebPMuxAssemble(mux, &output_data);
    WebPMuxDelete(mux);
    free(output);

    ret_size = output_data.size;
    if (ret_size > 0) {
        PyObject *ret = PyBytes_FromStringAndSize((char*)output_data.bytes, ret_size);
        WebPDataClear(&output_data);
        return ret;
    }
    }
#endif
    Py_RETURN_NONE;
}
    DEFINE_FUNC_5(webp_encode_argb, data_buffer_value, width_value, height_value, lossless_value, quality_factor_value) {
        int width = 0;
        int height = 0;
        float quality_factor = 100;
        int lossless = 1;
        int stride = 0;
        uint8_t* abgr = NULL;
        uint8_t* rgba = NULL;
        uint8_t* output = NULL;
        int output_size = 0;
        int pixels_size;
        int bytes_size;
        buffer data_buffer;

        if (val_is_int(width_value)) width = val_int(width_value);
        if (val_is_int(height_value)) height = val_int(height_value);
        if (val_is_bool(lossless_value)) lossless = val_bool(lossless_value);
        if (val_is_float(quality_factor_value)) quality_factor = val_float(quality_factor_value);

        stride = width * 4;
        pixels_size = width * height;
        bytes_size = pixels_size * 4;

        if (!val_is_buffer(data_buffer_value)) {
            val_throw(alloc_string("webp_encode_argb: Expected to be a buffer"));
            return alloc_null();
        }

        data_buffer = val_to_buffer(data_buffer_value);

        if (bytes_size != buffer_size(data_buffer)) {
            val_throw(alloc_string("webp_encode_argb: Invalid buffer size"));
            return alloc_null();
        }

        //if ()

        abgr = (uint8_t *)buffer_data(data_buffer);
        rgba = (uint8_t *)malloc(bytes_size);

        uint8_t* _abgr = abgr;
        uint8_t* _rgba = rgba;
        int _pixels_size = pixels_size;

        while (_pixels_size-- > 0) {
            //_rgba[0] = _abgr[3];
            _rgba[0] = _abgr[1];
            _rgba[1] = _abgr[2];
            _rgba[2] = _abgr[3];
            _rgba[3] = _abgr[0];
            _abgr += 4;
            _rgba += 4;
        }

        if (lossless) {
            output_size = WebPEncodeLosslessRGBA(
                              rgba,
                              //abgr,
                              width, height, stride,
                              &output
                          );
        } else {
            output_size = WebPEncodeRGBA(
                              rgba,
                              //abgr,
                              width, height, stride,
                              quality_factor,
                              &output
                          );
        }

        printf("output_size: (%d, %d, %d) : %d\n", width, height, stride, output_size);

        buffer output_buffer = alloc_buffer_len(0);
        buffer_append_sub(output_buffer, (char *)output, output_size);
        buffer_set_size(output_buffer, output_size);

        if (output != NULL) free(output);
        if (rgba != NULL) free(rgba);

        return buffer_val(output_buffer);
    }
Beispiel #10
0
/*!
 * \brief   pixWriteMemWebP()
 *
 * \param[out]   pencdata   webp encoded data of pixs
 * \param[out]   pencsize   size of webp encoded data
 * \param[in]    pixs       any depth, cmapped OK
 * \param[in]    quality    0 - 100; default ~80
 * \param[in]    lossless   use 1 for lossless; 0 for lossy
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) Lossless and lossy encoding are entirely different in webp.
 *          %quality applies to lossy, and is ignored for lossless.
 *      (2) The input image is converted to RGB if necessary.  If spp == 3,
 *          we set the alpha channel to fully opaque (255), and
 *          WebPEncodeRGBA() then removes the alpha chunk when encoding,
 *          setting the internal header field has_alpha to 0.
 * </pre>
 */
l_ok
pixWriteMemWebP(l_uint8  **pencdata,
                size_t    *pencsize,
                PIX       *pixs,
                l_int32    quality,
                l_int32    lossless)
{
l_int32    w, h, d, wpl, stride;
l_uint32  *data;
PIX       *pix1, *pix2;

    PROCNAME("pixWriteMemWebP");

    if (!pencdata)
        return ERROR_INT("&encdata not defined", procName, 1);
    *pencdata = NULL;
    if (!pencsize)
        return ERROR_INT("&encsize not defined", procName, 1);
    *pencsize = 0;
    if (!pixs)
        return ERROR_INT("&pixs not defined", procName, 1);
    if (lossless == 0 && (quality < 0 || quality > 100))
        return ERROR_INT("quality not in [0 ... 100]", procName, 1);

    if ((pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR)) == NULL)
        return ERROR_INT("failure to remove color map", procName, 1);

        /* Convert to rgb if not 32 bpp; pix2 must not be a clone of pixs. */
    if (pixGetDepth(pix1) != 32)
        pix2 = pixConvertTo32(pix1);
    else
        pix2 = pixCopy(NULL, pix1);
    pixDestroy(&pix1);
    pixGetDimensions(pix2, &w, &h, &d);
    if (w <= 0 || h <= 0 || d != 32) {
        pixDestroy(&pix2);
        return ERROR_INT("pix2 not 32 bpp or of 0 size", procName, 1);
    }

        /* If spp == 3, need to set alpha layer to opaque (all 1s). */
    if (pixGetSpp(pix2) == 3)
        pixSetComponentArbitrary(pix2, L_ALPHA_CHANNEL, 255);

        /* The WebP API expects data in RGBA order.  The pix stores
         * in host-dependent order with R as the MSB and A as the LSB.
         * On little-endian machines, the bytes in the word must
         * be swapped; e.g., R goes from byte 0 (LSB) to byte 3 (MSB).
         * No swapping is necessary for big-endians. */
    pixEndianByteSwap(pix2);
    wpl = pixGetWpl(pix2);
    data = pixGetData(pix2);
    stride = wpl * 4;
    if (lossless) {
        *pencsize = WebPEncodeLosslessRGBA((uint8_t *)data, w, h,
                                           stride, pencdata);
    } else {
        *pencsize = WebPEncodeRGBA((uint8_t *)data, w, h, stride,
                                   quality, pencdata);
    }
    pixDestroy(&pix2);

    if (*pencsize == 0) {
        free(*pencdata);
        *pencdata = NULL;
        return ERROR_INT("webp encoding failed", procName, 1);
    }

    return 0;
}