Esempio n. 1
1
bool
WebpInput::open (const std::string &name, ImageSpec &spec)
{
    m_filename = name;

    m_file = Filesystem::fopen(m_filename, "rb");
    if (!m_file)
    {
        error ("Could not open file \"%s\"", m_filename.c_str());
        return false;
    }

    fseek (m_file, 0, SEEK_END);
    m_image_size = ftell(m_file);
    fseek (m_file, 0, SEEK_SET);

    std::vector<uint8_t> encoded_image;
    encoded_image.resize(m_image_size, 0);
    size_t numRead = fread(&encoded_image[0], sizeof(uint8_t), encoded_image.size(), m_file);
    if (numRead != encoded_image.size()) {
    	error ("Read failure for \"%s\" (expected %d bytes, read %d)",
               m_filename, encoded_image.size(), numRead);
    	close ();
    	return false;
    }

    int width = 0, height = 0;
    if(!WebPGetInfo(&encoded_image[0], encoded_image.size(), &width, &height))
    {
        error ("%s is not a WebP image file", m_filename.c_str());
        close();
        return false;
    }

    const int CHANNEL_NUM = 4;
    m_scanline_size = width * CHANNEL_NUM;
    m_spec = ImageSpec(width, height, CHANNEL_NUM, TypeDesc::UINT8);
    spec = m_spec;

    if (!(m_decoded_image = WebPDecodeRGBA(&encoded_image[0], encoded_image.size(), &m_spec.width, &m_spec.height)))
    {
        error ("Couldn't decode %s", m_filename.c_str());
        close();
        return false;
    }
    return true;
}
Esempio n. 2
0
void LoadWEBP(const char *filename, unsigned char **pic, int *width, int *height, byte alphaByte)
{
	byte           *out;
	int             len;
	int		stride;
	int		size;
	union
	{
		byte           *b;
		void           *v;
	} fbuffer;

	/* read compressed data */
	len = ri.FS_ReadFile((char *)filename, &fbuffer.v);
	if(!fbuffer.b || len < 0)
	{
		return;
	}

	/* validate data and query image size */
	if( !WebPGetInfo( fbuffer.b, len, width, height ) )
		return;

	stride = *width * sizeof( color4ub_t );
	size = *height * stride;

	out = ri.Z_Malloc( size );
	if( !WebPDecodeRGBAInto( fbuffer.b, len, out, size, stride ) ) {
		ri.Free( out );
		return;
	}

	ri.FS_FreeFile(fbuffer.v);
	*pic = out;
}
Esempio n. 3
0
SWIGEXPORT jint JNICALL Java_com_google_webp_libwebpJNI_WebPGetInfo(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jintArray jarg3, jintArray jarg4) {
  jint jresult = 0 ;
  uint8_t *arg1 = (uint8_t *) 0 ;
  uint32_t arg2 ;
  int *arg3 = (int *) 0 ;
  int *arg4 = (int *) 0 ;
  jbyte *jarr1 ;
  int temp3 ;
  int temp4 ;
  int result;

  (void)jenv;
  (void)jcls;
  if (!SWIG_JavaArrayInSchar(jenv, &jarr1, &arg1, jarg1)) return 0;
  arg2 = (uint32_t)jarg2;
  {
    if (!jarg3) {
      SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
      return 0;
    }
    if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) {
      SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
      return 0;
    }
    arg3 = &temp3;
  }
  {
    if (!jarg4) {
      SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
      return 0;
    }
    if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) {
      SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
      return 0;
    }
    arg4 = &temp4;
  }
  {
    if (arg2 < 0) {
      {
        SWIG_JavaException(jenv, SWIG_ValueError, "Expected a non-negative value."); return 0;
      };
    }
  }
  result = (int)WebPGetInfo((uint8_t const *)arg1,arg2,arg3,arg4);
  jresult = (jint)result;
  SWIG_JavaArrayArgoutSchar(jenv, jarr1, arg1, jarg1);
  {
    jint jvalue = (jint)temp3;
    (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue);
  }
  {
    jint jvalue = (jint)temp4;
    (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue);
  }
  free(arg1);


  return jresult;
}
Esempio n. 4
0
int webp_get_info(const uint8_t* data, size_t data_size, int* width, int* height) {
  if (WebPGetInfo(data, data_size, width, height) == 1) {
    return 0;
  } else {
    return 1;
  }
}
Esempio n. 5
0
static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data,
                       size_t data_size, int* const width, int* const height,
                       WebPDecBuffer* const keep_info) {
  WebPDecParams params;
  WebPDecBuffer output;

  WebPInitDecBuffer(&output);
  WebPResetDecParams(&params);
  params.output = &output;
  output.colorspace = mode;

  // Retrieve (and report back) the required dimensions from bitstream.
  if (!WebPGetInfo(data, data_size, &output.width, &output.height)) {
    return NULL;
  }
  if (width != NULL) *width = output.width;
  if (height != NULL) *height = output.height;

  // Decode
  if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
    return NULL;
  }
  if (keep_info != NULL) {    // keep track of the side-info
    WebPCopyDecBuffer(&output, keep_info);
  }
  // return decoded samples (don't clear 'output'!)
  return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y;
}
Esempio n. 6
0
static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data,
                       size_t data_size, int* const width, int* const height,
                       WebPDecBuffer* const keep_info) {
  WebPDecParams params;
  WebPDecBuffer output;

  WebPInitDecBuffer(&output);
  WebPResetDecParams(&params);
  params.output = &output;
  output.colorspace = mode;

  
  if (!WebPGetInfo(data, data_size, &output.width, &output.height)) {
    return NULL;
  }
  if (width != NULL) *width = output.width;
  if (height != NULL) *height = output.height;

  
  if (DecodeInto(data, data_size, &params) != VP8_STATUS_OK) {
    return NULL;
  }
  if (keep_info != NULL) {    
    WebPCopyDecBuffer(&output, keep_info);
  }
  
  return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y;
}
Esempio n. 7
0
int
vips__iswebp_buffer( const void *buf, size_t len )
{
	if( len >= MINIMAL_HEADER &&
		WebPGetInfo( buf, MINIMAL_HEADER, NULL, NULL ) )
		return( 1 );

	return( 0 );
}
Esempio n. 8
0
char load(ImlibImage * im, ImlibProgressFunction progress,
          char progress_granularity, char immediate_load)
{
  uint8_t *data;
  size_t size;
  int w,h;
  int has_alpha;
#if (WEBP_DECODER_ABI_VERSION >= 0x200)
  WebPBitstreamFeatures features;
#endif
  char ret = 0;

  if(im->data)
    return 0;

  if(!(data = read_file(im->real_file, &size, progress)))
    return 0;

#if (WEBP_DECODER_ABI_VERSION >= 0x200)
  if(WebPGetFeatures(data, size, &features) != VP8_STATUS_OK)
    goto EXIT;
  w = features.width;
  h = features.height;
  has_alpha = features.has_alpha;
#else /* compatibility with versions <= 0.1.3 */
  if (!WebPGetInfo(data, size, &w, &h))
    goto EXIT;
  has_alpha = 0;
#endif

  if(!im->loader && !im->data) {
    im->w = w;
    im->h = h;

    if(!IMAGE_DIMENSIONS_OK(w, h))
      goto EXIT;

    if(!has_alpha)
      UNSET_FLAGS(im->flags, F_HAS_ALPHA);
    else
      SET_FLAGS(im->flags, F_HAS_ALPHA);
    im->format = strdup("webp");
  }

  if((!im->data && im->loader) || immediate_load || progress)
     im->data = (DATA32*)WebPDecodeBGRA(data, size, &w, &h);

  if(progress)
    progress(im, 100, 0, 0, 0, 0);

  ret = 1;

EXIT:
  free(data);
  return ret;
}
//{ Draw
void image_load(img_t *img,BYTE *data,int sz)
{
    BYTE *bits,*p1,*p2;
    BITMAPINFO bmi;
    int ret;
    int i;

    img->hasalpha=img->sx=img->sy=0;
#ifdef CONSOLE_MODE
    return;
#else
    ret=WebPGetInfo((PBYTE)data,sz,&img->sx,&img->sy);
    if(!ret)
    {
        log_err("ERROR in image_load(): failed WebPGetInfo\n");
        return;
    }
    img->big=WebPDecodeBGRA((PBYTE)data,sz,&img->sx,&img->sy);
    if(!img->big)
    {
        log_err("ERROR in image_load(): failed WebPDecodeBGRA\n");
        return;
    }
#endif

    ZeroMemory(&bmi,sizeof(BITMAPINFO));
    bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth=img->sx;
    bmi.bmiHeader.biHeight=-img->sy;
    bmi.bmiHeader.biPlanes=1;
    bmi.bmiHeader.biBitCount=32;
    bmi.bmiHeader.biCompression=BI_RGB;
    bmi.bmiHeader.biSizeImage=img->sx*img->sy*4;

    img->dc=CreateCompatibleDC(0);
    img->bitmap=CreateDIBSection(img->dc,&bmi,DIB_RGB_COLORS,(void *)&bits,0,0);
    SelectObject(img->dc,img->bitmap);

    p1=bits;p2=img->big;
    for(i=0;i<img->sx*img->sy;i++)
    {
        BYTE B,G,R,A;
        B=*p2++;
        G=*p2++;
        R=*p2++;
        A=*p2++;
        double dA=A/255.;
        if(A!=255)img->hasalpha=1;

        *p1++=(BYTE)(B*dA);
        *p1++=(BYTE)(G*dA);
        *p1++=(BYTE)(R*dA);
        *p1++=A;
    }
    //log_con("%dx%d:%d,%d\n",img->sx,img->sy,img->hasalpha,img->index);
}
Esempio n. 10
0
void webp_reader<T>::init()
{
    int width, height;
    if (!WebPGetInfo(buffer_->data(), buffer_->size(), &width, &height))
    {
        throw image_reader_exception("WEBP reader: WebPGetInfo failed");
    }
    width_ = width;
    height_ = height;
}
Esempio n. 11
0
int
vips__iswebp( const char *filename )
{
	unsigned char header[MINIMAL_HEADER];

	if( vips__get_bytes( filename, header, MINIMAL_HEADER ) &&
		WebPGetInfo( header, MINIMAL_HEADER, NULL, NULL ) )
		return( 1 );

	return( 0 );
}
Esempio n. 12
0
bool WebPDecoder::readHeader()
{
    if (m_buf.empty())
    {
        FILE * wfile = NULL;

        wfile = fopen(m_filename.c_str(), "rb");

        if(wfile == NULL)
        {
            return false;
        }

        fseek(wfile, 0, SEEK_END);
        size_t wfile_size = ftell(wfile);
        fseek(wfile, 0, SEEK_SET);

        if(wfile_size > (size_t)INT_MAX)
        {
            fclose(wfile);
            return false;
        }

        data.create(1, (int)wfile_size, CV_8U);

        size_t data_size = fread(data.data, 1, wfile_size, wfile);

        if(wfile)
        {
            fclose(wfile);
        }

        if( data_size < wfile_size )
        {
            return false;
        }
    }
    else
    {
        data = m_buf;
    }

    if(WebPGetInfo(data.data, data.total(), &m_width, &m_height) == 1)
    {
        m_type = CV_8UC3;
        return true;
    }

    return false;
}
Esempio n. 13
0
bool WEBPImageDecoder::decode(bool onlySize)
{
    // Minimum number of bytes needed to ensure one can parse size information.
    static const size_t sizeOfHeader = 30;
    // Number of bytes per pixel.
    static const int bytesPerPixel = 3;

    if (failed())
        return false;
    const size_t dataSize = m_data->buffer().size();
    const uint8_t* dataBytes =
        reinterpret_cast<const uint8_t*>(m_data->buffer().data());
    int width, height;
    if (dataSize < sizeOfHeader)
        return true;
    if (!WebPGetInfo(dataBytes, dataSize, &width, &height))
        return setFailed();
    if (!ImageDecoder::isSizeAvailable() && !setSize(width, height))
        return setFailed();
    if (onlySize)
        return true;

    // FIXME: Add support for progressive decoding.
    if (!isAllDataReceived())
        return true;
    ASSERT(!m_frameBufferCache.isEmpty());
    RGBA32Buffer& buffer = m_frameBufferCache[0];
    if (buffer.status() == RGBA32Buffer::FrameEmpty) {
        ASSERT(width == size().width());
        ASSERT(height == size().height());
        if (!buffer.setSize(width, height))
            return setFailed();
    }
    const int stride = width * bytesPerPixel;
    Vector<uint8_t> rgb;
    rgb.resize(height * stride);
    if (!WebPDecodeBGRInto(dataBytes, dataSize, rgb.data(), rgb.size(), stride))
        return setFailed();
    // FIXME: remove this data copy.
    for (int y = 0; y < height; ++y) {
        const uint8_t* const src = &rgb[y * stride];
        for (int x = 0; x < width; ++x)
            buffer.setRGBA(x, y, src[bytesPerPixel * x + 2], src[bytesPerPixel * x + 1], src[bytesPerPixel * x + 0], 0xff);
    }
    buffer.setStatus(RGBA32Buffer::FrameComplete);
    buffer.setHasAlpha(false);
    buffer.setRect(IntRect(IntPoint(), size()));
    return true;
}
Esempio n. 14
0
PremultipliedImage decodeWebP(const uint8_t* data, size_t size) {
    int width = 0, height = 0;
    if (WebPGetInfo(data, size, &width, &height) == 0) {
        throw std::runtime_error("failed to retrieve WebP basic header information");
    }

    int stride = width * 4;
    size_t webpSize = stride * height;
    auto webp = std::make_unique<uint8_t[]>(webpSize);

    if (!WebPDecodeRGBAInto(data, size, webp.get(), webpSize, stride)) {
        throw std::runtime_error("failed to decode WebP data");
    }

    UnassociatedImage image { size_t(width), size_t(height), std::move(webp) };
    return util::premultiply(std::move(image));
}
Esempio n. 15
0
std::auto_ptr<Image> WebPFormat::read(byte_source* src, ImageFactory* factory, const options_map& opts) {
    std::vector<byte> data = full_data(*src);
    int w, h;
    int ok = WebPGetInfo(&data[0], data.size(), &w, &h);
    if (!ok) {
        throw CannotReadError("imread.imread._webp: File does not validate as WebP");
    }
    std::auto_ptr<Image> output(factory->create(8, h, w, 4));
    const int stride = w*4;
    const uint8_t* p = WebPDecodeRGBAInto(
            &data[0], data.size(),
            output->rowp_as<byte>(0), h*stride, stride);
    if (p != output->rowp_as<uint8_t>(0)) {
        throw CannotReadError("imread.imread._webp: Error in decoding file");
    }

    return output;
}
Esempio n. 16
0
cairo_surface_t* guacenc_webp_decoder(unsigned char* data, int length) {

    int width, height;

    /* Validate WebP and pull dimensions */
    if (!WebPGetInfo((uint8_t*) data, length, &width, &height)) {
        guacenc_log(GUAC_LOG_WARNING, "Invalid WebP data");
        return NULL;
    }

    /* Create blank Cairo surface */
    cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
            width, height);

    /* Fill surface with opaque black */
    cairo_t* cairo = cairo_create(surface);
    cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
    cairo_set_source_rgba(cairo, 0.0, 0.0, 0.0, 1.0);
    cairo_paint(cairo);
    cairo_destroy(cairo);

    /* Finish any pending draws */
    cairo_surface_flush(surface);

    /* Pull underlying buffer and its stride */
    int stride = cairo_image_surface_get_stride(surface);
    unsigned char* image = cairo_image_surface_get_data(surface);

    /* Read WebP into surface */
    uint8_t* result = WebPDecodeBGRAInto((uint8_t*) data, length,
            (uint8_t*) image, stride * height, stride);

    /* Verify WebP was successfully decoded */
    if (result == NULL) {
        guacenc_log(GUAC_LOG_WARNING, "Invalid WebP data");
        cairo_surface_destroy(surface);
        return NULL;
    }

    /* WebP was read successfully */
    return surface;

}
Esempio n. 17
0
Bitmap *ImageFromData(const char *data, size_t len)
{
    int w, h;
    if (!WebPGetInfo((const uint8_t *)data, len, &w, &h))
        return nullptr;

    Bitmap bmp(w, h, PixelFormat32bppARGB);
    Rect bmpRect(0, 0, w, h);
    BitmapData bmpData;
    Status ok = bmp.LockBits(&bmpRect, ImageLockModeWrite, PixelFormat32bppARGB, &bmpData);
    if (ok != Ok)
        return nullptr;
    if (!WebPDecodeBGRAInto((const uint8_t *)data, len, (uint8_t *)bmpData.Scan0, bmpData.Stride * h, bmpData.Stride))
        return nullptr;
    bmp.UnlockBits(&bmpData);

    // hack to avoid the use of ::new (because there won't be a corresponding ::delete)
    return bmp.Clone(0, 0, w, h, PixelFormat32bppARGB);
}
Esempio n. 18
0
static gboolean
gdk_pixbuf__webp_image_load_increment (gpointer context,
                                       const guchar *buf, guint size,
                                       GError **error)
{
        gint w, h, stride;
        WebPContext *data = (WebPContext *) context;
        g_return_val_if_fail(data != NULL, FALSE);

        if (!data->got_header) {
                gint rc;
                rc = WebPGetInfo (buf, size, &w, &h);
                if (rc == 0) {
                        g_set_error (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     "Cannot read WebP image header.");
                        return FALSE;
                }
                stride = w * 3;  /* TODO Update when alpha support released */
                data->got_header = TRUE;
                if (data->size_func) {
                        (* data->size_func) (&w, &h,
                                             data->user_data);
                }
                data->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
                                               FALSE,
                                               8,
                                               w,
                                               h);
                data->decbuf = g_try_malloc (h * stride);
                if (!data->decbuf) {
                        g_set_error (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     "Cannot allocate memory for decoded image data.");
                        return FALSE;
                }
                data->idec = WebPINewRGB (MODE_RGB,
                                          data->decbuf,
                                          h * stride,
                                          stride);
                if (!data->idec) {
                        g_set_error (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_FAILED,
                                     "Cannot create WebP decoder.");
                        return FALSE;
                }
                if (data->prepare_func) {
                        (* data->prepare_func) (data->pixbuf,
                                                NULL,
                                                data->user_data);
                }
        }

        /* Append size bytes to decoder's buffer */
        const VP8StatusCode status = WebPIAppend (data->idec, buf, size);
        if (status != VP8_STATUS_SUSPENDED && status != VP8_STATUS_OK) {
                g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                             "WebP decoder failed with status code %d.",
                             status);
                return FALSE;
        }

        /* Decode decoder's updated buffer */
        guint8 *dec_output;
        dec_output = WebPIDecGetRGB (data->idec, &data->last_y, &w, &h, &stride);
        if (dec_output == NULL && status != VP8_STATUS_SUSPENDED) {
                g_set_error(error,
                            GDK_PIXBUF_ERROR,
                            GDK_PIXBUF_ERROR_FAILED,
                            "Bad inputs to WebP decoder.");
                return FALSE;
        }

        /* Copy decoder output to pixbuf */
        gint y, row;
        guchar *dptr;
        dptr = gdk_pixbuf_get_pixels (data->pixbuf);
        const guint8 offset = w % 4;  /* decoded width will be divisible by 4 */
        for (y = 0; y < data->last_y; ++y, dptr += offset) {
                row = y * stride;
                g_memmove (dptr + row, dec_output + row, stride);
        }

        if (data->update_func) {
                (* data->update_func) (data->pixbuf, 0, 0,
                                       w,
                                       data->last_y,
                                       data->user_data);
        }
        return TRUE;
}
Esempio n. 19
0
bool WEBPImageDecoder::decode(bool onlySize)
{
    if (failed())
        return false;

    const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(m_data->data());
    const size_t dataSize = m_data->size();

    if (!ImageDecoder::isSizeAvailable()) {
        static const size_t imageHeaderSize = 30;
        if (dataSize < imageHeaderSize)
            return false;
        int width, height;
#ifdef QCMS_WEBP_COLOR_CORRECTION
        WebPData inputData = { dataBytes, dataSize };
        WebPDemuxState state;
        WebPDemuxer* demuxer = WebPDemuxPartial(&inputData, &state);
        if (!demuxer)
            return setFailed();

        width = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_WIDTH);
        height = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_HEIGHT);
        m_formatFlags = WebPDemuxGetI(demuxer, WEBP_FF_FORMAT_FLAGS);
        m_hasAlpha = !!(m_formatFlags & ALPHA_FLAG);

        WebPDemuxDelete(demuxer);
        if (state <= WEBP_DEMUX_PARSING_HEADER)
            return false;
