/* * Copyright (c) 2017 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ package jsettlers.main.android.utils; import static java8.util.stream.StreamSupport.stream; import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.LinkedBlockingQueue; import jsettlers.common.Color; import jsettlers.common.buildings.EBuildingType; import jsettlers.common.images.ImageLink; import jsettlers.common.material.EMaterialType; import jsettlers.graphics.image.Image; import jsettlers.graphics.image.SingleImage; import jsettlers.graphics.map.draw.ImageProvider; import android.graphics.Bitmap; import android.os.Handler; import android.widget.ImageView; public class OriginalImageProvider { private static final OriginalImageProvider INSTANCE = new OriginalImageProvider(); private final HashMap<String, ImageReference> cachedImages = new HashMap<String, ImageReference>(); private ImageLoaderThread imageLoadThread; private final LinkedBlockingQueue<ImageReference> toLoad = new LinkedBlockingQueue<ImageReference>(); public static ImageReference get(EBuildingType building) { return INSTANCE.create(building.getGuiImage()); } public static ImageReference get(EMaterialType material) { return INSTANCE.create(material.getIcon()); } public static ImageReference get(String imageName) { return INSTANCE.create(ImageLink.fromName(imageName, 0)); } public static ImageReference get(ImageLink imageLink) { return INSTANCE.create(imageLink); } /** * Needs to be called on the Android UI Thread. * * @param image * The image to get * @return The reference to the image that will be loaded. */ private ImageReference create(ImageLink image) { String name = image.getName(); ImageReference cached = cachedImages.get(name); if (cached != null) { return cached; } ImageReference reference = new ImageReference(image); toLoad.add(reference); ensureImageLoaderStarted(); cachedImages.put(name, reference); return reference; } private void ensureImageLoaderStarted() { if (imageLoadThread == null) { imageLoadThread = new ImageLoaderThread(); imageLoadThread.start(); } } /** * A reference to an image that can be loaded at a later moment. */ public static class ImageReference { private ImageLink image; private ArrayList<ImageView> viewsToUpdate = new ArrayList<ImageView>(); private final Handler handler = new Handler(); private Bitmap bm = null; public ImageReference(ImageLink image) { this.image = image; } public void load() { Image loaded = ImageProvider.getInstance().getImage(image); int[] colors = new int[loaded.getWidth() * loaded.getHeight()]; if (loaded instanceof SingleImage) { ShortBuffer data = ((SingleImage) loaded).getData().duplicate(); data.rewind(); for (int i = 0; i < colors.length; i++) { colors[i] = Color.convertTo32Bit(data.get()); } } else { // TODO: Handle error. } bm = Bitmap.createBitmap(colors, 0, loaded.getWidth(), loaded.getWidth(), loaded.getHeight(), Bitmap.Config.ARGB_8888); handler.post(() -> { stream(viewsToUpdate).forEach(this::realSetAsImage); viewsToUpdate = null; }); } /** * To be called in the UI Thread. * * @param view */ public void setAsImage(ImageView view) { if (viewsToUpdate != null) { viewsToUpdate.add(view); } else { realSetAsImage(view); } } public void setAsButton(ImageView button) { float density = button.getContext().getResources().getDisplayMetrics().density; int w = (int) (180 / density); button.getLayoutParams().width = w; button.getLayoutParams().height = w * 3 / 4; button.setScaleType(ImageView.ScaleType.FIT_CENTER); setAsImage(button); } private void realSetAsImage(ImageView view) { view.setImageBitmap(bm); } } private class ImageLoaderThread extends Thread { public ImageLoaderThread() { super("Image loader"); } @Override public void run() { try { while (true) { ImageReference image = toLoad.take(); image.load(); } } catch (InterruptedException e) { // TODO: Error reporting. } } } }