static bool encodePixels(IntSize imageSize, const unsigned char* pixels, bool premultiplied, int quality, Vector<unsigned char>* output)
{
    if (imageSize.width() <= 0 || imageSize.width() > WEBP_MAX_DIMENSION)
        return false;
    if (imageSize.height() <= 0 || imageSize.height() > WEBP_MAX_DIMENSION)
        return false;

    WebPConfig config;
    if (!WebPConfigInit(&config))
        return false;
    WebPPicture picture;
    if (!WebPPictureInit(&picture))
        return false;

    picture.width = imageSize.width();
    picture.height = imageSize.height();

    if (premultiplied && !platformPremultipliedImportPicture(pixels, &picture))
        return false;
    if (!premultiplied && !importPictureRGBX<false>(pixels, &picture))
        return false;

    picture.custom_ptr = output;
    picture.writer = &writeOutput;
    config.quality = quality;
    config.method = 3;

    bool success = WebPEncode(&config, &picture);
    WebPPictureFree(&picture);
    return success;
}
Example #2
0
static size_t encode(const uint8_t* rgba, int width, int height,
                     uint8_t** output)
{
    WebPPicture pic;
    WebPConfig config;
    WebPMemoryWriter wrt;
    int ok;

    if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, 100) ||
            !WebPPictureInit(&pic))
    {
        return 0;
    }

    config.lossless = true;
    config.method = 6;
    pic.use_argb = true;
    pic.width = width;
    pic.height = height;
    pic.writer = WebPMemoryWrite;
    pic.custom_ptr = &wrt;
    WebPMemoryWriterInit(&wrt);

    ok = WebPPictureImportRGBA(&pic, rgba, width * 4) &&
         WebPEncode(&config, &pic);
    WebPPictureFree(&pic);
    if (!ok)
        return 0;
    *output = wrt.mem;
    return wrt.size;
}
Example #3
0
bool
WebpOutput::write_scanline (int y, int z, TypeDesc format,
                            const void *data, stride_t xstride)
{
    if (y > m_spec.height)
    {
        error ("Attempt to write too many scanlines to %s", m_filename.c_str());
        close ();
        return false;
    }
    std::vector<uint8_t> scratch;
    data = to_native_scanline (format, data, xstride, scratch,
                               m_dither, y, z);
    memcpy(&m_uncompressed_image[y*m_scanline_size], data, m_scanline_size);

    if (y == m_spec.height - 1)
    {
        if (m_spec.nchannels == 4)
        {
            WebPPictureImportRGBA(&m_webp_picture, &m_uncompressed_image[0], m_scanline_size);
        }
        else
        {
            WebPPictureImportRGB(&m_webp_picture, &m_uncompressed_image[0], m_scanline_size);
        }
        if (!WebPEncode(&m_webp_config, &m_webp_picture))
        {
            error ("Failed to encode %s as WebP image", m_filename.c_str());
            close();
            return false;
        }
    }
    return true;    
}
Example #4
0
static gboolean
export_webp (GeglOperation       *operation,
             GeglBuffer          *input,
             const GeglRectangle *result,
             GOutputStream       *stream)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  WebPConfig config;
  WebPPicture picture;
  const Babl *format;
  gint status;

  g_return_val_if_fail (stream != NULL, FALSE);

  if (!WebPConfigInit (&config) || !WebPPictureInit (&picture))
    {
      g_warning ("could not initialize WebP encoder");
      return FALSE;
    }

  if (!WebPConfigPreset (&config, WEBP_PRESET_DEFAULT, o->quality))
    {
      g_warning("could not load WebP default preset");
      return FALSE;
    }

  picture.width = result->width;
  picture.height = result->height;

  format = babl_format ("R'G'B'A u8");

  if (!WebPValidateConfig (&config))
    {
      g_warning ("WebP encoder configuration is invalid");
      return FALSE;
    }

  picture.writer = write_to_stream;
  picture.custom_ptr = stream;

  if (save_RGBA (&picture, input, result, format))
    {
      g_warning ("could not pass pixels data to WebP encoder");
      return FALSE;
    }

  status = WebPEncode (&config, &picture);

  WebPPictureFree (&picture);

  return status ? TRUE : FALSE;
}
Example #5
0
static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic,
                       WebPData* const encoded_data) {
  WebPMemoryWriter memory;
  pic->use_argb = 1;
  pic->writer = WebPMemoryWrite;
  pic->custom_ptr = &memory;
  WebPMemoryWriterInit(&memory);
  if (!WebPEncode(config, pic)) {
    return 0;
  }
  encoded_data->bytes = memory.mem;
  encoded_data->size  = memory.size;
  return 1;
}
Example #6
0
static int libwebp_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                                const AVFrame *frame, int *got_packet)
{
    LibWebPContext *s  = avctx->priv_data;
    WebPPicture *pic = NULL;
    AVFrame *alt_frame = NULL;
    WebPMemoryWriter mw = { 0 };

    int ret = ff_libwebp_get_frame(avctx, s, frame, &alt_frame, &pic);
    if (ret < 0)
        goto end;

    WebPMemoryWriterInit(&mw);
    pic->custom_ptr = &mw;
    pic->writer     = WebPMemoryWrite;

    ret = WebPEncode(&s->config, pic);
    if (!ret) {
        av_log(avctx, AV_LOG_ERROR, "WebPEncode() failed with error: %d\n",
               pic->error_code);
        ret = ff_libwebp_error_to_averror(pic->error_code);
        goto end;
    }

    ret = ff_alloc_packet(pkt, mw.size);
    if (ret < 0)
        goto end;
    memcpy(pkt->data, mw.mem, mw.size);

    pkt->flags |= AV_PKT_FLAG_KEY;
    *got_packet = 1;

end:
#if (WEBP_ENCODER_ABI_VERSION > 0x0203)
    WebPMemoryWriterClear(&mw);
#else
    free(mw.mem); /* must use free() according to libwebp documentation */
#endif
    WebPPictureFree(pic);
    av_freep(&pic);
    av_frame_free(&alt_frame);

    return ret;
}
Example #7
0
/*
* Finish off an encoded strip by flushing it.
*/
static int
TWebPPostEncode(TIFF* tif)
{
  static const char module[] = "WebPPostEncode";
  int64_t stride;
  WebPState *sp = EncoderState(tif);
  assert(sp != NULL);

  assert(sp->state == LSTATE_INIT_ENCODE);

  stride = (int64_t)sp->sPicture.width * sp->nSamples;

#if WEBP_ENCODER_ABI_VERSION >= 0x0100
  if (sp->nSamples == 4) {
      if (!WebPPictureImportRGBA(&sp->sPicture, sp->pBuffer, (int)stride)) {
          TIFFErrorExt(tif->tif_clientdata, module,
                    "WebPPictureImportRGBA() failed" );
          return 0;
      }
  }
  else
#endif
  if (!WebPPictureImportRGB(&sp->sPicture, sp->pBuffer, (int)stride)) {
      TIFFErrorExt(tif->tif_clientdata, module,
                    "WebPPictureImportRGB() failed");
      return 0;
  }
  
  if (!WebPEncode(&sp->sEncoderConfig, &sp->sPicture)) {

#if WEBP_ENCODER_ABI_VERSION >= 0x0100
    const char* pszErrorMsg = NULL;
    switch(sp->sPicture.error_code) {
    case VP8_ENC_ERROR_OUT_OF_MEMORY:
        pszErrorMsg = "Out of memory"; break;
    case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY:
        pszErrorMsg = "Out of memory while flushing bits"; break;
    case VP8_ENC_ERROR_NULL_PARAMETER:
        pszErrorMsg = "A pointer parameter is NULL"; break;
    case VP8_ENC_ERROR_INVALID_CONFIGURATION:
        pszErrorMsg = "Configuration is invalid"; break;
    case VP8_ENC_ERROR_BAD_DIMENSION:
        pszErrorMsg = "Picture has invalid width/height"; break;
    case VP8_ENC_ERROR_PARTITION0_OVERFLOW:
        pszErrorMsg = "Partition is bigger than 512k. Try using less "
            "SEGMENTS, or increase PARTITION_LIMIT value";
        break;
    case VP8_ENC_ERROR_PARTITION_OVERFLOW:
        pszErrorMsg = "Partition is bigger than 16M";
        break;
    case VP8_ENC_ERROR_BAD_WRITE:
        pszErrorMsg = "Error while fludshing bytes"; break;
    case VP8_ENC_ERROR_FILE_TOO_BIG:
        pszErrorMsg = "File is bigger than 4G"; break;
    case VP8_ENC_ERROR_USER_ABORT:
        pszErrorMsg = "User interrupted";
        break;
    default:
        TIFFErrorExt(tif->tif_clientdata, module,
                "WebPEncode returned an unknown error code: %d",
                sp->sPicture.error_code);
        pszErrorMsg = "Unknown WebP error type.";
        break;
    }
    TIFFErrorExt(tif->tif_clientdata, module,
             "WebPEncode() failed : %s", pszErrorMsg);
#else
    TIFFErrorExt(tif->tif_clientdata, module,
             "Error in WebPEncode()");
#endif
    return 0;
  }

  sp->sPicture.custom_ptr = NULL;

  if (!TIFFFlushData1(tif))
  {
    TIFFErrorExt(tif->tif_clientdata, module,
      "Error flushing TIFF WebP encoder.");
    return 0;
  }

  return 1;
}
Example #8
0
static MagickBooleanType WriteWEBPImage(const ImageInfo *image_info,
                                        Image *image)
{
    int
    webp_status;

    MagickBooleanType
    status;

    register const PixelPacket
    *__restrict__ p;

    register ssize_t
    x;

    register unsigned char
    *__restrict__ q;

    ssize_t
    y;

    unsigned char
    *pixels;

    WebPConfig
    configure;

    WebPPicture
    picture;

    WebPAuxStats
    statistics;

    /*
      Open output image file.
    */
    assert(image_info != (const ImageInfo *) NULL);
    assert(image_info->signature == MagickSignature);
    assert(image != (Image *) NULL);
    assert(image->signature == MagickSignature);
    if (image->debug != MagickFalse)
        (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
    if (status == MagickFalse)
        return(status);
    if (WebPPictureInit(&picture) == 0)
        ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    picture.writer=WebPWriter;
    picture.custom_ptr=(void *) image;
    picture.stats=(&statistics);
    picture.width=(int) image->columns;
    picture.height=(int) image->rows;
    if (image->quality != UndefinedCompressionQuality)
        configure.quality=(float) image->quality;
    if (WebPConfigInit(&configure) == 0)
        ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    /*
      Future: set custom configuration parameters here.
    */
    if (WebPValidateConfig(&configure) == 0)
        ThrowWriterException(ResourceLimitError,"UnableToEncodeImageFile");
    /*
      Allocate memory for pixels.
    */
    pixels=(unsigned char *) AcquireQuantumMemory(image->columns,
            (image->matte != MagickFalse ? 4 : 3)*image->rows*sizeof(*pixels));
    if (pixels == (unsigned char *) NULL)
        ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    /*
      Convert image to WebP raster pixels.
    */
    q=pixels;
    for (y=0; y < (ssize_t) image->rows; y++)
    {
        p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
        if (p == (PixelPacket *) NULL)
            break;
        for (x=0; x < (ssize_t) image->columns; x++)
        {
            *q++=ScaleQuantumToChar(GetRedPixelComponent(p));
            *q++=ScaleQuantumToChar(GetGreenPixelComponent(p));
            *q++=ScaleQuantumToChar(GetBluePixelComponent(p));
            if (image->matte != MagickFalse)
                *q++=ScaleQuantumToChar((Quantum) (QuantumRange-
                                                   (image->matte != MagickFalse ? GetOpacityPixelComponent(p) :
                                                    OpaqueOpacity)));
            p++;
        }
        status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
                                image->rows);
        if (status == MagickFalse)
            break;
    }
    if (image->matte == MagickFalse)
        webp_status=WebPPictureImportRGB(&picture,pixels,3*picture.width);
    else
        webp_status=WebPPictureImportRGBA(&picture,pixels,4*picture.width);
    pixels=(unsigned char *) RelinquishMagickMemory(pixels);
    webp_status=WebPEncode(&configure,&picture);
    (void) CloseBlob(image);
    return(webp_status == 0 ? MagickFalse : MagickTrue);
}
Example #9
0
/**
Encode a FIBITMAP to a WebP image
@param hmem Memory output stream, containing on return the encoded image
@param dib The FIBITMAP to encode
@param flags FreeImage save flags
@return Returns TRUE if successfull, returns FALSE otherwise
*/
static BOOL
EncodeImage(FIMEMORY *hmem, FIBITMAP *dib, int flags) {
	WebPPicture picture;	// Input buffer
	WebPConfig config;		// Coding parameters

	BOOL bIsFlipped = FALSE;

	try {
		const unsigned width = FreeImage_GetWidth(dib);
		const unsigned height = FreeImage_GetHeight(dib);
		const unsigned bpp = FreeImage_GetBPP(dib);
		const unsigned pitch = FreeImage_GetPitch(dib);

		// check image type
		FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);

		if( !((image_type == FIT_BITMAP) && ((bpp == 24) || (bpp == 32))) )  {
			throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
		}

		// check format limits
		if(MAX(width, height) > WEBP_MAX_DIMENSION) {
			FreeImage_OutputMessageProc(s_format_id, "Unsupported image size: width x height = %d x %d", width, height);
			return FALSE;
		}

		// Initialize output I/O
		if(WebPPictureInit(&picture) == 1) {
			picture.writer = WebP_MemoryWriter;
			picture.custom_ptr = hmem;
			picture.width = (int)width;
			picture.height = (int)height;
		} else {
			throw "Couldn't initialize WebPPicture";
		}

		// --- Set encoding parameters ---

		// Initialize encoding parameters to default values
		WebPConfigInit(&config);

		// quality/speed trade-off (0=fast, 6=slower-better)
		config.method = 6;

		if((flags & WEBP_LOSSLESS) == WEBP_LOSSLESS) {
			// lossless encoding
			config.lossless = 1;
			picture.use_argb = 1;
		} else if((flags & 0x7F) > 0) {
			// lossy encoding
			config.lossless = 0;
			// quality is between 1 (smallest file) and 100 (biggest) - default to 75
			config.quality = (float)(flags & 0x7F);
			if(config.quality > 100) {
				config.quality = 100;
			}
		}

		// validate encoding parameters
		if(WebPValidateConfig(&config) == 0) {
			throw "Failed to initialize encoder";
		}

		// --- Perform encoding ---
		
		// Invert dib scanlines
		bIsFlipped = FreeImage_FlipVertical(dib);


		// convert dib buffer to output stream

		const BYTE *bits = FreeImage_GetBits(dib);

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
		switch(bpp) {
			case 24:
				WebPPictureImportBGR(&picture, bits, pitch);
				break;
			case 32:
				WebPPictureImportBGRA(&picture, bits, pitch);
				break;
		}
#else
		switch(bpp) {
			case 24:
				WebPPictureImportRGB(&picture, bits, pitch);
				break;
			case 32:
				WebPPictureImportRGBA(&picture, bits, pitch);
				break;
		}

#endif // FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR

		if(!WebPEncode(&config, &picture)) {
			throw "Failed to encode image";
		}

		WebPPictureFree(&picture);

		if(bIsFlipped) {
			// invert dib scanlines
			FreeImage_FlipVertical(dib);
		}

		return TRUE;

	} catch (const char* text) {

		WebPPictureFree(&picture);

		if(bIsFlipped) {
			// invert dib scanlines
			FreeImage_FlipVertical(dib);
		}

		if(NULL != text) {
			FreeImage_OutputMessageProc(s_format_id, text);
		}
	}

	return FALSE;
}
Example #10
0
int webp_encode(const char *in_file, const char *out_file, const FfiWebpEncodeConfig *encode_config) {
  int return_value = -1;
  FILE *out = NULL;
  int keep_alpha = 1;
  WebPPicture picture;
  WebPConfig config;
  // OPTIONS BEGIN
  if (encode_config->lossless == 0 || encode_config->lossless == 1){
    config.lossless = encode_config->lossless;
  }
  if (encode_config->quality >= 0 && encode_config->quality <= 100){
    config.quality = encode_config->quality;
  }
  if (encode_config->method >= 0 && encode_config->method <= 6){
    config.method = encode_config->method;
  }
  if (encode_config->target_size > 0){
    config.target_size = encode_config->target_size;
  }
  if (encode_config->target_PSNR > 0){
    config.target_PSNR = encode_config->target_PSNR;
  }
  if (encode_config->segments >= 0 && encode_config->segments <= 4){
    config.segments = encode_config->segments;
  }
  if (encode_config->sns_strength >= 0 && encode_config->sns_strength <= 100){
    config.sns_strength = encode_config->sns_strength;
  }
  if (encode_config->filter_strength >= 0 && encode_config->filter_strength <= 100){
    config.filter_strength = encode_config->filter_strength;
  }
  if (encode_config->filter_sharpness >= 0 && encode_config->filter_sharpness <= 7){
    config.filter_sharpness = encode_config->filter_sharpness;
  }
  if (encode_config->filter_type == 0 || encode_config->filter_type == 1){
    config.filter_type = encode_config->filter_type;
  }
  if (encode_config->autofilter == 0 || encode_config->autofilter == 1){
    config.autofilter = encode_config->autofilter;
  }
  if (encode_config->alpha_compression == 0 || encode_config->alpha_compression == 1){
    config.alpha_compression = encode_config->alpha_compression;
  }
  if (encode_config->alpha_filtering >= 0 && encode_config->alpha_filtering <= 2){
    config.alpha_filtering = encode_config->alpha_filtering;
  }
  if (encode_config->alpha_quality >= 0 && encode_config->alpha_quality <= 100){
    config.alpha_quality = encode_config->alpha_quality;
  }
  if (encode_config->pass >= 0 && encode_config->pass <= 10){
    config.pass = encode_config->pass;
  }
  if (encode_config->show_compressed >= 0){
    config.show_compressed = encode_config->show_compressed;
  }
  if (encode_config->preprocessing == 0 || encode_config->preprocessing == 1){
    config.preprocessing = encode_config->preprocessing;
  }
  if (encode_config->partitions >= 0 && encode_config->partitions <= 3){
    config.partitions = encode_config->partitions;
  }
  if (encode_config->partition_limit >= 0 && encode_config->partition_limit <= 100){
    config.partition_limit = encode_config->partition_limit;
  }
  if ((encode_config->width | encode_config->height) > 0){
    picture.width = encode_config->width;
    picture.height = encode_config->height;
  }
  // OPTIONS END
  
  if (!WebPPictureInit(&picture) ||
      !WebPConfigInit(&config)) {
    //fprintf(stderr, "Error! Version mismatch!\n");
    return 1;
  }
  
  if (!WebPValidateConfig(&config)) {
    //fprintf(stderr, "Error! Invalid configuration.\n");
    return_value = 2;
    goto Error;
  }
  
  if (!UtilReadPicture(in_file, &picture, keep_alpha)) {
    //fprintf(stderr, "Error! Cannot read input picture file '%s'\n", in_file);
    return_value = 3;
    goto Error;
  }
  
  out = fopen(out_file, "wb");
  if (out == NULL) {
    //fprintf(stderr, "Error! Cannot open output file '%s'\n", out_file);
    return_value = 4;
    goto Error;
  }
  picture.writer = EncodeWriter;
  picture.custom_ptr = (void*)out;
  
  if ((encode_config->crop_w | encode_config->crop_h) > 0){
    if (!WebPPictureView(&picture, encode_config->crop_x, encode_config->crop_y, encode_config->crop_w, encode_config->crop_h, &picture)) {
      //fprintf(stderr, "Error! Cannot crop picture\n");
      return_value = 5;
      goto Error;
    }
  }
  
  if ((encode_config->resize_w | encode_config->resize_h) > 0) {
    if (!WebPPictureRescale(&picture, encode_config->resize_w, encode_config->resize_h)) {
      //fprintf(stderr, "Error! Cannot resize picture\n");
      return_value = 6;
      goto Error;
    }
  }
  
  if (picture.extra_info_type > 0) {
    AllocExtraInfo(&picture);
  }
  
  if (!WebPEncode(&config, &picture)) {
    //fprintf(stderr, "Error! Cannot encode picture as WebP\n");
    return_value = 7;
    goto Error;
  }
  return_value = 0;
  
Error:
  free(picture.extra_info);
  WebPPictureFree(&picture);
  if (out != NULL) {
    fclose(out);
  }

  return return_value;
}
Example #11
0
GDALDataset *
WEBPDataset::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();