#elif (WEBP_DECODER_ABI_VERSION >= 0x0163)
        WebPBitstreamFeatures features;
        if (WebPGetFeatures(dataBytes, dataSize, &features) != VP8_STATUS_OK)
            return setFailed();
        width = features.width;
        height = features.height;
        m_hasAlpha = features.has_alpha;
#else
        // Earlier version won't be able to display WebP files with alpha.
        if (!WebPGetInfo(dataBytes, dataSize, &width, &height))
            return setFailed();
        m_hasAlpha = false;
#endif
        if (!setSize(width, height))
            return setFailed();
    }

    ASSERT(ImageDecoder::isSizeAvailable());
    if (onlySize)
        return true;

    ASSERT(!m_frameBufferCache.isEmpty());
    ImageFrame& buffer = m_frameBufferCache[0];
    ASSERT(buffer.status() != ImageFrame::FrameComplete);

    if (buffer.status() == ImageFrame::FrameEmpty) {
        if (!buffer.setSize(size().width(), size().height()))
            return setFailed();
        buffer.setStatus(ImageFrame::FramePartial);
        buffer.setHasAlpha(m_hasAlpha);
        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
    }

    if (!m_decoder) {
        WEBP_CSP_MODE mode = outputMode(m_hasAlpha);
        if (!m_premultiplyAlpha)
            mode = outputMode(false);
        if ((m_formatFlags & ICCP_FLAG) && !ignoresGammaAndColorProfile())
            mode = MODE_RGBA; // Decode to RGBA for input to libqcms.
        int rowStride = size().width() * sizeof(ImageFrame::PixelData);
        uint8_t* output = reinterpret_cast<uint8_t*>(buffer.getAddr(0, 0));
        int outputSize = size().height() * rowStride;
        m_decoder = WebPINewRGB(mode, output, outputSize, rowStride);
        if (!m_decoder)
            return setFailed();
    }

    switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) {
    case VP8_STATUS_OK:
        if ((m_formatFlags & ICCP_FLAG) && !ignoresGammaAndColorProfile()) 
            applyColorProfile(dataBytes, dataSize, buffer);
        buffer.setStatus(ImageFrame::FrameComplete);
        clear();
        return true;
    case VP8_STATUS_SUSPENDED:
        if ((m_formatFlags & ICCP_FLAG) && !ignoresGammaAndColorProfile()) 
            applyColorProfile(dataBytes, dataSize, buffer);
        return false;
    default:
        clear();                         
        return setFailed();
    }
}
Esempio n. 20
0
SDL_Surface *IMG_LoadWEBP_RW(SDL_RWops *src)
{
    Sint64 start;
    const char *error = NULL;
    SDL_Surface *volatile surface = NULL;
    Uint32 Rmask;
    Uint32 Gmask;
    Uint32 Bmask;
    Uint32 Amask;
    WebPBitstreamFeatures features;
    int raw_data_size;
    uint8_t *raw_data = NULL;
    int r;
    uint8_t *ret;

    if ( !src ) {
        /* The error message has been set in SDL_RWFromFile */
        return NULL;
    }

    start = SDL_RWtell(src);

    if ( !IMG_Init(IMG_INIT_WEBP) ) {
        goto error;
    }

    raw_data_size = -1;
    if ( !webp_getinfo( src, &raw_data_size ) ) {
        error = "Invalid WEBP";
        goto error;
    }

    // seek to start of file
    SDL_RWseek(src, 0, RW_SEEK_SET );

    raw_data = (uint8_t*) SDL_malloc( raw_data_size );
    if ( raw_data == NULL ) {
        error = "Failed to allocate enought buffer for WEBP";
        goto error;
    }

    r = SDL_RWread(src, raw_data, 1, raw_data_size );
    if ( r != raw_data_size ) {
        error = "Failed to read WEBP";
        goto error;
    }

#if 0
    // extract size of picture, not interesting since we don't know about alpha channel
    int width = -1, height = -1;
    if ( !WebPGetInfo( raw_data, raw_data_size, &width, &height ) ) {
        printf("WebPGetInfo has failed\n" );
        return NULL;
    }
#endif

    if ( lib.webp_get_features_internal( raw_data, raw_data_size, &features, WEBP_DECODER_ABI_VERSION ) != VP8_STATUS_OK ) {
        error = "WebPGetFeatures has failed";
        goto error;
    }

    /* Check if it's ok !*/
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
    Rmask = 0x000000FF;
    Gmask = 0x0000FF00;
    Bmask = 0x00FF0000;
    Amask = (features.has_alpha) ? 0xFF000000 : 0;
#else
    s = (features.has_alpha) ? 0 : 8;
    Rmask = 0xFF000000 >> s;
    Gmask = 0x00FF0000 >> s;
    Bmask = 0x0000FF00 >> s;
    Amask = 0x000000FF >> s;
#endif

    surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
            features.width, features.height,
            features.has_alpha?32:24, Rmask,Gmask,Bmask,Amask);

    if ( surface == NULL ) {
        error = "Failed to allocate SDL_Surface";
        goto error;
    }

    if ( features.has_alpha ) {
        ret = lib.webp_decode_rgba_into( raw_data, raw_data_size, (uint8_t *)surface->pixels, surface->pitch * surface->h,  surface->pitch );
    } else {
        ret = lib.webp_decode_rgb_into( raw_data, raw_data_size, (uint8_t *)surface->pixels, surface->pitch * surface->h,  surface->pitch );
    }

    if ( !ret ) {
        error = "Failed to decode WEBP";
        goto error;
    }

    return surface;


