com.kabootar.GlassMemeGenerator.ImageOverlay.java Source code

Java tutorial

Introduction

Here is the source code for com.kabootar.GlassMemeGenerator.ImageOverlay.java

Source

package com.kabootar.GlassMemeGenerator;

import java.io.*;

/**
 * Created with IntelliJ IDEA.
 * User: abandeali
 * Date: 12/5/13
 * Time: 10:29 PM
 */
/*
 * Copyright 2012-2013 Amazon Technologies, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *    http://aws.amazon.com/apache2.0
 *
 * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
 * OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and
 * limitations under the License.
                  */
import android.content.Context;
import android.content.Intent;
import android.graphics.*;
import android.os.AsyncTask;
import android.util.Base64;
import android.util.Log;
import com.google.android.glass.timeline.TimelineManager;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import static android.graphics.Paint.Style.*;

/**
 * Worker that knows how to overlay text onto an image.
 */
public class ImageOverlay {

    private static final int MAX_FONT_SIZE = 640;
    private static final int BOTTOM_MARGIN = 10;
    private static final int TOP_MARGIN = 5;
    private static final int SIDE_MARGIN = 10;
    private static final String TOP_TEXT = "This is a long bit of text on the top, but don't worry, this algorithm will take care of it";
    // private static final String BOTTOM_TEXT =
    // "Some long text is too long for one line, and if we continue it gets really long indeed";
    private static final String BOTTOM_TEXT = "NOPE";

    private static final String INPUT_IMAGE = "/tmp/CHANGEME";
    private static final String CAPTION_FILE = "/tmp/CHANGEME.out";

    public static Bitmap overlay(Bitmap image, String topCaption, String bottomCaption, Context baseContext)
            throws IOException, InterruptedException {

        Canvas graphics = new Canvas(image);
        graphics.drawBitmap(image, 0, 0, null);
        drawStringCentered(graphics, topCaption, image, true, baseContext);
        graphics.drawBitmap(image, 0, 0, null);
        drawStringCentered(graphics, bottomCaption, image, false, baseContext);
        return image;
    }

