com.anrisoftware.resources.images.mapcached.ImagesMapImpl Maven / Gradle / Ivy
/*
* 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.mapcached;
import static java.lang.Math.abs;
import java.awt.Dimension;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
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.
*
* @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;
/**
* Creates the images map.
*/
@Inject
ImagesMapImpl(ImagesMapLogger logger) {
this.log = logger;
this.images = new HashMap>>();
}
@Override
public void putImage(ImageResource image) throws ResourcesException {
String name = image.getName();
ImageResolution resolution = image.getResolution();
Map> resolutions = resolutionsMap(name);
Map resources = resourcesMap(resolutions,
resolution);
Dimension dimension = image.getSizePx();
if (!resources.containsKey(dimension)) {
resources.put(dimension, image);
} else {
log.imageAlreadyInMap(this, image);
}
}
private Map resourcesMap(
Map> resolutions,
ImageResolution resolution) {
Map resources = resolutions.get(resolution);
if (resources == null) {
resources = new TreeMap(
new Comparator() {
@Override
public int compare(Dimension o1, Dimension o2) {
return o1.height < o2.height ? -1
: o1.height > o2.height ? 1 : 0;
}
});
}
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