/* -------------------------------------------------------------------- */
/*      WEBP library initialization                                     */
/* -------------------------------------------------------------------- */

    WebPPicture sPicture;
    if (!WebPPictureInit(&sPicture))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureInit() failed");
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Some some rudimentary checks                                    */
/* -------------------------------------------------------------------- */

    if( nXSize > 16383 || nYSize > 16383 )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "WEBP maximum image dimensions are 16383 x 16383.");

        return NULL;
    }

    if( nBands != 3 )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "WEBP driver doesn't support %d bands. Must be 3 (RGB) bands.",
                  nBands );

        return NULL;
    }

    GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();

    if( eDT != GDT_Byte )
    {
        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                  "WEBP driver doesn't support data type %s. "
                  "Only eight bit byte bands supported.",
                  GDALGetDataTypeName(
                      poSrcDS->GetRasterBand(1)->GetRasterDataType()) );

        if (bStrict)
            return NULL;
    }

/* -------------------------------------------------------------------- */
/*      What options has the user selected?                             */
/* -------------------------------------------------------------------- */
    float fQuality = 75.0f;
    const char* pszQUALITY = CSLFetchNameValue(papszOptions, "QUALITY"); 
    if( pszQUALITY != NULL )
    {
        fQuality = (float) atof(pszQUALITY);
        if( fQuality < 0.0f || fQuality > 100.0f )
        {
            CPLError( CE_Failure, CPLE_IllegalArg,
                      "%s=%s is not a legal value.", "QUALITY", pszQUALITY);
            return NULL;
        }
    }

    WebPPreset nPreset = WEBP_PRESET_DEFAULT;
    const char* pszPRESET = CSLFetchNameValueDef(papszOptions, "PRESET", "DEFAULT");
    if (EQUAL(pszPRESET, "DEFAULT"))
        nPreset = WEBP_PRESET_DEFAULT;
    else if (EQUAL(pszPRESET, "PICTURE"))
        nPreset = WEBP_PRESET_PICTURE;
    else if (EQUAL(pszPRESET, "PHOTO"))
        nPreset = WEBP_PRESET_PHOTO;
    else if (EQUAL(pszPRESET, "PICTURE"))
        nPreset = WEBP_PRESET_PICTURE;
    else if (EQUAL(pszPRESET, "DRAWING"))
        nPreset = WEBP_PRESET_DRAWING;
    else if (EQUAL(pszPRESET, "ICON"))
        nPreset = WEBP_PRESET_ICON;
    else if (EQUAL(pszPRESET, "TEXT"))
        nPreset = WEBP_PRESET_TEXT;
    else
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "%s=%s is not a legal value.", "PRESET", pszPRESET );
        return NULL;
    }

    WebPConfig sConfig;
    if (!WebPConfigInitInternal(&sConfig, nPreset, fQuality, WEBP_ENCODER_ABI_VERSION))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPConfigInit() failed");
        return NULL;
    }