error:

    if ( surface ) {
        SDL_FreeSurface( surface );
    }

    if ( raw_data ) {
        SDL_free( raw_data );
    }

    if ( error ) {
        IMG_SetError( error );
    }

    SDL_RWseek(src, start, RW_SEEK_SET);
    return(NULL);
}
Esempio n. 21
0
bool WEBPImageDecoder::decode(bool onlySize)
{
    if (failed())
        return false;

#if defined(__LB_SHELL__)
    // We dont want progressive decoding.
    if (!isAllDataReceived())
        return false;
#endif

    const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(m_data->data());
    const size_t dataSize = m_data->size();

    if (!ImageDecoder::isSizeAvailable()) {
        static const size_t imageHeaderSize = 30;
        if (dataSize < imageHeaderSize)
            return false;
        int width, height;
#if (WEBP_DECODER_ABI_VERSION >= 0x0163)
        WebPBitstreamFeatures features;
        if (WebPGetFeatures(dataBytes, dataSize, &features) != VP8_STATUS_OK)
            return setFailed();
        width = features.width;
        height = features.height;
        m_hasAlpha = features.has_alpha;
#else
        // Earlier version won't be able to display WebP files with alpha.
        if (!WebPGetInfo(dataBytes, dataSize, &width, &height))
            return setFailed();
        m_hasAlpha = false;
#endif
        if (!setSize(width, height))
            return setFailed();
    }

    ASSERT(ImageDecoder::isSizeAvailable());
    if (onlySize)
        return true;

    ASSERT(!m_frameBufferCache.isEmpty());
    ImageFrame& buffer = m_frameBufferCache[0];
    ASSERT(buffer.status() != ImageFrame::FrameComplete);

    if (buffer.status() == ImageFrame::FrameEmpty) {
        if (!buffer.setSize(size().width(), size().height()))
            return setFailed();
        buffer.setStatus(ImageFrame::FramePartial);
        buffer.setHasAlpha(m_hasAlpha);
        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
    }

    if (!m_decoder) {
        int rowStride = size().width() * sizeof(ImageFrame::PixelData);
        uint8_t* output = reinterpret_cast<uint8_t*>(buffer.getAddr(0, 0));
        int outputSize = size().height() * rowStride;
        m_decoder = WebPINewRGB(outputMode(m_hasAlpha), output, outputSize, rowStride);
        if (!m_decoder)
            return setFailed();
    }

    switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) {
    case VP8_STATUS_OK:
        buffer.setStatus(ImageFrame::FrameComplete);
        WebPIDelete(m_decoder);
        m_decoder = 0;
        return true;
    case VP8_STATUS_SUSPENDED:
        return false;
    default:
        WebPIDelete(m_decoder);
        m_decoder = 0;
        return setFailed();
    }
}
Esempio n. 22
0
bool WEBPImageDecoder::decode(bool onlySize)
{
    // Minimum number of bytes needed to ensure one can parse size information.
    static const size_t sizeOfHeader = 30;
    // Number of bytes per pixel.
    static const int bytesPerPixel = 3;

    if (failed())
        return false;

    const size_t dataSize = m_data->size();
    if (dataSize < sizeOfHeader)
        return true;

    int width, height;
    const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(m_data->data());
    if (!WebPGetInfo(dataBytes, dataSize, &width, &height))
        return setFailed();
    if (!ImageDecoder::isSizeAvailable() && !setSize(width, height))
        return setFailed();
    if (onlySize)
        return true;

    bool allDataReceived = isAllDataReceived();
    int stride = width * bytesPerPixel;
    ASSERT(!m_frameBufferCache.isEmpty());
    ImageFrame& buffer = m_frameBufferCache[0];
    if (buffer.status() == ImageFrame::FrameEmpty) {
        ASSERT(width == size().width());
        ASSERT(height == size().height());
        if (!buffer.setSize(width, height))
            return setFailed();
        buffer.setStatus(allDataReceived ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
        // FIXME: We currently hard code false below because libwebp doesn't support alpha yet.
        buffer.setHasAlpha(false);
        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
        m_rgbOutput.resize(height * stride);
    }
    int newLastVisibleRow = 0; // Last completed row.
    if (allDataReceived) {
        if (!WebPDecodeRGBInto(dataBytes, dataSize, m_rgbOutput.data(), m_rgbOutput.size(), stride))
            return setFailed();
        newLastVisibleRow = height;
    } else {
        if (!m_decoder) {
            m_decoder = WebPINewRGB(MODE_RGB, m_rgbOutput.data(), m_rgbOutput.size(), stride);
            if (!m_decoder)
                return setFailed();
        }
        const VP8StatusCode status = WebPIUpdate(m_decoder, dataBytes, dataSize);
        if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED)
            return setFailed();
        if (!WebPIDecGetRGB(m_decoder, &newLastVisibleRow, 0, 0, 0))
            return setFailed();
        ASSERT(newLastVisibleRow >= 0);
        ASSERT(newLastVisibleRow <= height);
    }
    // FIXME: remove this data copy.
    for (int y = m_lastVisibleRow; y < newLastVisibleRow; ++y) {
        const uint8_t* const src = &m_rgbOutput[y * stride];
        for (int x = 0; x < width; ++x)
            buffer.setRGBA(x, y, src[bytesPerPixel * x + 0], src[bytesPerPixel * x + 1], src[bytesPerPixel * x + 2], 0xff);
    }
    m_lastVisibleRow = newLastVisibleRow;
    if (m_lastVisibleRow == height)
         buffer.setStatus(ImageFrame::FrameComplete);
    return m_lastVisibleRow == height;
}
static jobject WebPFactory_decodeBuffer
  (JNIEnv *jniEnv, const uint8_t *buffer, size_t length, jobject options)
{
	// Validate image
	int bitmapWidth = 0;
	int bitmapHeight = 0;
	if (!WebPGetInfo(buffer, length, &bitmapWidth, &bitmapHeight))
	{
		jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Invalid WebP format");
		return NULL;
	}

	// Check if size is all what we were requested to do
	if(options && jniEnv->GetBooleanField(options, jrefs::android::graphics::BitmapFactory->Options.inJustDecodeBounds) == JNI_TRUE)
	{
		jniEnv->SetIntField(options, jrefs::android::graphics::BitmapFactory->Options.outWidth, bitmapWidth);
		jniEnv->SetIntField(options, jrefs::android::graphics::BitmapFactory->Options.outHeight, bitmapHeight);
		return NULL;
	}

	// Initialize decoder config and configure scaling if requested
	WebPDecoderConfig config;
	if (!WebPInitDecoderConfig(&config))
	{
		jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Unable to init WebP decoder config");
		return NULL;
	}

	if (options)
	{
		jint inSampleSize = jniEnv->GetIntField(options, jrefs::android::graphics::BitmapFactory->Options.inSampleSize);
		if (inSampleSize > 1)
		{
			config.options.use_scaling = 1;
			config.options.scaled_width = bitmapWidth /= inSampleSize;
			config.options.scaled_height = bitmapHeight /= inSampleSize;
		}
	}

	__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Decoding into %dx%d bitmap", bitmapWidth, bitmapHeight);

	// Create bitmap
	jobject value__ARGB_8888 = jniEnv->GetStaticObjectField(jrefs::android::graphics::Bitmap->Config.jclassRef, jrefs::android::graphics::Bitmap->Config.ARGB_8888);
	jobject outputBitmap = jniEnv->CallStaticObjectMethod(jrefs::android::graphics::Bitmap->jclassRef, jrefs::android::graphics::Bitmap->createBitmap,
		(jint)bitmapWidth, (jint)bitmapHeight,
		value__ARGB_8888);
	if (!outputBitmap)
	{
		jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Failed to allocate Bitmap");
		return NULL;
	}

	// Get information about bitmap passed
	AndroidBitmapInfo bitmapInfo;
	if (AndroidBitmap_getInfo(jniEnv, outputBitmap, &bitmapInfo) != ANDROID_BITMAP_RESULT_SUCCESS)
	{
		jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Failed to get Bitmap information");
		return NULL;
	}

	// Lock pixels
	void *bitmapPixels = 0;
	if (AndroidBitmap_lockPixels(jniEnv, outputBitmap, &bitmapPixels) != ANDROID_BITMAP_RESULT_SUCCESS)
	{
		jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Failed to lock Bitmap pixels");
		return NULL;
	}

	// Decode to ARGB
	config.output.colorspace = MODE_RGBA;
	config.output.u.RGBA.rgba = (uint8_t*)bitmapPixels;
	config.output.u.RGBA.stride = bitmapInfo.stride;
	config.output.u.RGBA.size = bitmapInfo.height * bitmapInfo.stride;
	config.output.is_external_memory = 1;
	if (WebPDecode(buffer, length, &config) != VP8_STATUS_OK)
	{
		AndroidBitmap_unlockPixels(jniEnv, outputBitmap);
		jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Failed to decode WebP pixel data");
		return NULL;
	}

	// Unlock pixels
	if (AndroidBitmap_unlockPixels(jniEnv, outputBitmap) != ANDROID_BITMAP_RESULT_SUCCESS)
	{
		jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Failed to unlock Bitmap pixels");
		return NULL;
	}

	return outputBitmap;
}
Esempio n. 24
0
int ImageFormatWEBP::load(const char *name, int& width, int& height, int& format) {
 	printf("ImageFormatWEBP::load\n");
    
    // Open File
 	FILE* file = fopen(name,"rb");
 	if (file == 0) {
        printf("ImageFormatWEBP::load(): can't open file '%s'\n",name);
 		return 0;
 	}
    
    // init width / height / format value to 0
    width  = 0;
 	height = 0;
    format = 0;
    
    // size of file
    fseek(file,0,SEEK_END);
 	const long data_size = ftell(file);
 	fseek(file,0,SEEK_SET);
    
    unsigned char * img_data = new unsigned char[data_size];
    fread(img_data,data_size,1,file);
    fclose(file);
    
    // Get header info
    int webpinfo = WebPGetInfo(img_data, data_size, &width, &height);
    if (webpinfo == 0) {
        printf("ImageFormatWEBP::load(): wrong header in \"%s\" file\n",name);
 		delete img_data;
 		return 0;
    }

    // Get betstream
    WebPBitstreamFeatures features;
    VP8StatusCode status = WebPGetFeatures(img_data, data_size, &features);

    if (status != VP8_STATUS_OK) {
        printf("ImageFormatWEBP::load(): bad bitstream in \"%s\" file, error:\"%d\"\n",name,status);
 		delete img_data;
 		return 0;
    }

    format = features.has_alpha ? 4 : 3;
    
    int data_decoded_size = width * height * format;

    // raw data image container
    unsigned char * img_data_decoded = new unsigned char[data_decoded_size];
    memset(img_data_decoded,0x00,data_decoded_size);

    // decode image inside container (RGB and RGBA)
    if (format == 3 ) {
        if ( WebPDecodeRGBInto(img_data, data_size, img_data_decoded, data_decoded_size, width * format) == NULL ) {
            printf("ImageFormatWEBP::load(): can't decode RGB \"%s\" file\n",name);
            delete img_data;
            delete img_data_decoded;
            return 0;
        }
    } else {
        if ( WebPDecodeRGBAInto(img_data, data_size, img_data_decoded, data_decoded_size, width * format) == NULL ) {
            printf("ImageFormatWEBP::load(): can't decode RGBA \"%s\" file\n",name);
            delete img_data;
            delete img_data_decoded;
           return 0;
        }
    }
    
    // create temporary file for glue code javascript
    FILE* raw = fopen(kTempararyName,"wb");
    if (raw) {
        fwrite(img_data_decoded,data_decoded_size ,1 , raw);
        fclose(raw);
    }
    
    delete img_data;
    delete img_data_decoded;
    
	return 1;
}
Esempio n. 25
0
// Store image bearing chunks to 'frame'.
static ParseStatus StoreFrame(int frame_num, MemBuffer* const mem,
                              Frame* const frame) {
  int alpha_chunks = 0;
  int image_chunks = 0;
  int done = (MemDataSize(mem) < CHUNK_HEADER_SIZE);
  ParseStatus status = PARSE_OK;

  if (done) return PARSE_NEED_MORE_DATA;

  do {
    const size_t chunk_start_offset = mem->start_;
    const uint32_t fourcc = GetLE32(mem);
    const uint32_t payload_size = GetLE32(mem);
    const uint32_t payload_size_padded = payload_size + (payload_size & 1);
    const size_t payload_available = (payload_size_padded > MemDataSize(mem))
                                   ? MemDataSize(mem) : payload_size_padded;
    const size_t chunk_size = CHUNK_HEADER_SIZE + payload_available;

    if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR;
    if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR;
    if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA;

    switch (fourcc) {
      case MKFOURCC('A', 'L', 'P', 'H'):
        if (alpha_chunks == 0) {
          ++alpha_chunks;
          frame->img_components_[1].offset_ = chunk_start_offset;
          frame->img_components_[1].size_ = chunk_size;
          frame->frame_num_ = frame_num;
          Skip(mem, payload_available);
        } else {
          goto Done;
        }
        break;
      case MKFOURCC('V', 'P', '8', ' '):
      case MKFOURCC('V', 'P', '8', 'L'):
        if (image_chunks == 0) {
          int width = 0, height = 0;
          ++image_chunks;
          frame->img_components_[0].offset_ = chunk_start_offset;
          frame->img_components_[0].size_ = chunk_size;
          // Extract the width and height from the bitstream, tolerating
          // failures when the data is incomplete.
          if (!WebPGetInfo(mem->buf_ + frame->img_components_[0].offset_,
                           frame->img_components_[0].size_, &width, &height) &&
              status != PARSE_NEED_MORE_DATA) {
            return PARSE_ERROR;
          }

          frame->width_ = width;
          frame->height_ = height;
          frame->frame_num_ = frame_num;
          frame->complete_ = (status == PARSE_OK);
          Skip(mem, payload_available);
        } else {
          goto Done;
        }
        break;
 Done:
      default:
        // Restore fourcc/size when moving up one level in parsing.
        Rewind(mem, CHUNK_HEADER_SIZE);
        done = 1;
        break;
    }

    if (mem->start_ == mem->riff_end_) {
      done = 1;
    } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) {
      status = PARSE_NEED_MORE_DATA;
    }
  } while (!done && status == PARSE_OK);

  return status;
}
Esempio n. 26
0
GDALDataset *WEBPDataset::Open( GDALOpenInfo * poOpenInfo )

{
    if( !Identify( poOpenInfo ) || poOpenInfo->fpL == NULL )
        return NULL;

    int nWidth, nHeight;
    if (!WebPGetInfo((const uint8_t*)poOpenInfo->pabyHeader, (uint32_t)poOpenInfo->nHeaderBytes,
                     &nWidth, &nHeight))
        return NULL;

    int nBands = 3;

#if WEBP_DECODER_ABI_VERSION >= 0x0002
     WebPDecoderConfig config;
     if (!WebPInitDecoderConfig(&config))
         return NULL;

     int bOK = WebPGetFeatures(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes, &config.input) == VP8_STATUS_OK;

    if (config.input.has_alpha)
        nBands = 4;

     WebPFreeDecBuffer(&config.output);

    if (!bOK)
        return NULL;

#endif

    if( poOpenInfo->eAccess == GA_Update )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "The WEBP driver does not support update access to existing"
                  " datasets.\n" );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
    WEBPDataset  *poDS;

    poDS = new WEBPDataset();
    poDS->nRasterXSize = nWidth;
    poDS->nRasterYSize = nHeight;
    poDS->fpImage = poOpenInfo->fpL;
    poOpenInfo->fpL = NULL;

/* -------------------------------------------------------------------- */
/*      Create band information objects.                                */
/* -------------------------------------------------------------------- */
    for( int iBand = 0; iBand < nBands; iBand++ )
        poDS->SetBand( iBand+1, new WEBPRasterBand( poDS, iBand+1 ) );

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
    poDS->SetDescription( poOpenInfo->pszFilename );

    poDS->TryLoadXML( poOpenInfo->GetSiblingFiles() );

/* -------------------------------------------------------------------- */
/*      Open overviews.                                                 */
/* -------------------------------------------------------------------- */
    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );

    return poDS;
}
Esempio n. 27
0
static int
WEBPDecode(WEBPDec* pSrc, Vbitmap *vbitmap,
           YmagineFormatOptions *options)
{
  int contentSize;
  int origWidth = 0;
  int origHeight = 0;
  int quality;
  unsigned char header[WEBP_HEADER_SIZE + 32];
  int headerlen;
  int toRead;
  unsigned char *input = NULL;
  int inputlen;
  int oformat;
  int opitch;
  unsigned char *odata;
  int rc;
  Vrect srcrect;
  Vrect destrect;
  WebPIDecoder* idec;

  if (options == NULL) {
    /* Options argument is mandatory */
    return 0;
  }

  headerlen = YchannelRead(pSrc->channel, (char *) header, sizeof(header));
  if (headerlen < WEBP_HEADER_SIZE) {
    return 0;
  }

  /* Check WEBP header */
  contentSize = WebpCheckHeader((const char*) header, headerlen);
  if (contentSize <= 0) {
    return 0;
  }

  if (WebPGetInfo(header, headerlen, &origWidth, &origHeight) == 0) {
    ALOGD("invalid VP8 header");
    return 0;
  }

  if (origWidth <= 0 || origHeight <= 0) {
    return 0;
  }

  if (YmagineFormatOptions_invokeCallback(options, YMAGINE_IMAGEFORMAT_WEBP,
                                          origWidth, origHeight) != YMAGINE_OK) {
    return 0;
  }

  if (YmaginePrepareTransform(vbitmap, options,
                              origWidth, origHeight,
                              &srcrect, &destrect) != YMAGINE_OK) {
    return 0;
  }

#if YMAGINE_DEBUG_WEBP
  ALOGD("size: %dx%d req: %dx%d %s -> output: %dx%d",
        origWidth, origHeight,
        destrect.width, destrect.height,
        (options->scalemode == YMAGINE_SCALE_CROP) ? "crop" :
        (options->scalemode == YMAGINE_SCALE_FIT ? "fit" : "letterbox"),
        destrect.width, destrect.height);
#endif

  if (vbitmap != NULL) {
    if (options->resizable) {
      destrect.x = 0;
      destrect.y = 0;
      if (VbitmapResize(vbitmap, destrect.width, destrect.height) != YMAGINE_OK) {
        return 0;
      }
    }
    if (VbitmapType(vbitmap) == VBITMAP_NONE) {
      /* Decode bounds only, return positive number (number of lines) on success */
      return VbitmapHeight(vbitmap);
    }
  }

  pSrc->bitmap = vbitmap;

  inputlen = contentSize;
  toRead = inputlen - headerlen;

  rc = VbitmapLock(vbitmap);
  if (rc != YMAGINE_OK) {
    ALOGE("VbitmapLock() failed (code %d)", rc);
    rc = YMAGINE_ERROR;
  } else {
    odata = VbitmapBuffer(vbitmap);
    opitch = VbitmapPitch(vbitmap);
    oformat = VbitmapColormode(vbitmap);

    pSrc->inwidth = origWidth;
    pSrc->inheight = origHeight;
    pSrc->outwidth = destrect.width;
    pSrc->outheight = destrect.height;

    if (odata == NULL) {
      ALOGD("failed to get reference to pixel buffer");
      rc = YMAGINE_ERROR;
   } else {
      WebPDecoderConfig config;
      int supported = 1;
      int webpcolorspace;

      switch(oformat) {
      case VBITMAP_COLOR_RGBA:
        webpcolorspace = MODE_RGBA;
        break;
      case VBITMAP_COLOR_RGB:
        webpcolorspace = MODE_RGB;
        break;
      case VBITMAP_COLOR_rgbA:
        webpcolorspace = MODE_rgbA;
        break;
      case VBITMAP_COLOR_ARGB:
        webpcolorspace = MODE_ARGB;
        break;
      case VBITMAP_COLOR_Argb:
        webpcolorspace = MODE_Argb;
        break;
      case VBITMAP_COLOR_GRAYSCALE:
      case VBITMAP_COLOR_YUV:
      case VBITMAP_COLOR_CMYK:
      case VBITMAP_COLOR_YCbCr:
      default:
        supported = 0;
        break;
      }

      if (!supported) {
        ALOGD("currently only support RGB, RGBA webp decoding");
        rc = YMAGINE_ERROR;
      } else {
        pSrc->isdirect = 1;
        pSrc->outformat = oformat;
        pSrc->outbpp = VbitmapBpp(vbitmap);
        pSrc->outstride = opitch;
        pSrc->outbuffer = odata + destrect.x * pSrc->outbpp + destrect.y * pSrc->outstride;

        WebPInitDecoderConfig(&config);

        quality = YmagineFormatOptions_normalizeQuality(options);
        if (quality < 90) {
          config.options.no_fancy_upsampling = 1;
        }
        if (quality < 60) {
          config.options.bypass_filtering = 1;
        }
        config.options.use_threads = 1;

        if (srcrect.x != 0 || srcrect.y != 0 || srcrect.width != origWidth || srcrect.height != origHeight) {
          /* Crop on source */
          config.options.use_cropping = 1;
          config.options.crop_left = srcrect.x;
          config.options.crop_top = srcrect.y;
          config.options.crop_width = srcrect.width;
          config.options.crop_height = srcrect.height;
        }
        if (pSrc->outwidth != pSrc->inwidth || pSrc->outheight != pSrc->inheight) {
          config.options.use_scaling = 1;
          config.options.scaled_width = pSrc->outwidth;
          config.options.scaled_height = pSrc->outheight;
        }

        rc = YMAGINE_ERROR;

        // Specify the desired output colorspace:
        config.output.colorspace = webpcolorspace;

        // Have config.output point to an external buffer:
        config.output.u.RGBA.rgba = (uint8_t*) pSrc->outbuffer;
        config.output.u.RGBA.stride = pSrc->outstride;
        config.output.u.RGBA.size = pSrc->outstride * pSrc->outheight;
        config.output.is_external_memory = 1;

        idec = WebPIDecode(NULL, 0, &config);
        if (idec != NULL) {
          VP8StatusCode status;

          status = WebPIAppend(idec, header, headerlen);
          if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
            int bytes_remaining = toRead;
            int bytes_read;
            int bytes_req;
            unsigned char rbuf[8192];

            // See WebPIUpdate(idec, buffer, size_of_transmitted_buffer);
            bytes_req = sizeof(rbuf);
            while (bytes_remaining > 0) {
              if (bytes_req > bytes_remaining) {
                bytes_req = bytes_remaining;
              }
              bytes_read = YchannelRead(pSrc->channel, rbuf, bytes_req);
              if (bytes_read <= 0) {
                break;
              }
              status = WebPIAppend(idec, (uint8_t*) rbuf, bytes_read);
              if (status == VP8_STATUS_OK) {
                rc = YMAGINE_OK;
                break;
              } else if (status == VP8_STATUS_SUSPENDED) {
                if (bytes_remaining > 0) {
                  bytes_remaining -= bytes_read;
                }
              } else {
                /* error */
                break;
              }
              // The above call decodes the current available buffer.
              // Part of the image can now be refreshed by calling
              // WebPIDecGetRGB()/WebPIDecGetYUVA() etc.
            }
          }
        }

        // the object doesn't own the image memory, so it can now be deleted.
        WebPIDelete(idec);
        WebPFreeDecBuffer(&config.output);
      }
    }

    VbitmapUnlock(vbitmap);
  }

  if (input) {
    Ymem_free((char*) input);
  }
  if (!pSrc->isdirect) {
    Ymem_free(pSrc->outbuffer);
  }

  if (rc == YMAGINE_OK) {
    return origHeight;
  }

  return 0;
}
Esempio n. 28
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;
}
Esempio n. 29
0
GDALDataset *WEBPDataset::Open( GDALOpenInfo * poOpenInfo )

