diff options
Diffstat (limited to 'main/src/cgeo/geocaching/connector/gc/IconDecoder.java')
| -rw-r--r-- | main/src/cgeo/geocaching/connector/gc/IconDecoder.java | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java new file mode 100644 index 0000000..2935ef0 --- /dev/null +++ b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java @@ -0,0 +1,156 @@ +package cgeo.geocaching.connector.gc; + +import cgeo.geocaching.cgCache; +import cgeo.geocaching.enumerations.CacheType; + +import android.graphics.Bitmap; + +/** + * icon decoder for cache icons + * + */ +public abstract class IconDecoder { + + private static final int[] OFFSET_X = new int[] { 0, -1, -1, 0, 1, 1, 1, 0, -1, -2, -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2 }; + private static final int[] OFFSET_Y = new int[] { 0, 0, 1, 1, 1, 0, -1, -1, -1, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2 }; + + /** + * The icon decoder walks a spiral around the center pixel position of the cache + * and searches for characteristic colors. + * + * @param cache + * @param bitmap + * @param xy + */ + public static void parseMapPNG13(final cgCache cache, Bitmap bitmap, UTFGridPosition xy) { + final int xCenter = xy.getX() * 4 + 2; + final int yCenter = xy.getY() * 4 + 2; + final int bitmapWidth = bitmap.getWidth(); + final int bitmapHeight = bitmap.getHeight(); + + int countMulti = 0; + int countFound = 0; + + for (int i = 0; i < OFFSET_X.length; i++) { + + // assert that we are still in the tile + final int x = xCenter + OFFSET_X[i]; + if (x < 0 || x >= bitmapWidth) { + continue; + } + + final int y = yCenter + OFFSET_Y[i]; + if (y < 0 || y >= bitmapHeight) { + continue; + } + + int color = bitmap.getPixel(x, y) & 0x00FFFFFF; + + // transparent pixels are not interesting + if (color == 0) { + continue; + } + + int red = (color & 0xFF0000) >> 16; + int green = (color & 0xFF00) >> 8; + int blue = color & 0xFF; + + // these are quite sure, so one pixel is enough for matching + if (green > 0x80 && green > red && green > blue) { + cache.setType(CacheType.TRADITIONAL); + return; + } + if (blue > 0x80 && blue > red && blue > green) { + cache.setType(CacheType.MYSTERY); + return; + } + if (red > 0x90 && blue < 0x10 && green < 0x10) { + cache.setType(CacheType.EVENT); + return; + } + + // next two are hard to distinguish, therefore we sample all pixels of the spiral + if (red > 0xFA && green > 0xD0) { + countMulti++; + } + if (red < 0xF3 && red > 0xa0 && green > 0x20 && blue < 0x80) { + countFound++; + } + } + + // now check whether we are sure about found/multi + if (countFound > countMulti && countFound >= 2) { + cache.setFound(true); + } + if (countMulti > countFound && countMulti >= 5) { + cache.setType(CacheType.MULTI); + } + } + + // Pixel colors in tile + private final static int COLOR_BORDER_GRAY = 0x5F5F5F; + private final static int COLOR_TRADITIONAL = 0x316013; + private final static int COLOR_MYSTERY = 0x243C97; + private final static int COLOR_MULTI = 0xFFDE19; + private final static int COLOR_FOUND = 0xFBEA5D; + + // Offset inside cache icon + private final static int POSX_TRADI = 7; + private final static int POSY_TRADI = -12; + private final static int POSX_MULTI = 5; // for orange 8 + private final static int POSY_MULTI = -9; // for orange 10 + private final static int POSX_MYSTERY = 5; + private final static int POSY_MYSTERY = -13; + private final static int POSX_FOUND = 10; + private final static int POSY_FOUND = -8; + + /** + * For level 14 find the borders of the icons and then use a single pixel and color to match. + * + * @param cache + * @param bitmap + * @param xy + */ + public static void parseMapPNG14(cgCache cache, Bitmap bitmap, UTFGridPosition xy) { + int x = xy.getX() * 4 + 2; + int y = xy.getY() * 4 + 2; + + // search for left border + int countX = 0; + while ((bitmap.getPixel(x, y) & 0x00FFFFFF) != COLOR_BORDER_GRAY) { + if (--x < 0 || ++countX > 20) { + return; + } + } + // search for bottom border + int countY = 0; + while ((bitmap.getPixel(x, y) & 0x00FFFFFF) != 0x000000) { + if (++y >= Tile.TILE_SIZE || ++countY > 20) { + return; + } + } + + try { + if ((bitmap.getPixel(x + POSX_TRADI, y + POSY_TRADI) & 0x00FFFFFF) == COLOR_TRADITIONAL) { + cache.setType(CacheType.TRADITIONAL); + return; + } + if ((bitmap.getPixel(x + POSX_MYSTERY, y + POSY_MYSTERY) & 0x00FFFFFF) == COLOR_MYSTERY) { + cache.setType(CacheType.MYSTERY); + return; + } + if ((bitmap.getPixel(x + POSX_MULTI, y + POSY_MULTI) & 0x00FFFFFF) == COLOR_MULTI) { + cache.setType(CacheType.MULTI); + return; + } + if ((bitmap.getPixel(x + POSX_FOUND, y + POSY_FOUND) & 0x00FFFFFF) == COLOR_FOUND) { + cache.setFound(true); + return; + } + } catch (IllegalArgumentException e) { + // intentionally left blank + } + + return; + } +} |