#define FETCH_AND_SET_OPTION_INT(name, fieldname, minval, maxval) \
{ \
    const char* pszVal = CSLFetchNameValue(papszOptions, name); \
    if (pszVal != NULL) \
    { \
        sConfig.fieldname = atoi(pszVal); \
        if (sConfig.fieldname < minval || sConfig.fieldname > maxval) \
        { \
            CPLError( CE_Failure, CPLE_IllegalArg, \
                      "%s=%s is not a legal value.", name, pszVal ); \
            return NULL; \
        } \
    } \
}

    FETCH_AND_SET_OPTION_INT("TARGETSIZE", target_size, 0, INT_MAX);

    const char* pszPSNR = CSLFetchNameValue(papszOptions, "PSNR");
    if (pszPSNR)
    {
        sConfig.target_PSNR = atof(pszPSNR);
        if (sConfig.target_PSNR < 0)
        {
            CPLError( CE_Failure, CPLE_IllegalArg,
                      "PSNR=%s is not a legal value.", pszPSNR );
            return NULL;
        }
    }

    FETCH_AND_SET_OPTION_INT("METHOD", method, 0, 6);
    FETCH_AND_SET_OPTION_INT("SEGMENTS", segments, 1, 4);
    FETCH_AND_SET_OPTION_INT("SNS_STRENGTH", sns_strength, 0, 100);
    FETCH_AND_SET_OPTION_INT("FILTER_STRENGTH", filter_strength, 0, 100);
    FETCH_AND_SET_OPTION_INT("FILTER_SHARPNESS", filter_sharpness, 0, 7);
    FETCH_AND_SET_OPTION_INT("FILTER_TYPE", filter_type, 0, 1);
    FETCH_AND_SET_OPTION_INT("AUTOFILTER", autofilter, 0, 1);
    FETCH_AND_SET_OPTION_INT("PASS", pass, 1, 10);
    FETCH_AND_SET_OPTION_INT("PREPROCESSING", preprocessing, 0, 1);
    FETCH_AND_SET_OPTION_INT("PARTITIONS", partitions, 0, 3);

    if (!WebPValidateConfig(&sConfig))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPValidateConfig() failed");
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Allocate memory                                                 */
/* -------------------------------------------------------------------- */
    GByte   *pabyBuffer;

    pabyBuffer = (GByte *) VSIMalloc( 3 * nXSize * nYSize );
    if (pabyBuffer == NULL)
    {
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create the dataset.                                             */
/* -------------------------------------------------------------------- */
    VSILFILE    *fpImage;

    fpImage = VSIFOpenL( pszFilename, "wb" );
    if( fpImage == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Unable to create WEBP file %s.\n",
                  pszFilename );
        VSIFree(pabyBuffer);
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      WEBP library settings                                           */
/* -------------------------------------------------------------------- */

    sPicture.colorspace = 0;
    sPicture.width = nXSize;
    sPicture.height = nYSize;
    sPicture.writer = WEBPDatasetWriter;
    sPicture.custom_ptr = fpImage;
    if (!WebPPictureAlloc(&sPicture))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureAlloc() failed");
        VSIFree(pabyBuffer);
        VSIFCloseL( fpImage );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Acquire source imagery.                                         */
/* -------------------------------------------------------------------- */
    CPLErr      eErr = CE_None;

    eErr = poSrcDS->RasterIO( GF_Read, 0, 0, nXSize, nYSize,
                              pabyBuffer, nXSize, nYSize, GDT_Byte,
                              3, NULL,
                              3, 3 * nXSize, 1 );

/* -------------------------------------------------------------------- */
/*      Import and write to file                                        */
/* -------------------------------------------------------------------- */
    if (eErr == CE_None &&
        !WebPPictureImportRGB(&sPicture, pabyBuffer, 3 * nXSize))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureImportRGB() failed");
        eErr = CE_Failure;
    }

    if (eErr == CE_None && !WebPEncode(&sConfig, &sPicture))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPEncode() failed");
        eErr = CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Cleanup and close.                                              */
