Skip to content

Instantly share code, notes, and snippets.

@zhukov
Created February 28, 2012 17:58
Show Gist options
  • Save zhukov/1934001 to your computer and use it in GitHub Desktop.
Save zhukov/1934001 to your computer and use it in GitHub Desktop.
VK compose photos
public void processThumbs(int maxW, int maxH){
ArrayList<ThumbAttachment> thumbs=new ArrayList<ThumbAttachment>();
for(Attachment att:attachments)
if(att instanceof PhotoAttachment) thumbs.add((ThumbAttachment)att);
String orients="";
int[] orients_cnt=new int[3];
ArrayList<Float> ratios=new ArrayList<Float>();
int cnt=thumbs.size();
boolean bad=false;
for(ThumbAttachment thumb:thumbs){
float ratio=thumb.getRatio();
if(ratio==-1){
bad=true;
}
char orient=ratio > 1.2 ? 'w' : (ratio < 0.8 ? 'n' : 'q');
orients+=orient;
orients_cnt[oi(orient)]++;
ratios.add(ratio);
}
if(bad || NetworkStateReceiver.disableBigImages){
//Log.e("vk", "BAD!");
return;
}
float avg_ratio = !ratios.isEmpty() ? sum(ratios) / ratios.size() : 1.0f;
float max_w, max_h, margin_w=Global.scale(2), margin_h=Global.scale(2);
if(maxW>0){
max_w=maxW;
max_h=maxH;
}else{
max_w=320;
max_h=210;
}
float max_ratio=(float)max_w/(float)max_h;
if(cnt==1){
if(ratios.get(0)>0.5){
thumbs.get(0).setViewSize(max_w, (float)max_w/(float)ratios.get(0), false, false);
}else{
thumbs.get(0).setViewSize(max_w, max_w*2, false, false);
}
}
else if(cnt==2){
if(orients.equals("ww") && avg_ratio > 1.4 * max_ratio && (ratios.get(1) - ratios.get(0)) < 0.2){
float w = max_w;
float h = Math.min((float)w / ratios.get(0), Math.min((float)w / ratios.get(1), (max_h - margin_h) / 2.0f));
thumbs.get(0).setViewSize(w, h, true, false);
thumbs.get(1).setViewSize(w, h, false, false);
}else if(orients.equals("ww") || orients.equals("qq")){
float w = ((max_w - margin_w) / 2);
float h = Math.min(w / ratios.get(0), Math.min(w / ratios.get(1), max_h));
thumbs.get(0).setViewSize(w, h, false, false);
thumbs.get(1).setViewSize(w, h, false, false);
}else{
float w0 = ((max_w - margin_w) / ratios.get(1) / (1 / ratios.get(0) + 1 / ratios.get(1)));
float w1 = (max_w - w0 - margin_w);
float h = Math.min(max_h, Math.min(w0 / ratios.get(0), w1 / ratios.get(1)));
thumbs.get(0).setViewSize(w0, h, false, false);
thumbs.get(1).setViewSize(w1, h, false, false);
}
}
else if(cnt==3){
if (/*(ratios.get(0) > 1.2 * max_ratio || avg_ratio > 1.5 * max_ratio) &&*/ orients.equals("www")) { // 2nd and 3rd photos are on the next line
float w = max_w;
float h_cover = Math.min(w / ratios.get(0), (max_h - margin_h) * 0.66f);
thumbs.get(0).setViewSize(w, h_cover, true, false);
w = ((max_w - margin_w) / 2);
float h = Math.min(max_h - h_cover - margin_h, Math.min(w / ratios.get(1), w / ratios.get(2)));
thumbs.get(1).setViewSize(w, h, false, false);
thumbs.get(2).setViewSize(w, h, false, false);
} else { // 2nd and 3rd photos are on the right part
int h = (int)max_h;
int w_cover = (int)Math.min(h * ratios.get(0), (max_w - margin_w) * 0.75);
thumbs.get(0).setViewSize(w_cover, h, false, false);
float h1 = (ratios.get(1) * (max_h - margin_h) / (ratios.get(2) + ratios.get(1)));
float h0 = (max_h - h1 - margin_h);
float w = Math.min(max_w - w_cover - margin_w, Math.min(h1 * ratios.get(2), h0 * ratios.get(1)));
thumbs.get(1).setViewSize(w, h0, false, true);
thumbs.get(2).setViewSize(w, h1, false, true);
}
}
else if (cnt == 4) {
if (/*(ratios.get(0) > 1.2 * max_ratio || avg_ratio > 1.5 * $max_ration) &&*/ orients.equals("wwww")) { // 2nd, 3rd and 4th photos are on the next line
int w = (int)max_w;
int h_cover = (int)Math.min(w / ratios.get(0), (max_h - margin_h) * 0.66);
thumbs.get(0).setViewSize(w, h_cover, true, false);
int h = (int)((max_w - 2 * margin_w) / (ratios.get(1) + ratios.get(2) + ratios.get(3)));
int w0 = (int)(h * ratios.get(1));
int w1 = (int)(h * ratios.get(2));
int w2 = (int)(h * ratios.get(3));
h = (int)Math.min(max_h - h_cover - margin_h, h);
thumbs.get(1).setViewSize(w0, h, false, false);
thumbs.get(2).setViewSize(w1, h, false, false);
thumbs.get(3).setViewSize(w2, h, false, false);
} else { // 2nd, 3rd and 4th photos are on the right part
int h = (int)max_h;
int w_cover = (int)Math.min(h * ratios.get(0), (max_w - margin_w) * 0.66);
thumbs.get(0).setViewSize(w_cover, h, false, false);
int w = (int)((max_h - 2 * margin_h) / (1 / ratios.get(1) + 1 / ratios.get(2) + 1 / ratios.get(3)));
int h0 = (int)(w / ratios.get(1));
int h1 = (int)(w / ratios.get(2));
int h2 = (int)(w / ratios.get(3)+margin_h);
w = (int)Math.min(max_w - w_cover - margin_w, w);
thumbs.get(1).setViewSize(w, h0, false, true);
thumbs.get(2).setViewSize(w, h1, false, true);
thumbs.get(3).setViewSize(w, h2, false, true);
}
}
else{
ArrayList<Float> ratios_cropped = new ArrayList<Float>();
if (avg_ratio > 1.1) {
for(float ratio:ratios) {
ratios_cropped.add(Math.max(1.0f, ratio));
}
} else {
for (float ratio:ratios) {
ratios_cropped.add(Math.min(1.0f, ratio));
}
}
HashMap<String, float[]> tries = new HashMap<String, float[]>();
// One line
int first_line, second_line, third_line;
tries.put((first_line=cnt)+"", new float[]{calculateMultiThumbsHeight(ratios_cropped, max_w, margin_w)});
// Two lines
for (first_line = 1; first_line <= cnt - 1; first_line++) {
tries.put(first_line+","+(second_line = cnt - first_line), new float[]{
calculateMultiThumbsHeight(ratios_cropped.subList(0, first_line), max_w, margin_w),
calculateMultiThumbsHeight(ratios_cropped.subList(first_line, ratios_cropped.size()), max_w, margin_w)
}
);
}
// Three lines
for (first_line = 1; first_line <= cnt - 2; first_line++) {
for (second_line = 1; second_line <= cnt - first_line - 1; second_line++) {
tries.put(first_line+","+second_line+","+(third_line = cnt - first_line - second_line), new float[]{
calculateMultiThumbsHeight(ratios_cropped.subList(0, first_line), max_w, margin_w),
calculateMultiThumbsHeight(ratios_cropped.subList(first_line, first_line+second_line), max_w, margin_w),
calculateMultiThumbsHeight(ratios_cropped.subList(first_line + second_line, ratios_cropped.size()), max_w, margin_w)
}
);
}
}
// Looking for minimum difference between thumbs block height and max_h (may probably be little over)
String opt_conf = null;
float opt_diff = 0;
float opt_height = 0;
float opt_h;
Set<String> keys=tries.keySet();
for (String conf:keys) {
float[] heights=tries.get(conf);
float conf_h = margin_h * (heights.length - 1);
for(float h:heights) conf_h+=h;
float conf_diff = Math.abs(conf_h - max_h);
if (conf.indexOf(',') != -1) {
String[] conf_nums = conf.split(",");
if (Integer.parseInt(conf_nums[0]) > Integer.parseInt(conf_nums[1]) ||
conf_nums.length>2 && Integer.parseInt(conf_nums[1]) > Integer.parseInt(conf_nums[2])) {
conf_diff *= 1.1;
}
}
if (opt_conf == null || conf_diff < opt_diff) {
opt_conf = conf;
opt_diff = conf_diff;
opt_h = conf_h;
}
}
boolean breakNext=false;
// Generating optimal HTML
ArrayList<ThumbAttachment> thumbs_remain = (ArrayList<ThumbAttachment>) thumbs.clone();
ArrayList<Float> ratios_remain = (ArrayList<Float>) ratios_cropped.clone();
String[] chunks = opt_conf.split(",");
float[] opt_heights = tries.get(opt_conf);
int last_row = chunks.length - 1;
int k=0;
for (int i=0;i<chunks.length;i++) {
int line_chunks_num=Integer.parseInt(chunks[i]);
ArrayList<ThumbAttachment> line_thumbs = new ArrayList<ThumbAttachment>();
for(int j=0;j<line_chunks_num;j++) line_thumbs.add(thumbs_remain.remove(0));
float line_height = opt_heights[k];
k++;
int last_column = line_thumbs.size() - 1;
for (int j=0;j<line_thumbs.size();j++) {
ThumbAttachment thumb=line_thumbs.get(j);
float thumb_ratio = ratios_remain.remove(0);
thumb.setViewSize((int)(thumb_ratio * line_height), (int)line_height, j==last_column, false);
}
}
}
}
private int oi(char o){
switch(o){
case 'w':
return 0;
case 'n':
return 1;
case 'q':
return 2;
}
return 0;
}
private float sum(List<Float> a){
float sum=0;
for(float f:a) sum+=f;
return sum;
}
private float calculateMultiThumbsHeight(List<Float> ratios, float width, float margin) {
return (width - (ratios.size() - 1) * margin) / sum(ratios);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment