Showing posts with label Technical. Show all posts
Showing posts with label Technical. Show all posts

Tuesday, September 2, 2014

Android Image Cropping - Changing Template Instructions

A year ago I posted on my blog about my image cropping algorithm that developers can use freely for their own applications. During this time I have received many requests on changing template to their own custom templates, which many of them faced identical issues when modifying code to adapt to their custom templates. Therefore, in this post I will provide a step-by-step process on how to make the necessary changes when you plan to add your own custom templates.




Setting Up Project with your Templates

For this image crop algorithm to successfully work, you must provide templates with the background transparent and the lines clearly outlining your template. Make sure this template is saved as PNG, otherwise you won't have the transparent background that is required.
Once you have your templates in PNG files, you now need to place them into the correct project folders.
Looking at the screenshot above, I've placed my templates under res/drawable-nodpi. If you created your templates meant for any screen resolutions, then you can just place it under res/drawable-nodpi. Otherwise if you made different template sizes for different screen densities, then place them in their respective drawable folders.

Making the Proper Code Changes

The next process is to write code that will crop the images that you need.
Looking at the code snippet I have posted above.  The only code that you will need to modify are the arguments for invoking the static method ImageProcess.cropImage(). In the last two arguments, you must provide it with the width and height of your template. Passing in the incorrect argument can produce an error within the application.

That is pretty much it for making the proper modifications to add your own templates. If you have any questions and/or facing issues, feel free to comment below or create a Github issue.

Cheers!!

Link to my Github project: android-cropping-example.
Link to previous blog post: Android Image Cropping Example

Thursday, August 8, 2013

Android Camera Intent Example

Need to incorporate camera into your application? You can follow this instruction HERE provided by Google on creating custom camera app. Or you can do it the easier way which is to start a camera intent. If all you need to do is to capture photos, and do not have the time and resources to create your own custom camera app, then using intent to start the device's camera app is the right way to go. Doing this provides users the ability adjust camera settings provided by the camera app without having you to go through all the trouble creating one from scratch. There are two ways to start a camera intent, which will be described below. In the meantime, if you are eager to look at the source code, it can be view in my android-api-example Github project.

Start Camera Intent without Specified File Path

Basically, all you need to do is create an Intent indicating that you want to capture and image. The value indicating that you would like to capture an image is MediaStore.ACTION_IMAGE_CAPTURE. After when you have created the Intent, we then would want to Activity.startActivityForResult().  The reason for using Activity.startActivityForResult() instead of Activity.startActivity() is because we need to retrieve the image that the camera intent returns. You must then override Activity.startActivityForResult() method like in the code below: Since, we have not specified to the camera intent where to save the captured image file, it will return the image as a Bundle within the Intent data. Just as a side note, depending on the device that is being used it will either save a copy of the image file on the device (usually where the camera app saves captured images) or it doesn't.

Start Camera Intent with Specified File Path

In order to provide the Intent with a file path, we must come-up with a file path that we would like it to save it to and the filename. Different device have different starting file paths and to do this safely, I first check there is internal storage available and if there is then I retrieve the root public folder of the device's internal storage. This can be done using Android's Environment class. Then in that public root directory I create a standard Android pictures folder using Environment.DIRECTORY_PICTURES. This code is shown below: Once you have the file path, you just need specify the path into the Intent like this: Then finally in your overridden Activity.startActivityForResult(), since you already know the location of the image, you just need to decode the Bitmap using that file path.


You can view my Android Camera Intent example HERE.
Relevant files are:
src/com/choiboi/apiexamples/camera/CameraMainActivity.java
res/layout/activity_camera_main.xml

Hope this was helpful!!

Saturday, August 3, 2013

Android Toast Example

In this post I will be describing how Android Toasts can be done. Toast implementations are pretty simple and does not require many lines of code. To see my working example application of Toast implementation, you can take a look here android-api-example.




Basic Toast

Creating toasts requires only one line as shown below:
Basically all you need to do is invoke the static method Toast.makeText(), which will create a Toast object. The first argument takes in the current activity's Context object, second argument is the message that you would like to display, and finally the third argument would be the length of time that you would like it to be displayed for. Currently, the third argument will only either accept Toast.LENGTH_SHORT or Toast.LENGTH_LONG and you will not be able specify your own set time. Once the Toast object is created, invoke Toast.show() with that Toast object. If you want to display Toast longer then just replace Toast.LENGTH_SHORT with Toast.LENGTH_LONG and you are done!

Display Toast Even Longer

Currently, I was only able to find one way to display Toasts longer than Toast.LENGTH_LONG. What I did was basically invoke show() on the same Toast object more than once consecutively. This was simply done by using a for loop and looping it as many times as you like. Depending on how many times you loop, it will display it for Toast.LENGTH_LONG times the number of times you loop.
In the above code, I am looping 4 times which results to a Toast message displaying for 4×Toast.LENGTH_LONG amount of time.

Custom Toast Background

If you happen to not like the default background, you create your own custom background and display Toasts messages using that background. To do this, you will first need to create a 9-patch image that you want to use for your Toast background. One tool that you can use to create 9-patch images from an existing image is Nine-patch Generator. Once you have placed the 9-patch images to their corresponding folders in your Android project, you need to then create a separate layout for your Toast and set that 9-patch image as background value for your root layout. Like this:
Creating a layout like the above gives you the flexibility on how you want to display your Toast. Once you have created your Toast message layout, next step is just a matter of writing few simple lines of code, shown below.
There is also another way customizing your Toast messages. This is done through Android's XML styling and more information can be found here in this link.

You can view my Android Toast example HERE.
Relevant files are:
src/com/choiboi/apiexamples/toast/ToastMainActivity.java
res/layout/activity_toast.xml
res/layout/activity_toast_custom_toast.xml

Happy Coding!

Wednesday, July 24, 2013

Android Image Cropping Example

When I was creating PsyYourself, I was faced with a challenge on how I can crop out the face with an image that the user provides. One option was to somehow apply Optical Character Recognition (OCR) to detect faces in an image and crop that part out, but at the time OCR was something out of my league to create.

Instead I optioned to have a set of templates that make up
the various shapes of faces and from there, users will be able to orient, either by zooming in or out or moving the image, to fit inside the template. Once that was done, it was up to the device to crop out the image. The problem with this is that there were no available cropping tools/algorithms that I can make use of. I mean, there are existing cropping APIs, but the only problem with that is that they crop out rectangular shaped images, which is something that I did not want. Therefore I am posting this blog to show how I did this. The example project can be found on Github android-cropping-example.

Project Setup

Now, both the image that is going to cropped and the template image has to be overlapped on the screen so that users can easily orient the image to fit into the template. This can be accomplished by using FrameLayout and having two ImageView as its children. As seen below.

The first ImageView with the id cp_img will be the image that user will be orienting. While the second ImageView cp_face_template with scaleType as centerInside because I want to use the exact size of my templates that I have created.

Once the users are done with orienting the image, we then now have to get those images from ImageView the way how it is displayed on the screen. To do this we must first call View.buildDrawingCache() and View.setDrawingCacheEnabled() with the boolean value true as their arguments. Then, to get the bitmap, call View.getDrawingCache(). Lastly, call View.setDrawingCacheEnabled() again and this time with the boolean value false passed in. This process will allow you to retrieve images from ImageView multiple times.

Once, we have retrieved both the template and the oriented image, it's time to put the device to work. As we can see above, I created another thread to handle that work as we don't want the main thread to be blocked because it's processing. So, now this is where my algorithm that I have create comes into play.

Cropping Algorithm

The main idea of how my algorithm works is:
  1. I merge the two bitmaps together making sure template is placed on top.
  2. Since I know the size of the template, create a new blank bitmap with those dimensions.
  3. From the centre of the combined image, go out quadrant by quadrant, going through every pixel value and copy it onto the blank bitmap.
  4. Once it hits the colour of the template lines, then from that point on set the pixel value of the blank bitmap transparent.
  5. After it has gotten through all 4 quadrants, return the created bitmap, which is the cropped image. 
Here is the cropping code:
Feel free to view, download, and make use of my code HERE!!
Enjoy :)

Link to android-cropping-example.

Tuesday, July 2, 2013

My Two Android Apps

As mentioned in my previous post, I've spent the past two months creating Android applications. So far, I have create two Android apps that have already been published on Google Play Store. These applications are Randomizer and Psy Yourself.

Randomizer (Random Generator)
Randomizer was the first app to be completed out of the two. It is a simple web based application using HTML, CSS, JavaScript, jQuery, jQuery mobile, Graphite for jQuery mobile, and finally packaged together using PhoneGap. My reasons for using use web technology is because of my extensive knowledge with web over Android development and the ability to deploy over multiple mobile platforms using PhoneGap.

Randomizer is an application for users where if they have difficulty making choices from the available selections they have on hand, they can input those selections and it will randomly select one. Other features includes, randomly ordering the list of choices, random number generator, and one neat feature is the ability to save randomly ordered lists, list of choices, and previous random selections for future view or use.

At first, the user experience wasn't that as pleasant compared to that of Android applications developed natively. It resulted in noticeable lag during page transitions and user input responses. Over time, after some extensive search on the web for optimizing mobile applications, I was able to improve the user experience and the user interface. But, in the end it still can't be compared to that of natively developed Android applications. This got me to think that I should move towards native development for all of my future applications. My friends have explained to me that it might be jQuery mobile at fault, causing Randomizer to be slow. Their reasoning have to do with jQuery mobile loading multiple unnecessary DOMs, which results in lag. So for now, I have my eyes on moving towards native app development for my next app, while keeping a lookout for other mobile web frameworks.

Psy Yourself (Photo Booth)
Psy Yourself is a photo booth type application where users get an image of themselves or an image of someone else and it will crop the face out replacing one of Korea's famous music artist Psy's face with the face that was cropped out. In the end it will display GIF style animation with the appropriate Psy music in the background. With social media connecting people, users will have the ability to save as a JPEG or GIF onto their devices and can be shared using their favorite social media apps.

This application was created natively using Android Development Tools (ADT). After successfully deploying an application using native development, I felt that I have made the right decision. Compared to web apps, the user interface feels smooth and quick to respond, a huge difference over my Randomizer app. But I am currently face with one major issue with this application, which happens to be memory issues. As this application is heavy with image since it loads and processes multiple images to once, it can be a burden on the phone's memory. This issue can be easily witnessed on low end phones with little RAM. I have deployed many updates for this application trying to optimize memory usage by removing bitmaps that aren't being used and adjusting images accordingly to phone's specifications, but this turns out to be not enough. In the meantime I am continuously looking out for other solutions to this issue that way majority of people interested in trying out this application can enjoy it! :)

Anyhow, these are my two applications already on the Android Play Store, feel free to try it out and provide feedbacks/comments via email (alottapps@gmail.com for Randomizer and nonamebrand00@gmail.com for Psy Yourself)!!

Link to Randomizer.
Link to Psy Yourself.

Enjoy :D