/* -------------------------------------------------------------------- */
    CPLFree( pabyBuffer );

    WebPPictureFree(&sPicture);

    VSIFCloseL( fpImage );

    if( eErr != CE_None )
    {
        VSIUnlink( pszFilename );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Re-open dataset, and copy any auxilary pam information.         */
/* -------------------------------------------------------------------- */
    GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);

    /* If outputing to stdout, we can't reopen it, so we'll return */
    /* a fake dataset to make the caller happy */
    CPLPushErrorHandler(CPLQuietErrorHandler);
    WEBPDataset *poDS = (WEBPDataset*) WEBPDataset::Open( &oOpenInfo );
    CPLPopErrorHandler();
    if( poDS )
    {
        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
        return poDS;
    }

    return NULL;
}
Example #12
0
int
encodeWEBP(Vbitmap *vbitmap, Ychannel *channelout, YmagineFormatOptions *options)
{
  int rc = YMAGINE_ERROR;

#if HAVE_WEBP
  WebPConfig config;
  WebPPicture picture;
  WebPPreset preset = WEBP_PRESET_PHOTO; // One of DEFAULT, PICTURE, PHOTO, DRAWING, ICON or TEXT
  int width;
  int height;
  int pitch;
  int quality;
  const unsigned char *pixels;
  int colormode;

  /*
   * List of encoding options for WebP config
   *   int lossless;           // Lossless encoding (0=lossy(default), 1=lossless).
   *   float quality;          // between 0 (smallest file) and 100 (biggest)
   *   int method;             // quality/speed trade-off (0=fast, 6=slower-better)
   *
   *   WebPImageHint image_hint;  // Hint for image type (lossless only for now).
   *
   *   // Parameters related to lossy compression only:
   *   int target_size;        // if non-zero, set the desired target size in bytes.
   *                           // Takes precedence over the 'compression' parameter.
   *   float target_PSNR;      // if non-zero, specifies the minimal distortion to
   *                           // try to achieve. Takes precedence over target_size.
   *   int segments;           // maximum number of segments to use, in [1..4]
   *   int sns_strength;       // Spatial Noise Shaping. 0=off, 100=maximum.
   *   int filter_strength;    // range: [0 = off .. 100 = strongest]
   *   int filter_sharpness;   // range: [0 = off .. 7 = least sharp]
   *   int filter_type;        // filtering type: 0 = simple, 1 = strong (only used
   *                           // if filter_strength > 0 or autofilter > 0)
   *   int autofilter;         // Auto adjust filter's strength [0 = off, 1 = on]
   *   int alpha_compression;  // Algorithm for encoding the alpha plane (0 = none,
   *                           // 1 = compressed with WebP lossless). Default is 1.
   *   int alpha_filtering;    // Predictive filtering method for alpha plane.
   *                           //  0: none, 1: fast, 2: best. Default if 1.
   *   int alpha_quality;      // Between 0 (smallest size) and 100 (lossless).
   *                           // Default is 100.
   *   int pass;               // number of entropy-analysis passes (in [1..10]).
   *
   *   int show_compressed;    // if true, export the compressed picture back.
   *                           // In-loop filtering is not applied.
   *   int preprocessing;      // preprocessing filter (0=none, 1=segment-smooth)
   *   int partitions;         // log2(number of token partitions) in [0..3]
   *                           // Default is set to 0 for easier progressive decoding.
   *   int partition_limit;    // quality degradation allowed to fit the 512k limit on
   *                           // prediction modes coding (0: no degradation,
   *                           // 100: maximum possible degradation).
   */

  colormode = VbitmapColormode(vbitmap);

  if (colormode != VBITMAP_COLOR_RGBA && colormode != VBITMAP_COLOR_RGB) {
    ALOGD("currently only support RGB, RGBA webp encoding");
    return rc;
  }

  quality = YmagineFormatOptions_normalizeQuality(options);

  if (!WebPConfigPreset(&config, preset, (float) quality)) {
    return YMAGINE_ERROR;   // version error
  }

  if (options && options->accuracy >= 0) {
    int method = options->accuracy / 15;
    if (method > 6) {
      method = 6;
    }
    config.method = method;
  }

  if (!WebPValidateConfig(&config)) {
    // parameter ranges verification failed
    return YMAGINE_ERROR;
  }

  rc = VbitmapLock(vbitmap);
  if (rc < 0) {
    ALOGE("AndroidBitmap_lockPixels() failed");
    return YMAGINE_ERROR;
  }

  width = VbitmapWidth(vbitmap);
  height = VbitmapHeight(vbitmap);
  pitch = VbitmapPitch(vbitmap);
  pixels = VbitmapBuffer(vbitmap);

  if (WebPPictureInit(&picture)) {
    picture.use_argb = 1;
    picture.width = width;
    picture.height = height;
    picture.writer = WebPYchannelWrite;
    picture.custom_ptr = channelout;

    if (colormode == VBITMAP_COLOR_RGBA) {
      WebPPictureImportRGBA(&picture, pixels, pitch);
    } else {
      WebPPictureImportRGB(&picture, pixels, pitch);
    }

    WebPEncode(&config, &picture);

    WebPPictureFree(&picture);
  }

  VbitmapUnlock(vbitmap);
  rc = YMAGINE_OK;
#endif

  return rc;
}
Example #13
0
GDALDataset *
WEBPDataset::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();

/* -------------------------------------------------------------------- */
/*      WEBP library initialization                                     */
/* -------------------------------------------------------------------- */

    WebPPicture sPicture;
    if (!WebPPictureInit(&sPicture))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureInit() failed");
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Some some rudimentary checks                                    */
/* -------------------------------------------------------------------- */

    if( nXSize > 16383 || nYSize > 16383 )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "WEBP maximum image dimensions are 16383 x 16383.");

        return NULL;
    }

    if( nBands != 3
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
        && nBands != 4
#endif
        )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "WEBP driver doesn't support %d bands. Must be 3 (RGB) "
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
                  "or 4 (RGBA) "
#endif
                  "bands.",
                  nBands );

        return NULL;
    }

    GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();

    if( eDT != GDT_Byte )
    {
        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                  "WEBP driver doesn't support data type %s. "
                  "Only eight bit byte bands supported.",
                  GDALGetDataTypeName(
                      poSrcDS->GetRasterBand(1)->GetRasterDataType()) );

        if (bStrict)
            return NULL;
    }

