All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.anrisoftware.resources.images.mapcachedbounded.ImagesMapImpl Maven / Gradle / Ivy

There is a newer version: 4.7.0
Show newest version
/*
 * Copyright 2012-2016 Erwin Müller 
 *
 * This file is part of resources-images.
 *
 * resources-images is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * resources-images is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with resources-images. If not, see .
 */
package com.anrisoftware.resources.images.mapcachedbounded;

import static java.lang.Math.abs;

import java.awt.Dimension;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.inject.Inject;

import com.anrisoftware.resources.api.ResourcesException;
import com.anrisoftware.resources.images.api.ImageResolution;
import com.anrisoftware.resources.images.api.ImageResource;
import com.anrisoftware.resources.images.api.ImagesMap;

/**
 * Uses a Java hash map to store the image resources, removes the oldest entries
 * if it's over maximum cache size.
 *
 * @author Erwin Mueller, [email protected]
 * @since 1.1
 */
class ImagesMapImpl implements ImagesMap {

    private final ImagesMapLogger log;

    /**
     * Saves the loaded image resources.
     * 

* The image resources are stored for each name, for each resolution and for * each image size, i.e.: * *

     * [<name:{@link String}> = [<resolution:{@link ImageResolution}> = [<size:{@link Dimension}> = {@link ImageResource}]]]
     * 
*/ private final Map>> images; private final int maxEntries; /** * Creates the images map. */ @Inject ImagesMapImpl(ImagesMapLogger logger) { this.log = logger; this.images = new HashMap>>(); this.maxEntries = 32; } @Override public void putImage(ImageResource image) throws ResourcesException { String name = image.getName(); ImageResolution resolution = image.getResolution(); Map> resolutions = resolutionsMap(name); Map imagesSizes; imagesSizes = resourcesMap(resolutions, resolution); Dimension dimension = image.getSizePx(); if (!imagesSizes.containsKey(dimension)) { imagesSizes.put(dimension, image); } else { log.imageAlreadyInMap(this, image); } } @SuppressWarnings("serial") private Map resourcesMap( Map> resolutions, ImageResolution resolution) { Map resources = resolutions.get(resolution); if (resources == null) { resources = new LinkedHashMap() { @Override protected boolean removeEldestEntry( Map.Entry eldest) { return size() > maxEntries; } }; } resolutions.put(resolution, resources); return resources; } private Map> resolutionsMap( String name) { Map> resolutions; resolutions = images.get(name); if (resolutions == null) { resolutions = new HashMap>(); images.put(name, resolutions); } return resolutions; } @Override public ImageResource getImage(String name, Dimension size) { Map> resolutions = resolutionsMap(name); FindNearest findNearest = new FindNearest(size); int diff = Integer.MAX_VALUE; ImageResource foundImage = null; for (Map sizesmap : resolutions.values()) { ImageResource image = sizesmap.get(size); if (image != null) { return image; } findNearest.findNearest(sizesmap); int newdiff = findNearest.getDifference(); if (newdiff < 0 && abs(newdiff) < abs(diff)) { foundImage = findNearest.getImage(); diff = newdiff; } if (newdiff > 0 && newdiff < diff) { foundImage = findNearest.getImage(); diff = newdiff; } } return foundImage; } @Override public ImageResource getImage(String name, Dimension size, ImageResolution resolution) { Map> resolutions; Map resources; resolutions = resolutionsMap(name); resources = resourcesMap(resolutions, resolution); ImageResource image = resources.get(size); if (image == null) { log.noImageReturningNearest(this, name); return new FindNearest(size).findNearest(resources); } return image; } /** * Find the nearest image resource. * * @author Erwin Mueller, [email protected] * @since 1.0 */ private static class FindNearest { private final int searchArea; private int difference; private ImageResource image; /** * Set the size what we search for. * * @param searchSize * the {@link Dimension} that is the size. */ public FindNearest(Dimension searchSize) { this.searchArea = searchSize.width * searchSize.height; this.difference = Integer.MAX_VALUE; } /** * Find the next nearest image to the give size. * * @param resources * the {@link Map} of the {@link ImageResource}s with the * {@link Dimension} size that are in the map. * * @return the nearest {@link ImageResource} that is found. If the size * is smaller then the smallest image in the map, we return the * smallest image. If the size is larger then the biggest image * in the map, we return the biggest image. */ public ImageResource findNearest(Map resources) { for (Map.Entry entry : resources .entrySet()) { int newarea = entry.getKey().width * entry.getKey().height; int newdiff = searchArea - newarea; if (newdiff < 0 && abs(newdiff) < abs(difference)) { image = entry.getValue(); difference = newdiff; } if (newdiff > 0 && newdiff < difference) { image = entry.getValue(); difference = newdiff; } } return image; } /** * Return the found nearest {@link ImageResource} or null * if no image was found. */ public ImageResource getImage() { return image; } /** * Returns the difference of the area of the found image and the * searched size. */ public int getDifference() { return difference; } } @Override public boolean haveImage(String name) { return images.containsKey(name); } @Override public boolean haveImage(String name, ImageResolution resolution) { Map> resolutions; resolutions = images.get(name); return resolutions == null ? false : resolutions .containsKey(resolution); } @Override public boolean haveImage(String name, ImageResolution resolution, Dimension size) { Map> resolutions; resolutions = images.get(name); if (resolutions == null) { return false; } Map sizes = resolutions.get(size); return sizes == null ? false : sizes.containsKey(size); } @Override public String toString() { return images.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy