jobject doDecode()

in static-webp/src/main/jni/static-webp/webp_bitmapfactory.cpp [100:165]


jobject doDecode(
    JNIEnv* env,
    uint8_t* encoded_image,
    unsigned encoded_image_length,
    jobject bitmapOptions,
    jfloat scale) {

  // Options manipulation is taken from https://github.com/android/platform_frameworks_base/blob/master/core/jni/android/graphics/BitmapFactory.cpp
  int image_width = 0;
  int image_height = 0;

  jobject bitmap = nullptr;

  WebPGetInfo(
      encoded_image,
      encoded_image_length,
      &image_width,
      &image_height);

  WebPDecoderConfig config;
  WebPInitDecoderConfig(&config);

  if ((bitmapOptions != nullptr) &&
      (setOutDimensions(env, bitmapOptions, image_width, image_height))) {
    return {};
  }

  if (scale != 1.0f) {
    image_width = int(image_width * scale + 0.5f);
    image_height = int(image_height  * scale + 0.5f);
    config.options.use_scaling = 1;
    config.options.scaled_width = image_width;
    config.options.scaled_height = image_height;
  }

  bitmap = createBitmap(env, image_width, image_height, bitmapOptions);
  RETURN_NULL_IF_EXCEPTION(env);

  void* raw_pixels = nullptr;

  int rc = AndroidBitmap_lockPixels(env, bitmap, (void**) &raw_pixels);
  if (rc != ANDROID_BITMAP_RESULT_SUCCESS) {
    env->ThrowNew(runtimeExceptionClass, "Decode error locking pixels");
    return JNI_FALSE;
  }

  config.output.colorspace = MODE_rgbA;
  config.output.u.RGBA.rgba = (uint8_t*) raw_pixels;
  config.output.u.RGBA.stride = image_width * 4;
  config.output.u.RGBA.size = image_width * image_height * 4;
  config.output.is_external_memory = 1;

  WebPDecode(encoded_image, encoded_image_length, &config);

  rc = AndroidBitmap_unlockPixels(env, bitmap);
  if (rc != ANDROID_BITMAP_RESULT_SUCCESS) {
    env->ThrowNew(runtimeExceptionClass, "Decode error unlocking pixels");
    return {};
  }

  if (bitmapOptions != nullptr) {
    setBitmapSize(env, bitmapOptions, image_width, image_height);
  }

  return bitmap;
}