/* -------------------------------------------------------------------- */
/*      What options has the user selected?                             */
/* -------------------------------------------------------------------- */
    float fQuality = 75.0f;
    const char* pszQUALITY = CSLFetchNameValue(papszOptions, "QUALITY"); 
    if( pszQUALITY != NULL )
    {
        fQuality = (float) CPLAtof(pszQUALITY);
        if( fQuality < 0.0f || fQuality > 100.0f )
        {
            CPLError( CE_Failure, CPLE_IllegalArg,
                      "%s=%s is not a legal value.", "QUALITY", pszQUALITY);
            return NULL;
        }
    }

    WebPPreset nPreset = WEBP_PRESET_DEFAULT;
    const char* pszPRESET = CSLFetchNameValueDef(papszOptions, "PRESET", "DEFAULT");
    if (EQUAL(pszPRESET, "DEFAULT"))
        nPreset = WEBP_PRESET_DEFAULT;
    else if (EQUAL(pszPRESET, "PICTURE"))
        nPreset = WEBP_PRESET_PICTURE;
    else if (EQUAL(pszPRESET, "PHOTO"))
        nPreset = WEBP_PRESET_PHOTO;
    else if (EQUAL(pszPRESET, "PICTURE"))
        nPreset = WEBP_PRESET_PICTURE;
    else if (EQUAL(pszPRESET, "DRAWING"))
        nPreset = WEBP_PRESET_DRAWING;
    else if (EQUAL(pszPRESET, "ICON"))
        nPreset = WEBP_PRESET_ICON;
    else if (EQUAL(pszPRESET, "TEXT"))
        nPreset = WEBP_PRESET_TEXT;
    else
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "%s=%s is not a legal value.", "PRESET", pszPRESET );
        return NULL;
    }

    WebPConfig sConfig;
    if (!WebPConfigInitInternal(&sConfig, nPreset, fQuality, WEBP_ENCODER_ABI_VERSION))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPConfigInit() failed");
        return NULL;
    }


#define FETCH_AND_SET_OPTION_INT(name, fieldname, minval, maxval) \
{ \
    const char* pszVal = CSLFetchNameValue(papszOptions, name); \
    if (pszVal != NULL) \
    { \
        sConfig.fieldname = atoi(pszVal); \
        if (sConfig.fieldname < minval || sConfig.fieldname > maxval) \
        { \
            CPLError( CE_Failure, CPLE_IllegalArg, \
                      "%s=%s is not a legal value.", name, pszVal ); \
            return NULL; \
        } \
    } \
}

    FETCH_AND_SET_OPTION_INT("TARGETSIZE", target_size, 0, INT_MAX);

    const char* pszPSNR = CSLFetchNameValue(papszOptions, "PSNR");
    if (pszPSNR)
    {
        sConfig.target_PSNR = CPLAtof(pszPSNR);
        if (sConfig.target_PSNR < 0)
        {
            CPLError( CE_Failure, CPLE_IllegalArg,
                      "PSNR=%s is not a legal value.", pszPSNR );
            return NULL;
        }
    }

    FETCH_AND_SET_OPTION_INT("METHOD", method, 0, 6);
    FETCH_AND_SET_OPTION_INT("SEGMENTS", segments, 1, 4);
    FETCH_AND_SET_OPTION_INT("SNS_STRENGTH", sns_strength, 0, 100);
    FETCH_AND_SET_OPTION_INT("FILTER_STRENGTH", filter_strength, 0, 100);
    FETCH_AND_SET_OPTION_INT("FILTER_SHARPNESS", filter_sharpness, 0, 7);
    FETCH_AND_SET_OPTION_INT("FILTER_TYPE", filter_type, 0, 1);
    FETCH_AND_SET_OPTION_INT("AUTOFILTER", autofilter, 0, 1);
    FETCH_AND_SET_OPTION_INT("PASS", pass, 1, 10);
    FETCH_AND_SET_OPTION_INT("PREPROCESSING", preprocessing, 0, 1);
    FETCH_AND_SET_OPTION_INT("PARTITIONS", partitions, 0, 3);
#if WEBP_ENCODER_ABI_VERSION >= 0x0002
    FETCH_AND_SET_OPTION_INT("PARTITION_LIMIT", partition_limit, 0, 100);
#endif
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
    sConfig.lossless = CSLFetchBoolean(papszOptions, "LOSSLESS", FALSE);
    if (sConfig.lossless)
        sPicture.use_argb = 1;
#endif

    if (!WebPValidateConfig(&sConfig))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPValidateConfig() failed");
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Allocate memory                                                 */
/* -------------------------------------------------------------------- */
    GByte   *pabyBuffer;

    pabyBuffer = (GByte *) VSIMalloc( nBands * nXSize * nYSize );
    if (pabyBuffer == NULL)
    {
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create the dataset.                                             */
/* -------------------------------------------------------------------- */
    VSILFILE    *fpImage;

    fpImage = VSIFOpenL( pszFilename, "wb" );
    if( fpImage == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Unable to create WEBP file %s.\n",
                  pszFilename );
        VSIFree(pabyBuffer);
        return NULL;
    }

    WebPUserData sUserData;
    sUserData.fp = fpImage;
    sUserData.pfnProgress = pfnProgress ? pfnProgress : GDALDummyProgress;
    sUserData.pProgressData = pProgressData;

/* -------------------------------------------------------------------- */
/*      WEBP library settings                                           */
/* -------------------------------------------------------------------- */

    sPicture.width = nXSize;
    sPicture.height = nYSize;
    sPicture.writer = WEBPDatasetWriter;
    sPicture.custom_ptr = &sUserData;
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
    sPicture.progress_hook = WEBPDatasetProgressHook;
#endif
    if (!WebPPictureAlloc(&sPicture))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureAlloc() failed");
        VSIFree(pabyBuffer);
        VSIFCloseL( fpImage );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Acquire source imagery.                                         */
/* -------------------------------------------------------------------- */
    CPLErr      eErr = CE_None;

    eErr = poSrcDS->RasterIO( GF_Read, 0, 0, nXSize, nYSize,
                              pabyBuffer, nXSize, nYSize, GDT_Byte,
                              nBands, NULL,
                              nBands, nBands * nXSize, 1, NULL );

/* -------------------------------------------------------------------- */
/*      Import and write to file                                        */
/* -------------------------------------------------------------------- */
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
    if (eErr == CE_None && nBands == 4)
    {
        if (!WebPPictureImportRGBA(&sPicture, pabyBuffer, nBands * nXSize))
        {
            CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureImportRGBA() failed");
            eErr = CE_Failure;
        }
    }
    else
#endif
    if (eErr == CE_None &&
        !WebPPictureImportRGB(&sPicture, pabyBuffer, nBands * nXSize))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureImportRGB() failed");
        eErr = CE_Failure;
    }

    if (eErr == CE_None && !WebPEncode(&sConfig, &sPicture))
    {
        const char* pszErrorMsg = NULL;
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
        switch(sPicture.error_code)
        {
            case VP8_ENC_ERROR_OUT_OF_MEMORY: pszErrorMsg = "Out of memory"; break;
            case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY: pszErrorMsg = "Out of memory while flushing bits"; break;
            case VP8_ENC_ERROR_NULL_PARAMETER: pszErrorMsg = "A pointer parameter is NULL"; break;
            case VP8_ENC_ERROR_INVALID_CONFIGURATION: pszErrorMsg = "Configuration is invalid"; break;
            case VP8_ENC_ERROR_BAD_DIMENSION: pszErrorMsg = "Picture has invalid width/height"; break;
            case VP8_ENC_ERROR_PARTITION0_OVERFLOW: pszErrorMsg = "Partition is bigger than 512k. Try using less SEGMENTS, or increase PARTITION_LIMIT value"; break;
            case VP8_ENC_ERROR_PARTITION_OVERFLOW: pszErrorMsg = "Partition is bigger than 16M"; break;
            case VP8_ENC_ERROR_BAD_WRITE: pszErrorMsg = "Error while flusing bytes"; break;
            case VP8_ENC_ERROR_FILE_TOO_BIG: pszErrorMsg = "File is bigger than 4G"; break;
            case VP8_ENC_ERROR_USER_ABORT: pszErrorMsg = "User interrupted"; break;
            default: break;
        }
#endif
        if (pszErrorMsg)
            CPLError(CE_Failure, CPLE_AppDefined, "WebPEncode() failed : %s", pszErrorMsg);
        else
            CPLError(CE_Failure, CPLE_AppDefined, "WebPEncode() failed");
        eErr = CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Cleanup and close.                                              */
/* -------------------------------------------------------------------- */
    CPLFree( pabyBuffer );

    WebPPictureFree(&sPicture);

    VSIFCloseL( fpImage );

    if( eErr != CE_None )
    {
        VSIUnlink( pszFilename );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Re-open dataset, and copy any auxiliary pam information.         */
/* -------------------------------------------------------------------- */
    GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);

    /* If outputing to stdout, we can't reopen it, so we'll return */
    /* a fake dataset to make the caller happy */
    CPLPushErrorHandler(CPLQuietErrorHandler);
    WEBPDataset *poDS = (WEBPDataset*) WEBPDataset::Open( &oOpenInfo );
    CPLPopErrorHandler();
    if( poDS )
    {
        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
        return poDS;
    }

    return NULL;
}
Example #14
0
bool QWebpHandler::write(const QImage &image)
{
    if (image.isNull()) {
        qWarning() << "source image is null.";
        return false;
    }

    QImage srcImage = image;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
    if (srcImage.format() != QImage::Format_ARGB32)
        srcImage = srcImage.convertToFormat(QImage::Format_ARGB32);
#else /* Q_BIG_ENDIAN */
    if (srcImage.format() != QImage::Format_RGBA8888)
        srcImage = srcImage.convertToFormat(QImage::Format_RGBA8888);
#endif

    WebPPicture picture;
    WebPConfig config;

    if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) {
        qWarning() << "failed to init webp picture and config";
        return false;
    }

    picture.width = srcImage.width();
    picture.height = srcImage.height();
    picture.use_argb = 1;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
    if (!WebPPictureImportBGRA(&picture, srcImage.bits(), srcImage.bytesPerLine())) {
#else /* Q_BIG_ENDIAN */
    if (!WebPPictureImportRGBA(&picture, srcImage.bits(), srcImage.bytesPerLine())) {
#endif
        qWarning() << "failed to import image data to webp picture.";

        WebPPictureFree(&picture);
        return false;
    }

    config.lossless = m_lossless;
    config.quality = m_quality;
    picture.writer = pictureWriter;
    picture.custom_ptr = device();

    if (!WebPEncode(&config, &picture)) {
        qWarning() << "failed to encode webp picture, error code: " << picture.error_code;
        WebPPictureFree(&picture);
        return false;
    }

    WebPPictureFree(&picture);

    return true;
}