    public static void main(String[] args) throws InterruptedException {

        try {
            if (new File(CAPTION_FILE).exists()) {
                new File(CAPTION_FILE).delete();
            }
            Bitmap image = BitmapFactory.decodeFile(INPUT_IMAGE);
            Canvas graphics = new Canvas(image);
            String captionTop = TOP_TEXT;
            String captionBottom = BOTTOM_TEXT;
            drawStringCentered(graphics, captionTop, image, true, null);
            drawStringCentered(graphics, captionBottom, image, false, null);

            //ImageIO.write(image, "png", new File(CAPTION_FILE));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Draws the given string centered, as big as possible, on either the top or
     * bottom 20% of the image given.
     */
    private static void drawStringCentered(Canvas g, String text, Bitmap image, boolean top, Context baseContext)
            throws InterruptedException {
        if (text == null)
            text = "";

        int height = 0;
        int fontSize = MAX_FONT_SIZE;
        int maxCaptionHeight = image.getHeight() / 5;
        int maxLineWidth = image.getWidth() - SIDE_MARGIN * 2;
        String formattedString = "";
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        Paint stkPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        stkPaint.setStyle(STROKE);
        stkPaint.setStrokeWidth(8);
        stkPaint.setColor(Color.BLACK);

        //Typeface tf = Typeface.create("Arial", Typeface.BOLD);
        Typeface tf = Typeface.createFromAsset(baseContext.getAssets(), "fonts/impact.ttf");

        paint.setTypeface(tf);
        stkPaint.setTypeface(tf);
        do {

            paint.setTextSize(fontSize);

            // first inject newlines into the text to wrap properly
            StringBuilder sb = new StringBuilder();
            int left = 0;
            int right = text.length() - 1;
            while (left < right) {

                String substring = text.substring(left, right + 1);
                Rect stringBounds = new Rect();
                paint.getTextBounds(substring, 0, substring.length(), stringBounds);
                while (stringBounds.width() > maxLineWidth) {
                    if (Thread.currentThread().isInterrupted()) {
                        throw new InterruptedException();
                    }

                    // look for a space to break the line
                    boolean spaceFound = false;
                    for (int i = right; i > left; i--) {
                        if (text.charAt(i) == ' ') {
                            right = i - 1;
                            spaceFound = true;
                            break;
                        }
                    }
                    substring = text.substring(left, right + 1);
                    paint.getTextBounds(substring, 0, substring.length(), stringBounds);

                    // If we're down to a single word and we are still too wide,
                    // the font is just too big.
                    if (!spaceFound && stringBounds.width() > maxLineWidth) {
                        break;
                    }
                }
                sb.append(substring).append("\n");
                left = right + 2;
                right = text.length() - 1;
            }

            formattedString = sb.toString();

            // now determine if this font size is too big for the allowed height
            height = 0;
            for (String line : formattedString.split("\n")) {
                Rect stringBounds = new Rect();
                paint.getTextBounds(line, 0, line.length(), stringBounds);
                height += stringBounds.height();
            }
            fontSize--;
        } while (height > maxCaptionHeight);

        // draw the string one line at a time
        int y = 0;
        if (top) {
            y = TOP_MARGIN;
        } else {
            y = image.getHeight() - height - BOTTOM_MARGIN;
        }
        for (String line : formattedString.split("\n")) {
            // Draw each string twice for a shadow effect
            Rect stringBounds = new Rect();
            paint.getTextBounds(line, 0, line.length(), stringBounds);
            //paint.setColor(Color.BLACK);
            //g.drawText(line, (image.getWidth() - (int) stringBounds.width()) / 2 + 2, y + stringBounds.height() + 2, paint);

            paint.setColor(Color.WHITE);
            g.drawText(line, (image.getWidth() - (int) stringBounds.width()) / 2, y + stringBounds.height(), paint);

            //stroke
            Rect strokeBounds = new Rect();
            stkPaint.setTextSize(fontSize);
            stkPaint.getTextBounds(line, 0, line.length(), strokeBounds);
            g.drawText(line, (image.getWidth() - (int) strokeBounds.width()) / 2, y + strokeBounds.height(),
                    stkPaint);

            y += stringBounds.height();
        }
    }

    public static boolean saveToSD(final Bitmap overlaid, final String sdPath, final String fileName) {
        boolean isItSaved = false;
        new AsyncTask<Void, Void, Void>() {

            @Override
            protected Void doInBackground(Void... arg0) {

                File image = new File(sdPath, fileName);

                FileOutputStream outStream;
                try {

                    outStream = new FileOutputStream(image);
                    //resize image
                    Bitmap newoverlaid = getResizedBitmap(overlaid, 1000, 1362);
                    newoverlaid.compress(Bitmap.CompressFormat.PNG, 100, outStream);

                    outStream.flush();
                    outStream.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }

            public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
                int width = bm.getWidth();
                int height = bm.getHeight();
                float scaleWidth = ((float) newWidth) / width;
                float scaleHeight = ((float) newHeight) / height;
                // CREATE A MATRIX FOR THE MANIPULATION
                Matrix matrix = new Matrix();
                // RESIZE THE BIT MAP
                matrix.postScale(scaleWidth, scaleHeight);

                // "RECREATE" THE NEW BITMAP
                Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
                return resizedBitmap;
            }

            @Override
            protected void onPostExecute(Void result) {
                super.onPostExecute(result);
            }
        }.execute();

        return isItSaved;
    }

    public static void uploadToImgur(final String fileName, Context context) {
        Uploader mUploader = new Uploader(context, fileName);
        mUploader.execute();
    }

    public static class Uploader extends AsyncTask<Void, Void, String> {
        private final String fileName;
        private Context mContext;

        public Uploader(Context context, String file_name) {
            mContext = context;
            fileName = file_name;
        }

        @Override
        protected String doInBackground(Void... arg0) {
            final String url = "https://api.imgur.com/3/upload.json";

            HttpClient httpClient = new DefaultHttpClient();
            HttpContext localContext = new BasicHttpContext();
            HttpPost httpPost = new HttpPost(url);
            try {
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
                nameValuePairs.add(new BasicNameValuePair("image", fileName));
                nameValuePairs.add(new BasicNameValuePair("title", "GlassMeme #throughglass"));
                nameValuePairs.add(new BasicNameValuePair("description", "Meme generated using Google Glass"));

                MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);

                for (int index = 0; index < nameValuePairs.size(); index++) {
                    if (nameValuePairs.get(index).getName().equalsIgnoreCase("image")) {
                        // If the key equals to "image", we use FileBody to transfer the data
                        entity.addPart(nameValuePairs.get(index).getName(),
                                new FileBody(new File(nameValuePairs.get(index).getValue())));
                    } else {
                        // Normal string data
                        entity.addPart(nameValuePairs.get(index).getName(),
                                new StringBody(nameValuePairs.get(index).getValue()));
                    }
                }

                httpPost.addHeader(new BasicHeader("Authorization", "Client-ID c7170fd28edd452"));

                httpPost.setEntity(entity);

                HttpResponse response = httpClient.execute(httpPost, localContext);
                String statusLine = response.getStatusLine().toString();
                String responseBody = EntityUtils.toString(response.getEntity());
                Log.i("response", statusLine);
                Log.i("response", responseBody);

                JSONObject json = new JSONObject(responseBody);

                if (json.getInt("status") == 200) {
                    JSONObject data = json.getJSONObject("data");

                    Log.i("response", data.getString("link"));
                    return data.getString("link");
                }

            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return "";

        }

        @Override
        protected void onPostExecute(String s) {
            Intent intent = new Intent("meme_broadcast");
            intent.putExtra("message", s);
            intent.putExtra("fileName", fileName);
            mContext.sendBroadcast(intent);

            super.onPostExecute(s);
        }

    }
}