From 8ae70105463db78699ef3743fb24503ed8feb054 Mon Sep 17 00:00:00 2001 From: Asheem Mamoowala Date: Tue, 11 Jul 2017 14:31:05 -0700 Subject: [core][ios][android][macos] Use premultiplied image directly for RasterTile and ImageSource, un-premultiply in the shader for blending --- include/mbgl/style/sources/image_source.hpp | 2 +- .../style/AnimatedImageSourceActivity.java | 28 +++++++++++++++++----- .../android/src/style/sources/image_source.cpp | 3 +-- platform/darwin/src/MGLImageSource.mm | 5 ++-- src/mbgl/renderer/buckets/raster_bucket.cpp | 8 +++---- src/mbgl/renderer/buckets/raster_bucket.hpp | 8 +++---- src/mbgl/renderer/sources/render_image_source.cpp | 2 +- src/mbgl/shaders/raster.cpp | 6 +++++ src/mbgl/style/sources/image_source.cpp | 5 ++-- src/mbgl/style/sources/image_source_impl.cpp | 6 ++--- src/mbgl/style/sources/image_source_impl.hpp | 6 ++--- src/mbgl/tile/raster_tile_worker.cpp | 2 +- test/gl/bucket.test.cpp | 2 +- test/style/source.test.cpp | 2 +- test/tile/raster_tile.test.cpp | 2 +- 15 files changed, 53 insertions(+), 34 deletions(-) diff --git a/include/mbgl/style/sources/image_source.hpp b/include/mbgl/style/sources/image_source.hpp index d8a2c45bd8..009764291f 100644 --- a/include/mbgl/style/sources/image_source.hpp +++ b/include/mbgl/style/sources/image_source.hpp @@ -18,7 +18,7 @@ public: optional getURL() const; void setURL(const std::string& url); - void setImage(UnassociatedImage&&); + void setImage(PremultipliedImage&&); void setCoordinates(const std::array&); std::array getCoordinates() const; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java index aeb6751b99..1beba632b0 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java @@ -1,10 +1,16 @@ package com.mapbox.mapboxsdk.testapp.activity.style; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; +import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngQuad; import com.mapbox.mapboxsdk.maps.MapView; @@ -106,17 +112,27 @@ public class AnimatedImageSourceActivity extends AppCompatActivity implements On private MapboxMap mapboxMap; private Handler handler; - private int[] drawables; + private Bitmap[] drawables; private int drawableIndex; + Bitmap getBitmap(int resourceId) { + Context context = Mapbox.getApplicationContext(); + Drawable drawable = ContextCompat.getDrawable(context, resourceId); + if (drawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + return bitmapDrawable.getBitmap(); + } + return null; + } + RefreshImageRunnable(MapboxMap mapboxMap, Handler handler) { this.mapboxMap = mapboxMap; this.handler = handler; - drawables = new int[4]; - drawables[0] = R.drawable.southeast_radar_0; - drawables[1] = R.drawable.southeast_radar_1; - drawables[2] = R.drawable.southeast_radar_2; - drawables[3] = R.drawable.southeast_radar_3; + drawables = new Bitmap[4]; + drawables[0] = getBitmap(R.drawable.southeast_radar_0); + drawables[1] = getBitmap(R.drawable.southeast_radar_1); + drawables[2] = getBitmap(R.drawable.southeast_radar_2); + drawables[3] = getBitmap(R.drawable.southeast_radar_3); drawableIndex = 1; } diff --git a/platform/android/src/style/sources/image_source.cpp b/platform/android/src/style/sources/image_source.cpp index cc7e1e7404..9c37d63d4b 100644 --- a/platform/android/src/style/sources/image_source.cpp +++ b/platform/android/src/style/sources/image_source.cpp @@ -40,8 +40,7 @@ namespace android { } void ImageSource::setImage(jni::JNIEnv& env, jni::Object bitmap) { - UnassociatedImage image = util::unpremultiply(Bitmap::GetImage(env, bitmap)); - source.as()->setImage(std:: move(image)); + source.as()->setImage(Bitmap::GetImage(env, bitmap)); } jni::Class ImageSource::javaClass; diff --git a/platform/darwin/src/MGLImageSource.mm b/platform/darwin/src/MGLImageSource.mm index 0a2dc2713f..351247e901 100644 --- a/platform/darwin/src/MGLImageSource.mm +++ b/platform/darwin/src/MGLImageSource.mm @@ -60,10 +60,9 @@ - (void)setImage:(MGLImage *)image { if (image != nullptr) { - mbgl::UnassociatedImage unassociatedImage = mbgl::util::unpremultiply(image.mgl_premultipliedImage); - self.rawSource->setImage(std::move(unassociatedImage)); + self.rawSource->setImage(image.mgl_premultipliedImage); } else { - self.rawSource->setImage(mbgl::UnassociatedImage({0,0})); + self.rawSource->setImage(mbgl::PremultipliedImage({0,0})); } _image = image; } diff --git a/src/mbgl/renderer/buckets/raster_bucket.cpp b/src/mbgl/renderer/buckets/raster_bucket.cpp index 61548ee333..8a2f1227a5 100644 --- a/src/mbgl/renderer/buckets/raster_bucket.cpp +++ b/src/mbgl/renderer/buckets/raster_bucket.cpp @@ -9,11 +9,11 @@ namespace mbgl { using namespace style; -RasterBucket::RasterBucket(UnassociatedImage&& image_) { - image = std::make_shared(std::move(image_)); +RasterBucket::RasterBucket(PremultipliedImage&& image_) { + image = std::make_shared(std::move(image_)); } -RasterBucket::RasterBucket(std::shared_ptr image_): image(image_) { +RasterBucket::RasterBucket(std::shared_ptr image_): image(image_) { } void RasterBucket::upload(gl::Context& context) { @@ -40,7 +40,7 @@ void RasterBucket::clear() { uploaded = false; } -void RasterBucket::setImage(std::shared_ptr image_) { +void RasterBucket::setImage(std::shared_ptr image_) { image = std::move(image_); texture = {}; uploaded = false; diff --git a/src/mbgl/renderer/buckets/raster_bucket.hpp b/src/mbgl/renderer/buckets/raster_bucket.hpp index e92e4b51f7..1b0d787bcd 100644 --- a/src/mbgl/renderer/buckets/raster_bucket.hpp +++ b/src/mbgl/renderer/buckets/raster_bucket.hpp @@ -13,8 +13,8 @@ namespace mbgl { class RasterBucket : public Bucket { public: - RasterBucket(UnassociatedImage&&); - RasterBucket(std::shared_ptr); + RasterBucket(PremultipliedImage&&); + RasterBucket(std::shared_ptr); void upload(gl::Context&) override; void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; void render(Painter& painter, @@ -24,8 +24,8 @@ public: bool hasData() const override; void clear(); - void setImage(std::shared_ptr); - std::shared_ptr image; + void setImage(std::shared_ptr); + std::shared_ptr image; optional texture; // Bucket specific vertices are used for Image Sources only diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index a17f97ee2f..3ffff5c8c6 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -82,7 +82,7 @@ void RenderImageSource::update(Immutable baseImpl_, std::swap(baseImpl, baseImpl_); auto coords = impl().getCoordinates(); - std::shared_ptr image = impl().getImage(); + std::shared_ptr image = impl().getImage(); if (!image || !image->valid()) { enabled = false; diff --git a/src/mbgl/shaders/raster.cpp b/src/mbgl/shaders/raster.cpp index eb7a2db240..f454078310 100644 --- a/src/mbgl/shaders/raster.cpp +++ b/src/mbgl/shaders/raster.cpp @@ -45,6 +45,12 @@ void main() { // read and cross-fade colors from the main and parent tiles vec4 color0 = texture2D(u_image0, v_pos0); vec4 color1 = texture2D(u_image1, v_pos1); + if (color0.a > 0.0) { + color0.rgb = color0.rgb / color0.a; + } + if (color1.a > 0.0) { + color1.rgb = color1.rgb / color1.a; + } vec4 color = mix(color0, color1, u_fade_t); color.a *= u_opacity; vec3 rgb = color.rgb; diff --git a/src/mbgl/style/sources/image_source.cpp b/src/mbgl/style/sources/image_source.cpp index 9313d8da4a..9b60ba1a48 100644 --- a/src/mbgl/style/sources/image_source.cpp +++ b/src/mbgl/style/sources/image_source.cpp @@ -37,7 +37,7 @@ void ImageSource::setURL(const std::string& url_) { } } -void ImageSource::setImage(UnassociatedImage&& image_) { +void ImageSource::setImage(PremultipliedImage&& image_) { url = {}; if (req) { req.reset(); @@ -70,8 +70,7 @@ void ImageSource::loadDescription(FileSource& fileSource) { observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty image url"))); } else { try { - UnassociatedImage image = util::unpremultiply(decodeImage(*res.data)); - baseImpl = makeMutable(impl(), std::move(image)); + baseImpl = makeMutable(impl(), decodeImage(*res.data)); } catch (...) { observer->onSourceError(*this, std::current_exception()); } diff --git a/src/mbgl/style/sources/image_source_impl.cpp b/src/mbgl/style/sources/image_source_impl.cpp index eb3e2635e5..c1f31dbdc6 100644 --- a/src/mbgl/style/sources/image_source_impl.cpp +++ b/src/mbgl/style/sources/image_source_impl.cpp @@ -15,14 +15,14 @@ ImageSource::Impl::Impl(const Impl& other, std::array coords_) image(other.image) { } -ImageSource::Impl::Impl(const Impl& rhs, UnassociatedImage&& image_) +ImageSource::Impl::Impl(const Impl& rhs, PremultipliedImage&& image_) : Source::Impl(rhs), coords(rhs.coords), - image(std::make_shared(std::move(image_))) { + image(std::make_shared(std::move(image_))) { } ImageSource::Impl::~Impl() = default; -std::shared_ptr ImageSource::Impl::getImage() const { +std::shared_ptr ImageSource::Impl::getImage() const { return image; } diff --git a/src/mbgl/style/sources/image_source_impl.hpp b/src/mbgl/style/sources/image_source_impl.hpp index e0999c34a5..1e1b005a32 100644 --- a/src/mbgl/style/sources/image_source_impl.hpp +++ b/src/mbgl/style/sources/image_source_impl.hpp @@ -13,17 +13,17 @@ class ImageSource::Impl : public Source::Impl { public: Impl(std::string id, std::array coords); Impl(const Impl& rhs, std::array coords); - Impl(const Impl& rhs, UnassociatedImage&& image); + Impl(const Impl& rhs, PremultipliedImage&& image); ~Impl() final; - std::shared_ptr getImage() const; + std::shared_ptr getImage() const; std::array getCoordinates() const; optional getAttribution() const final; private: std::array coords; - std::shared_ptr image; + std::shared_ptr image; }; } // namespace style diff --git a/src/mbgl/tile/raster_tile_worker.cpp b/src/mbgl/tile/raster_tile_worker.cpp index 86fb5f181d..3c8af97b40 100644 --- a/src/mbgl/tile/raster_tile_worker.cpp +++ b/src/mbgl/tile/raster_tile_worker.cpp @@ -17,7 +17,7 @@ void RasterTileWorker::parse(std::shared_ptr data) { } try { - auto bucket = std::make_unique(util::unpremultiply(decodeImage(*data))); + auto bucket = std::make_unique(decodeImage(*data)); parent.invoke(&RasterTile::onParsed, std::move(bucket)); } catch (...) { parent.invoke(&RasterTile::onError, std::current_exception()); diff --git a/test/gl/bucket.test.cpp b/test/gl/bucket.test.cpp index 24bec0bd22..7ff67f40d0 100644 --- a/test/gl/bucket.test.cpp +++ b/test/gl/bucket.test.cpp @@ -101,7 +101,7 @@ TEST(Buckets, SymbolBucket) { TEST(Buckets, RasterBucket) { gl::Context context; - UnassociatedImage rgba({ 1, 1 }); + PremultipliedImage rgba({ 1, 1 }); // RasterBucket::hasData() is always true. RasterBucket bucket = { std::move(rgba) }; diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp index d576dc1e4a..8b9cda1db3 100644 --- a/test/style/source.test.cpp +++ b/test/style/source.test.cpp @@ -531,7 +531,7 @@ TEST(Source, ImageSourceImageUpdate) { // Load initial, so the source state will be loaded=true source.loadDescription(test.fileSource); - UnassociatedImage rgba({ 1, 1 }); + PremultipliedImage rgba({ 1, 1 }); rgba.data[0] = 255; rgba.data[1] = 254; rgba.data[2] = 253; diff --git a/test/tile/raster_tile.test.cpp b/test/tile/raster_tile.test.cpp index 025208c331..4680e7f485 100644 --- a/test/tile/raster_tile.test.cpp +++ b/test/tile/raster_tile.test.cpp @@ -60,7 +60,7 @@ TEST(RasterTile, onError) { TEST(RasterTile, onParsed) { RasterTileTest test; RasterTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset); - tile.onParsed(std::make_unique(UnassociatedImage{})); + tile.onParsed(std::make_unique(PremultipliedImage{})); EXPECT_TRUE(tile.isRenderable()); EXPECT_TRUE(tile.isLoaded()); EXPECT_TRUE(tile.isComplete()); -- cgit v1.2.1