QVariant QWebpHandler::option(ImageOption option) const
{
    if (!supportsOption(option) || !ensureScanned())
        return QVariant();

    switch (option) {
    case Quality:
        return m_quality;
    case Size:
        return QSize(m_width, m_height);
    case Animation:
        return (m_flags & ANIMATION_FLAG) == ANIMATION_FLAG;
    default:
        return QVariant();
    }
}

void QWebpHandler::setOption(ImageOption option, const QVariant &value)
{
    switch (option) {
    case Quality:
        m_quality = qBound(0, value.toInt(), 100);
        m_lossless = (m_quality >= 100);
        return;
    default:
        break;
    }
    return QImageIOHandler::setOption(option, value);
}

bool QWebpHandler::supportsOption(ImageOption option) const
{
    return option == Quality
        || option == Size
        || option == Animation;
}

QByteArray QWebpHandler::name() const
{
    return QByteArrayLiteral("webp");
}

int QWebpHandler::imageCount() const
{
    if (!ensureScanned())
        return 0;

    if ((m_flags & ANIMATION_FLAG) == 0)
        return 1;

    return m_frameCount;
}

int QWebpHandler::currentImageNumber() const
{
    if (!ensureScanned())
        return 0;

    return m_iter.frame_num;
}

QRect QWebpHandler::currentImageRect() const
{
    if (!ensureScanned())
        return QRect();

    return QRect(m_iter.x_offset, m_iter.y_offset, m_iter.width, m_iter.height);
}

bool QWebpHandler::jumpToImage(int imageNumber)
{
    if (!ensureScanned())
        return false;

    WebPDemuxReleaseIterator(&m_iter);
    return WebPDemuxGetFrame(m_demuxer, imageNumber, &m_iter);
}

bool QWebpHandler::jumpToNextImage()
{
    if (!ensureScanned())
        return false;

    return WebPDemuxNextFrame(&m_iter);
}

int QWebpHandler::loopCount() const
{
    if (!ensureScanned() || (m_flags & ANIMATION_FLAG) == 0)
        return 0;

    return m_loop;
}