{
    if( !Identify( poOpenInfo ) )
        return NULL;

    int nWidth, nHeight;
    if (!WebPGetInfo((const uint8_t*)poOpenInfo->pabyHeader, (uint32_t)poOpenInfo->nHeaderBytes,
                     &nWidth, &nHeight))
        return NULL;

    if( poOpenInfo->eAccess == GA_Update )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "The WEBP driver does not support update access to existing"
                  " datasets.\n" );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Open the file using the large file api.                         */
/* -------------------------------------------------------------------- */
    VSILFILE* fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );

    if( fpImage == NULL )
        return NULL;

    GByte* pabyUncompressed = (GByte*)VSIMalloc3(nWidth, nHeight, 3);
    if (pabyUncompressed == NULL)
    {
        VSIFCloseL(fpImage);
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
    WEBPDataset  *poDS;

    poDS = new WEBPDataset();
    poDS->nRasterXSize = nWidth;
    poDS->nRasterYSize = nHeight;
    poDS->fpImage = fpImage;
    poDS->pabyUncompressed = pabyUncompressed;

/* -------------------------------------------------------------------- */
/*      Create band information objects.                                */
/* -------------------------------------------------------------------- */
    for( int iBand = 0; iBand < 3; iBand++ )
        poDS->SetBand( iBand+1, new WEBPRasterBand( poDS, iBand+1 ) );

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
    poDS->SetDescription( poOpenInfo->pszFilename );

    poDS->TryLoadXML( poOpenInfo->papszSiblingFiles );

/* -------------------------------------------------------------------- */
/*      Open overviews.                                                 */
/* -------------------------------------------------------------------- */
    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );

    return poDS;
}
Esempio n. 30
0
// Returns true if this is a valid WebP bitstream.
static int IsWebP(const WebPData* const webp_data) {
  return (WebPGetInfo(webp_data->bytes, webp_data->size, NULL, NULL) != 0);
}