[core][ios][android][macos] Use premultiplied image directly for RasterTile and ImageSource, un-premultiply in the shader for blending
This commit is contained in:
@@ -18,7 +18,7 @@ public:
|
||||
optional<std::string> getURL() const;
|
||||
void setURL(const std::string& url);
|
||||
|
||||
void setImage(UnassociatedImage&&);
|
||||
void setImage(PremultipliedImage&&);
|
||||
|
||||
void setCoordinates(const std::array<LatLng, 4>&);
|
||||
std::array<LatLng, 4> getCoordinates() const;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,8 +40,7 @@ namespace android {
|
||||
}
|
||||
|
||||
void ImageSource::setImage(jni::JNIEnv& env, jni::Object<Bitmap> bitmap) {
|
||||
UnassociatedImage image = util::unpremultiply(Bitmap::GetImage(env, bitmap));
|
||||
source.as<mbgl::style::ImageSource>()->setImage(std:: move(image));
|
||||
source.as<mbgl::style::ImageSource>()->setImage(Bitmap::GetImage(env, bitmap));
|
||||
}
|
||||
|
||||
jni::Class<ImageSource> ImageSource::javaClass;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@ namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
|
||||
RasterBucket::RasterBucket(UnassociatedImage&& image_) {
|
||||
image = std::make_shared<UnassociatedImage>(std::move(image_));
|
||||
RasterBucket::RasterBucket(PremultipliedImage&& image_) {
|
||||
image = std::make_shared<PremultipliedImage>(std::move(image_));
|
||||
}
|
||||
|
||||
RasterBucket::RasterBucket(std::shared_ptr<UnassociatedImage> image_): image(image_) {
|
||||
RasterBucket::RasterBucket(std::shared_ptr<PremultipliedImage> image_): image(image_) {
|
||||
|
||||
}
|
||||
void RasterBucket::upload(gl::Context& context) {
|
||||
@@ -40,7 +40,7 @@ void RasterBucket::clear() {
|
||||
uploaded = false;
|
||||
}
|
||||
|
||||
void RasterBucket::setImage(std::shared_ptr<UnassociatedImage> image_) {
|
||||
void RasterBucket::setImage(std::shared_ptr<PremultipliedImage> image_) {
|
||||
image = std::move(image_);
|
||||
texture = {};
|
||||
uploaded = false;
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace mbgl {
|
||||
|
||||
class RasterBucket : public Bucket {
|
||||
public:
|
||||
RasterBucket(UnassociatedImage&&);
|
||||
RasterBucket(std::shared_ptr<UnassociatedImage>);
|
||||
RasterBucket(PremultipliedImage&&);
|
||||
RasterBucket(std::shared_ptr<PremultipliedImage>);
|
||||
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<UnassociatedImage>);
|
||||
std::shared_ptr<UnassociatedImage> image;
|
||||
void setImage(std::shared_ptr<PremultipliedImage>);
|
||||
std::shared_ptr<PremultipliedImage> image;
|
||||
optional<gl::Texture> texture;
|
||||
|
||||
// Bucket specific vertices are used for Image Sources only
|
||||
|
||||
@@ -82,7 +82,7 @@ void RenderImageSource::update(Immutable<style::Source::Impl> baseImpl_,
|
||||
std::swap(baseImpl, baseImpl_);
|
||||
|
||||
auto coords = impl().getCoordinates();
|
||||
std::shared_ptr<UnassociatedImage> image = impl().getImage();
|
||||
std::shared_ptr<PremultipliedImage> image = impl().getImage();
|
||||
|
||||
if (!image || !image->valid()) {
|
||||
enabled = false;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>(impl(), std::move(image));
|
||||
baseImpl = makeMutable<Impl>(impl(), decodeImage(*res.data));
|
||||
} catch (...) {
|
||||
observer->onSourceError(*this, std::current_exception());
|
||||
}
|
||||
|
||||
@@ -15,14 +15,14 @@ ImageSource::Impl::Impl(const Impl& other, std::array<LatLng, 4> 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<UnassociatedImage>(std::move(image_))) {
|
||||
image(std::make_shared<PremultipliedImage>(std::move(image_))) {
|
||||
}
|
||||
ImageSource::Impl::~Impl() = default;
|
||||
|
||||
std::shared_ptr<UnassociatedImage> ImageSource::Impl::getImage() const {
|
||||
std::shared_ptr<PremultipliedImage> ImageSource::Impl::getImage() const {
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,17 +13,17 @@ class ImageSource::Impl : public Source::Impl {
|
||||
public:
|
||||
Impl(std::string id, std::array<LatLng, 4> coords);
|
||||
Impl(const Impl& rhs, std::array<LatLng, 4> coords);
|
||||
Impl(const Impl& rhs, UnassociatedImage&& image);
|
||||
Impl(const Impl& rhs, PremultipliedImage&& image);
|
||||
|
||||
~Impl() final;
|
||||
|
||||
std::shared_ptr<UnassociatedImage> getImage() const;
|
||||
std::shared_ptr<PremultipliedImage> getImage() const;
|
||||
std::array<LatLng, 4> getCoordinates() const;
|
||||
|
||||
optional<std::string> getAttribution() const final;
|
||||
private:
|
||||
std::array<LatLng, 4> coords;
|
||||
std::shared_ptr<UnassociatedImage> image;
|
||||
std::shared_ptr<PremultipliedImage> image;
|
||||
};
|
||||
|
||||
} // namespace style
|
||||
|
||||
@@ -17,7 +17,7 @@ void RasterTileWorker::parse(std::shared_ptr<const std::string> data) {
|
||||
}
|
||||
|
||||
try {
|
||||
auto bucket = std::make_unique<RasterBucket>(util::unpremultiply(decodeImage(*data)));
|
||||
auto bucket = std::make_unique<RasterBucket>(decodeImage(*data));
|
||||
parent.invoke(&RasterTile::onParsed, std::move(bucket));
|
||||
} catch (...) {
|
||||
parent.invoke(&RasterTile::onError, std::current_exception());
|
||||
|
||||
@@ -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) };
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<RasterBucket>(UnassociatedImage{}));
|
||||
tile.onParsed(std::make_unique<RasterBucket>(PremultipliedImage{}));
|
||||
EXPECT_TRUE(tile.isRenderable());
|
||||
EXPECT_TRUE(tile.isLoaded());
|
||||
EXPECT_TRUE(tile.isComplete());
|
||||
|
||||
Reference in New Issue
Block a user