int QWebpHandler::nextImageDelay() const
{
    if (!ensureScanned())
        return 0;

    return m_iter.duration;
}
static GstFlowReturn
gst_webp_enc_handle_frame (GstVideoEncoder * encoder,
    GstVideoCodecFrame * frame)
{
  GstWebpEnc *enc = GST_WEBP_ENC (encoder);
  GstBuffer *out_buffer = NULL;
  GstVideoFrame vframe;

  GST_LOG_OBJECT (enc, "got new frame");

  gst_webp_set_picture_params (enc);

  if (!gst_video_frame_map (&vframe, &enc->input_state->info,
          frame->input_buffer, GST_MAP_READ))
    return GST_FLOW_ERROR;

  if (!enc->use_argb) {
    enc->webp_picture.y = GST_VIDEO_FRAME_COMP_DATA (&vframe, 0);
    enc->webp_picture.u = GST_VIDEO_FRAME_COMP_DATA (&vframe, 1);
    enc->webp_picture.v = GST_VIDEO_FRAME_COMP_DATA (&vframe, 2);

    enc->webp_picture.y_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0);
    enc->webp_picture.uv_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 1);

  } else {
    switch (enc->rgb_format) {
      case GST_VIDEO_FORMAT_RGB:
        WebPPictureImportRGB (&enc->webp_picture,
            GST_VIDEO_FRAME_COMP_DATA (&vframe, 0),
            GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0));
        break;
      case GST_VIDEO_FORMAT_RGBA:
        WebPPictureImportRGBA (&enc->webp_picture,
            GST_VIDEO_FRAME_COMP_DATA (&vframe, 0),
            GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0));
        break;
      default:
        break;
    }
  }

  if (WebPEncode (&enc->webp_config, &enc->webp_picture)) {
    WebPPictureFree (&enc->webp_picture);

    out_buffer = gst_buffer_new_allocate (NULL, enc->webp_writer.size, NULL);
    if (!out_buffer) {
      GST_ERROR_OBJECT (enc, "Failed to create output buffer");
      return GST_FLOW_ERROR;
    }
    gst_buffer_fill (out_buffer, 0, enc->webp_writer.mem,
        enc->webp_writer.size);
    free (enc->webp_writer.mem);
  } else {
    GST_ERROR_OBJECT (enc, "Failed to encode WebPPicture");
    return GST_FLOW_ERROR;
  }

  gst_video_frame_unmap (&vframe);
  frame->output_buffer = out_buffer;
  return gst_video_encoder_finish_frame (encoder, frame);
}
Example #16
0
static gboolean
real_save_webp (GdkPixbuf        *pixbuf,
                gchar           **keys,
                gchar           **values,
                GError          **error,
                gboolean          to_callback,
                FILE             *f,
                save_context     *context)
{
        WebPPicture picture;
        WebPConfig config;
        gint w, h, rowstride, has_alpha, rc;
        guchar *pixels;

        if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) {
                g_set_error(error,
                            GDK_PIXBUF_ERROR,
                            GDK_PIXBUF_ERROR_BAD_OPTION,
                            "WebP encoder version mismatch.");
                return FALSE;
        }

        if (keys && *keys) {
                gchar **kiter = keys;
                gchar **viter = values;

                while (*kiter) {
                        if (strncmp (*kiter, "quality", 7) == 0) {
                                float quality = (float) g_ascii_strtod (*viter, NULL);
                                if (quality < 0 || quality > 100) {
                                        g_set_error (error,
                                                     GDK_PIXBUF_ERROR,
                                                     GDK_PIXBUF_ERROR_BAD_OPTION,
                                                     "WebP quality must be a value between 0 and 100.");
                                        return FALSE;
                                }
                                config.quality = quality;
                        } else if (strncmp (*kiter, "preset", 6) == 0) {
                                WebPPreset preset;
                                if (strncmp (*viter, "default", 7) == 0) {
                                        preset = WEBP_PRESET_DEFAULT;
                                } else if (strncmp (*viter, "photo", 5) == 0) {
                                        preset = WEBP_PRESET_PHOTO;
                                } else if (strncmp (*viter, "picture", 7) == 0) {
                                        preset = WEBP_PRESET_PICTURE;
                                } else if (strncmp (*viter, "drawing", 7) == 0) {
                                        preset = WEBP_PRESET_DRAWING;
                                } else if (strncmp (*viter, "icon", 4) == 0) {
                                        preset = WEBP_PRESET_ICON;
                                } else if (strncmp (*viter, "text", 4) == 0) {
                                        preset = WEBP_PRESET_TEXT;
                                } else {
                                        g_set_error (error,
                                                     GDK_PIXBUF_ERROR,
                                                     GDK_PIXBUF_ERROR_BAD_OPTION,
                                                     "WebP encoder invalid preset.");
                                        return FALSE;
                                }
                                if (WebPConfigPreset (&config, preset, config.quality) == 0) {
                                         g_set_error (error,
                                                      GDK_PIXBUF_ERROR,
                                                      GDK_PIXBUF_ERROR_FAILED,
                                                      "Could not initialize decoder with preset.");
                                         return FALSE;
                                }
                        }
                        ++kiter;
                        ++viter;
                }
        }

        if (WebPValidateConfig (&config) != 1) {
                g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_BAD_OPTION,
                             "Invalid encoding configuration");
                return FALSE;
        }

        w = gdk_pixbuf_get_width (pixbuf);
        h = gdk_pixbuf_get_height (pixbuf);
        rowstride = gdk_pixbuf_get_rowstride (pixbuf);
        has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
        pixels = gdk_pixbuf_get_pixels (pixbuf);

        picture.width = w;
        picture.height = h;

        if (has_alpha) {
                rc = WebPPictureImportRGBA (&picture, pixels, rowstride);
        } else {
                rc = WebPPictureImportRGB (&picture, pixels, rowstride);
        }
        if (rc == 0) {
                g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                             "Failed to allocate picture");
                return FALSE;
        }

        if (to_callback) {
                picture.writer = save_callback;
                picture.custom_ptr = (void*) context;
        } else {
                picture.writer = write_file;
                picture.custom_ptr = (void*) f;
        }

        if (WebPEncode(&config, &picture) == 0) {
                fprintf(stderr, "Error! Cannot encode picture as WebP\n");
        }

        return TRUE;
}
status_t
WebPTranslator::_TranslateFromBits(BPositionIO* stream, BMessage* ioExtension,
		uint32 outType, BPositionIO* target)
{
	if (!outType)
		outType = WEBP_IMAGE_FORMAT;
	if (outType != WEBP_IMAGE_FORMAT)
		return B_NO_TRANSLATOR;

	TranslatorBitmap bitsHeader;
	status_t status;

	status = identify_bits_header(stream, NULL, &bitsHeader);
	if (status != B_OK)
		return status;

	if (bitsHeader.colors == B_CMAP8) {
		// TODO: support whatever colospace by intermediate colorspace conversion
		printf("Error! Colorspace not supported\n");
		return B_NO_TRANSLATOR;
	}

	int32 bitsBytesPerPixel = 0;
	switch (bitsHeader.colors) {
		case B_RGB32:
		case B_RGB32_BIG:
		case B_RGBA32:
		case B_RGBA32_BIG:
		case B_CMY32:
		case B_CMYA32:
		case B_CMYK32:
			bitsBytesPerPixel = 4;
			break;

		case B_RGB24:
		case B_RGB24_BIG:
		case B_CMY24:
			bitsBytesPerPixel = 3;
			break;

		case B_RGB16:
		case B_RGB16_BIG:
		case B_RGBA15:
		case B_RGBA15_BIG:
		case B_RGB15:
		case B_RGB15_BIG:
			bitsBytesPerPixel = 2;
			break;

		case B_CMAP8:
		case B_GRAY8:
			bitsBytesPerPixel = 1;
			break;

		default:
			return B_ERROR;
	}

	if (bitsBytesPerPixel < 3) {
		// TODO support
		return B_NO_TRANSLATOR;
	}

	WebPPicture picture;
	WebPConfig config;

	if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) {
		printf("Error! Version mismatch!\n");
  		return B_ERROR;
	}

	WebPPreset preset = (WebPPreset)fSettings->SetGetInt32(WEBP_SETTING_PRESET);
	config.quality = (float)fSettings->SetGetInt32(WEBP_SETTING_QUALITY);

	if (!WebPConfigPreset(&config, (WebPPreset)preset, config.quality)) {
		printf("Error! Could initialize configuration with preset.");
		return B_ERROR;
	}

	config.method = fSettings->SetGetInt32(WEBP_SETTING_METHOD);
	config.preprocessing = fSettings->SetGetBool(WEBP_SETTING_PREPROCESSING);

	if (!WebPValidateConfig(&config)) {
		printf("Error! Invalid configuration.\n");
 		return B_ERROR;
	}

	picture.width = bitsHeader.bounds.IntegerWidth() + 1;
	picture.height = bitsHeader.bounds.IntegerHeight() + 1;

	int stride = bitsHeader.rowBytes;
	int bitsSize = picture.height * stride;
	uint8* bits = (uint8*)malloc(bitsSize);
	if (bits == NULL)
		return B_NO_MEMORY;

	if (stream->Read(bits, bitsSize) != bitsSize) {
		free(bits);
		return B_IO_ERROR;
	}

	if (!WebPPictureImportBGRA(&picture, bits, stride)) {
		printf("Error! WebPEncode() failed!\n");
		free(bits);
		return B_ERROR;
	}
	free(bits);

	picture.writer = _EncodedWriter;
	picture.custom_ptr = target;
	picture.stats = NULL;

	if (!WebPEncode(&config, &picture)) {
		printf("Error! WebPEncode() failed!\n");
		status = B_NO_TRANSLATOR;
	} else
		status = B_OK;

	WebPPictureFree(&picture);
	return status;
}
Example #18
0
static gboolean
_cairo_surface_write_as_webp (cairo_surface_t  *image,
			      char            **buffer,
			      gsize            *buffer_size,
			      char            **keys,
			      char            **values,
			      GError          **error)
{
	gboolean       lossless;
	int            quality;
	int            method;
	WebPConfig     config;
	CairoWebpData *cairo_webp_data;
	WebPPicture    pic;

	lossless = TRUE;
	quality = 75;
	method = 4;

	if (keys && *keys) {
		char **kiter = keys;
		char **viter = values;

		while (*kiter) {
			if (strcmp (*kiter, "lossless") == 0) {
				if (*viter == NULL) {
					g_set_error (error,
						     G_IO_ERROR,
						     G_IO_ERROR_INVALID_DATA,
						     "Must specify a value for the 'lossless' option");
					return FALSE;
				}

				lossless = atoi (*viter);

				if (lossless < 0 || lossless > 1) {
					g_set_error (error,
						     G_IO_ERROR,
						     G_IO_ERROR_INVALID_DATA,
						     "Invalid value set for the 'lossless' option of the WebP saver");
					return FALSE;
				}
			}
			else if (strcmp (*kiter, "quality") == 0) {
				if (*viter == NULL) {
					g_set_error (error,
						     G_IO_ERROR,
						     G_IO_ERROR_INVALID_DATA,
						     "Must specify a quality value to the WebP saver");
					return FALSE;
				}

				quality = atoi (*viter);

				if (quality < 0 || quality > 100) {
					g_set_error (error,
						     G_IO_ERROR,
						     G_IO_ERROR_INVALID_DATA,
						     "Unsupported quality value passed to the WebP saver");
					return FALSE;
				}
			}
			else if (strcmp (*kiter, "method") == 0) {
				if (*viter == NULL) {
					g_set_error (error,
						     G_IO_ERROR,
						     G_IO_ERROR_INVALID_DATA,
						     "Must specify a method value to the WebP saver");
					return FALSE;
				}

				method = atoi (*viter);

				if (method < 0 || method > 6) {
					g_set_error (error,
						     G_IO_ERROR,
						     G_IO_ERROR_INVALID_DATA,
						     "Unsupported method value passed to the WebP saver");
					return FALSE;
				}
			}
			else {
				g_warning ("Bad option name '%s' passed to the WebP saver", *kiter);
				return FALSE;
			}

			++kiter;
			++viter;
		}
	}

	if (! WebPConfigInit (&config)) {
		g_set_error (error,
			     G_IO_ERROR,
			     G_IO_ERROR_INVALID_DATA,
			     "Version error");
		return FALSE;
	}

	config.lossless = lossless;
	config.quality = quality;
	config.method = method;

	if (! WebPValidateConfig (&config)) {
		g_set_error (error,
			     G_IO_ERROR,
			     G_IO_ERROR_INVALID_DATA,
			     "Config error");
		return FALSE;
	}

	cairo_webp_data = g_new0 (CairoWebpData, 1);
	cairo_webp_data->error = error;
	cairo_webp_data->buffer_data = gth_buffer_data_new ();
	cairo_webp_data->success = FALSE;

	WebPPictureInit (&pic);
	pic.width = cairo_image_surface_get_width (image);
	pic.height = cairo_image_surface_get_height (image);
	pic.writer = cairo_webp_writer_func;
	pic.custom_ptr = cairo_webp_data;
	pic.use_argb = TRUE;

	if (_WebPPictureImportCairoSurface (&pic, image)) {
		int ok = WebPEncode (&config, &pic);
		WebPPictureFree (&pic);

		if (cairo_webp_data->success && ! ok) {
			g_set_error (cairo_webp_data->error,
				     G_IO_ERROR,
				     G_IO_ERROR_INVALID_DATA,
				     "Encoding error: %d", pic.error_code);
			cairo_webp_data->success = FALSE;
		}
	}
	else {
		g_set_error (cairo_webp_data->error,
			     G_IO_ERROR,
			     G_IO_ERROR_INVALID_DATA,
			     "Memory error");
		cairo_webp_data->success = FALSE;
	}

	if (cairo_webp_data->success)
		gth_buffer_data_get (cairo_webp_data->buffer_data, buffer, buffer_size);

	_cairo_webp_data_destroy (cairo_webp_data);

	return TRUE;
}
/**
 * Convert bitmap object from Android code to WebP format. Save to file.
 */
