1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2011 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.data; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Context; 2004a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chenimport android.graphics.Rect; 2104a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen 2204a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chenimport com.android.gallery3d.R; 2304a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chenimport com.android.gallery3d.picasasource.PicasaSource; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.TreeMap; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class FaceClustering extends Clustering { 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unused") 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "FaceClustering"; 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 3204a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen private FaceCluster[] mClusters; 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private String mUntaggedString; 3404a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen private Context mContext; 3504a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen 3604a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen private class FaceCluster { 3704a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen ArrayList<Path> mPaths = new ArrayList<Path>(); 3804a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen String mName; 3904a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen MediaItem mCoverItem; 4004a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen Rect mCoverRegion; 4104a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen int mCoverFaceIndex; 4204a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen 4304a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen public FaceCluster(String name) { 4404a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mName = name; 4504a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 4604a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen 4704a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen public void add(MediaItem item, int faceIndex) { 4804a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen Path path = item.getPath(); 4904a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mPaths.add(path); 5004a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen Face[] faces = item.getFaces(); 5104a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen if (faces != null) { 5204a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen Face face = faces[faceIndex]; 5304a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen if (mCoverItem == null) { 5404a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mCoverItem = item; 5504a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mCoverRegion = face.getPosition(); 5604a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mCoverFaceIndex = faceIndex; 5704a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } else { 5804a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen Rect region = face.getPosition(); 5904a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen if (mCoverRegion.width() < region.width() && 6004a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mCoverRegion.height() < region.height()) { 6104a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mCoverItem = item; 6204a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mCoverRegion = face.getPosition(); 6304a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mCoverFaceIndex = faceIndex; 6404a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 6504a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 6604a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 6704a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 6804a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen 6904a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen public int size() { 7004a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen return mPaths.size(); 7104a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 7204a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen 7304a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen public MediaItem getCover() { 7404a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen if (mCoverItem != null) { 7504a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen if (PicasaSource.isPicasaImage(mCoverItem)) { 7604a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen return PicasaSource.getFaceItem(mContext, mCoverItem, mCoverFaceIndex); 7704a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } else { 7804a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen return mCoverItem; 7904a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 8004a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 8104a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen return null; 8204a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 8304a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public FaceClustering(Context context) { 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mUntaggedString = context.getResources().getString(R.string.untagged); 8704a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mContext = context; 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void run(MediaSet baseSet) { 9204a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen final TreeMap<Face, FaceCluster> map = 9304a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen new TreeMap<Face, FaceCluster>(); 9404a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen final FaceCluster untagged = new FaceCluster(mUntaggedString); 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { 977817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void consume(int index, MediaItem item) { 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Face[] faces = item.getFaces(); 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (faces == null || faces.length == 0) { 10104a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen untagged.add(item, -1); 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return; 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int j = 0; j < faces.length; j++) { 10504a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen Face face = faces[j]; 10604a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen FaceCluster cluster = map.get(face); 10704a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen if (cluster == null) { 10804a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen cluster = new FaceCluster(face.getName()); 10904a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen map.put(face, cluster); 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 11104a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen cluster.add(item, j); 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin }); 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int m = map.size(); 11704a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mClusters = map.values().toArray(new FaceCluster[m + ((untagged.size() > 0) ? 1 : 0)]); 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (untagged.size() > 0) { 11904a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen mClusters[m] = untagged; 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getNumberOfClusters() { 12504a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen return mClusters.length; 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ArrayList<Path> getCluster(int index) { 13004a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen return mClusters[index].mPaths; 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public String getClusterName(int index) { 13504a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen return mClusters[index].mName; 13604a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen } 13704a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen 13804a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen @Override 13904a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen public MediaItem getClusterCover(int index) { 14004a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen return mClusters[index].getCover(); 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 143