jint Java_com_tbliss_android_seniorproject_webpconv_WebPConv_doConvJniGraphics2( JNIEnv* env,
																				 jobject javaThis,
																				 jobject jbitmap,
																				 jfloat jqualityFactor,
																				 jstring filename) 
{
	int ret = 0;
	float cqualityFactor;
	int stride, width, height;
	void* pixels; // pointer to address of bitmap
	int outputSize = 0;
	AndroidBitmapInfo bitmapInfo;
	uint8_t* outputPointer;
	uint8_t* cbitmapPointer;
	WebPConfig config;
	WebPMemoryWriter wrt;
	size_t dataWritten = 0;
	int bytesWritten = 0;
	FILE* fileout = NULL;
	const char* fname	= (*env)->GetStringUTFChars(env, filename, NULL);
	
	// Get Bitmap info (height/width/stride)
	if ((ret = AndroidBitmap_getInfo(env, jbitmap, &bitmapInfo)) < 0){
		LOGV("Could not get Bitmap info. error=%d", ret);
		return 0;
	}
	width = (int)bitmapInfo.width;
	height = (int)bitmapInfo.height;
	stride = (int)bitmapInfo.stride; // width * 4
	LOGV("Bitmap: width=%d, height=%d, stride=%d, format=%d", width, height, stride, bitmapInfo.format);
	
    // Lock Bitmap pixels
	if ((ret = AndroidBitmap_lockPixels(env, jbitmap, &pixels)) < 0) {
     LOGV("AndroidBitmap_lockPixels() failed ! error=%d", ret);
		 return 0;
    }

	cbitmapPointer = (uint8_t*)pixels;
	outputSize = stride * height;
	LOGV("output_size: %d", outputSize);
	outputPointer = (uint8_t*) malloc(outputSize);
	cqualityFactor = (float)jqualityFactor;
	
	// Setup a config
    if (!WebPConfigPreset(&config, WEBP_PRESET_PICTURE, cqualityFactor)) {
	    LOGV("WebPConfigPreset failed");
        return 0;   // version error
    }
    
    // ... additional tuning
	config.method = 1;
	LOGV("config.method = %d", config.method);
    
    if (WebPValidateConfig(&config) != 1) {
	    LOGV("Error with config");
	}

    // Setup the input data
    WebPPicture pic;
    if (!WebPPictureInit(&pic)) {
	    LOGV("WebPPictureInit failed");
        return 0;  // version error
    }

    pic.width = width;
    pic.height = height;
  	
    if (!WebPPictureImportRGBA(&pic, cbitmapPointer, stride)) {
		LOGV("WebPPictureImportRGB failed");
		return 0;
	}
	
    // Set up a byte-output write method. WebPMemoryWriter, for instance.
    pic.writer = MyMemoryWriter;
    pic.custom_ptr = &wrt;
    //InitMemoryWriter(&wrt);
	wrt.mem = &outputPointer;
	wrt.size = &dataWritten;
	wrt.max_size = outputSize;
	
    // Compress!
    ret = WebPEncode(&config, &pic);   // ok = 0 => error occurred!
	if (!ret) {
	    LOGV("ret == 0, WebPEncode fail");
	}
  
    WebPPictureFree(&pic);  // must be called independently of the 'ok' result.

	// Write to phone
	fileout = fopen(fname, "wb");
	if(!fileout){
		LOGV("cannot open output file %s", fname);
		return 0;
	}
	bytesWritten = fwrite(outputPointer, 1, dataWritten, fileout);
	LOGV("bytesWritten: %d", bytesWritten);
	
	// Unlock pixels of Bitmap
	fclose(fileout);
	AndroidBitmap_unlockPixels(env, jbitmap);
	free(outputPointer);
	(*env)->ReleaseStringUTFChars(env, filename, fname);
	
	return dataWritten;
}
Example #20
0
/* Save a layer from an image */
gboolean save_layer(gint32             drawable_ID,
                    WebPWriterFunction writer,
                    void              *custom_ptr,
#ifdef WEBP_0_5
                    gboolean           animation,
                    WebPAnimEncoder   *enc,
                    int                frame_timestamp,
#endif
                    WebPSaveParams    *params,
                    GError           **error)
{
    gboolean          status   = FALSE;
    gint              bpp;
    gint              width;
    gint              height;
    GimpImageType     drawable_type;
    WebPConfig        config;
    WebPPicture       picture;
    guchar           *buffer   = NULL;
#ifdef GIMP_2_9
    GeglBuffer       *geglbuffer;
    GeglRectangle     extent;
#else
    GimpDrawable     *drawable = NULL;
    GimpPixelRgn      region;
#endif

    /* Retrieve the image data */
    bpp = gimp_drawable_bpp(drawable_ID);
    width = gimp_drawable_width(drawable_ID);
    height = gimp_drawable_height(drawable_ID);
    drawable_type = gimp_drawable_type(drawable_ID);

    /* Initialize the WebP configuration with a preset and fill in the
     * remaining values */
    WebPConfigPreset(&config,
                     webp_preset_by_name(params->preset),
                     params->quality);

    config.lossless      = params->lossless;
    config.method        = 6;  /* better quality */
    config.alpha_quality = params->alpha_quality;

    /* Prepare the WebP structure */
    WebPPictureInit(&picture);
    picture.use_argb      = 1;
    picture.width         = width;
    picture.height        = height;
    picture.writer        = writer;
    picture.custom_ptr    = custom_ptr;
    picture.progress_hook = webp_file_progress;

    do {
        /* Attempt to allocate a buffer of the appropriate size */
        buffer = (guchar *)g_malloc(bpp * width * height);
        if(!buffer) {
            g_set_error(error,
                        G_FILE_ERROR,
                        0,
                        "Unable to allocate buffer for layer");
            break;
        }

#ifdef GIMP_2_9
        /* Obtain the buffer and get its extent */
        geglbuffer = gimp_drawable_get_buffer(drawable_ID);
        extent = *gegl_buffer_get_extent(geglbuffer);

        /* Read the layer buffer into our buffer */
        gegl_buffer_get(geglbuffer, &extent, 1.0, NULL, buffer,
                        GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

        g_object_unref(geglbuffer);
#else
        /* Get the drawable */
        drawable = gimp_drawable_get(drawable_ID);

        /* Obtain the pixel region for the drawable */
        gimp_pixel_rgn_init(&region,
                            drawable,
                            0, 0,
                            width,
                            height,
                            FALSE, FALSE);

        /* Read the region into the buffer */
        gimp_pixel_rgn_get_rect(&region,
                                buffer,
                                0, 0,
                                width,
                                height);

        gimp_drawable_detach(drawable);
#endif

        /* Use the appropriate function to import the data from the buffer */
        if(drawable_type == GIMP_RGB_IMAGE) {
            WebPPictureImportRGB(&picture, buffer, width * bpp);
        } else {
            WebPPictureImportRGBA(&picture, buffer, width * bpp);
        }

#ifdef WEBP_0_5
        if (animation == TRUE) {

            if (!WebPAnimEncoderAdd(enc, &picture, frame_timestamp, &config)) {
                g_set_error(error,
                            G_FILE_ERROR,
                            picture.error_code,
                            "WebP error: '%s'",
                            webp_error_string(picture.error_code));
                break;
            }
        } else {
#endif
            if(!WebPEncode(&config, &picture)) {
                g_set_error(error,
                            G_FILE_ERROR,
                            picture.error_code,
                            "WebP error: '%s'",
                            webp_error_string(picture.error_code));
                break;
            }
#ifdef WEBP_0_5
        }
#endif

        /* Everything succeeded */
        status = TRUE;

    } while(0);

    /* Free the buffer */
    if (buffer) {
        free(buffer);
    }

    return status;
}