Monday, December 31, 2012

Download YouTube video and convert it for Android

For downloading videos from YouTube I am using YouTubeDownloader2 and you can find it here http://sourceforge.net/projects/ytd2/. Why I am using that and not using Firefox add-ons? YouTubeDownloader2 is standalone program written in Java which is not storing my browsing habits in some remote DB. How do I know that? That is OSS, downloaded code, checked what it does, compiled it. If you don’t do Java, trust others who do ;-)
Once video is on file system we can encode it. It should be easy on Linux unless you are have common repo FFmpeg which is compiled without support for H.264, mp3 and few others codecs. If you are experienced Linux user you will visit FFmpeg wiki where is detailed instruction https://ffmpeg.org/trac/ffmpeg/wiki/UbuntuCompilationGuide how to configure and build FFmpeg. I am on Mint so that is valid set of instructions for me, people using other distro will look for their set of instructions. If you are not experienced user maybe mencoder which comes by default with everything enabled is better option. So, install libavcodec-extra-53 or maybe 54 and mencoder. We can ask mencoder what is supported if in terminal we execute:

~ $ mencoder -ovc help
MEncoder svn r34540 (Ubuntu), built with gcc-4.6 (C) 2000-2012 MPlayer Team

Available codecs:
copy     - frame copy, without re-encoding. Doesn't work with filters.
frameno  - special audio-only file for 3-pass encoding, see DOCS.
raw      - uncompressed video. Use fourcc option to set format explicitly.
nuv      - nuppel video
lavc     - libavcodec codecs - best quality!
xvid     - XviD encoding
x264     - H.264 encoding


and it produces video codecs list. For audio, query looks like this:

~ $ mencoder -oac help
MEncoder svn r34540 (Ubuntu), built with gcc-4.6 (C) 2000-2012 MPlayer Team

Available codecs:
   copy     - frame copy, without re-encoding (useful for AC3)
   pcm      - uncompressed PCM audio
   mp3lame  - cbr/abr/vbr MP3 using libmp3lame
   lavc     - FFmpeg audio encoder (MP2, AC3, ...)
   faac     - FAAC AAC audio encoder


There is small problem with mencoder, there is no WinFF for it and one have to do quite a bit of reading to assemble proper set of parameters. To save you from learning, here is what I do:

~ $ mencoder -of lavf -lavfopts format=mp4 -oac lavc -ovc lavc -lavcopts vbitrate=480:aglobal=1:vglobal=1:acodec=libfaac:abitrate=64:vcodec=mpeg4:keyint=25 -ofps 15 -af lavcresample=44100 -vf harddup,scale=480:320 -mc 0 "/home/yourlogin/in.flv" -o "/home/yourlogin/out.mp4"

I want H.263 video and AAC audio in MP4 container. Video should have bitrate up to 480kb/s and must be resized to 480x320 pixels, also frame rate is 15 frames per second.  For audio requested was resampling at 44.1 KHz and bit rate up to 64kb/s. It is not requirement that input video must be FLV, it should work for any container which you can find at YouTube. If your screen is different from 480x320, you may want to resize video differently. For example for 320x240 screen, vbitrate=256 and scale=320:240 should be good choice.
Not so nice as WinFF but not very complicated either.

Saturday, December 15, 2012

How to stack images using G’MIC

After chat on Astophotography Google+ community https://plus.google.com/u/0/communities/118208937662082340807 I concluded that it may be enough interest for 16 bit image processing using G’MIC tutorial and here it is.
G'MIC stands for GREYC's Magic Image Converter and we know it as plugin for GIMP. It is less known that G'MIC framework can be used on it’s own through simple shell scripting or possible C++ or web interface. What is very important it supports 16 bits integers per channel and that is something what GIMP is lacking.
So, what we are going to do here is to take a look at G’MIC tutorial http://gmic.sourceforge.net/tutorial.shtml and load images into stack average them and save them as 16 bit TIFF.
Tutorial says if you are using G’MIC as GIMP plugin and set logging to verbose it will print what it does.

I prefer writing output to log file to suggested running GIMP from terminal (command line for Windows users). Standard path and name for log file is /tmp/gmic_log
Also from tutorial we see that 16 bit processing starts with division with 256 and ends with multiplication with 256. While that represents reduction to 8 bit it is important to note that G’MIC internally works with floating point numbers and there is no loss of precision when we convert it back to 16 bit integers. Once when we are done with processing it is important how we are going to specify TIFF output. G’MIC will pick format from extension but it by default writes 32 bit TIFF. So, to get 8 bit TIFF we need to specify output type uchar and to get 16 bit TIFF we need to specify output type ushort.
Typical operations which we are going to use are:
  1.     -gimp_haar_smoothing 0.1,10,2,0,0 what is Smooth [wavelets] under Enhancements
  2.     -gimp_compose_average 1,0 what is Blend [average]  under Layers
  3.     -gimp_compose_screen 1,0 what is Blend [screen] under Layers
So complete workflow is we pick nicer RAWs export them as 16 bit PPMs using darktable as in http://grumpyoldprogrammer.blogspot.com/2012/11/more-about-stacking.html then we align them using align_image_stack from hugin-tools as in http://grumpyoldprogrammer.blogspot.com/2012/12/how-to-align-image-stack.html and finally we process them with G’MIC.
Averaging layers will produce at the end two layers, if we want we can save them as separate pictures, like this:

$ gmic tif0000.tif tif0001.tif tif0002.tif tif0003.tif -div 256 -gimp_compose_average 1,0 -mul 256 -c 0,65536 -type ushort -output[1] imageA.tiff -output[0] imageB.tiff

or we can stack those two layers in screen mode to boost light and stretch contrast, like this:

$ gmic tif0000.tif tif0001.tif tif0002.tif tif0003.tif -div 256 -gimp_compose_average 1,0 -gimp_compose_screen 1,0 -mul 256 -c 0,65536 -type ushort -output imageS.tiff

If we want to do resizing we can as in G’MIC tutorial use -resize2dx 1600,5 what is bi-cubic resizing to 1600 pixels width.
Instead of averaging we can try other options like -compose_median what is median or any other available filter or combination of filters, we try in GIMP, set logging to verbose and later run it in terminal without loss of data.

Monday, December 10, 2012

How to align image stack

Aligning images in GIMP is not very difficult if we do not have rotation to attend to, if rotation is present we rather leave that task to computer.
Aligning stack of images is not only used in astrophotography, it is common task in creation of HDR images. So, we can use align_image_stack from hugin-tools to align images. Installation procedure on Mint or Ubuntu is simple, we find it:

$ apt-cache search hugin
enblend - image blending tool
enfuse - image exposure blending tool
hugin - panorama photo stitcher - GUI tools
hugin-data - panorama photo stitcher - common data files
hugin-tools - panorama photo stitcher - commandline tools


and after that we install it:

$ sudo apt-get install hugin

It is available from repositories and there is no need to compile it from source. People using different operating system from Linux should visit Hugin website http://hugin.sourceforge.net/download/ and download installer for their operating system.
Once Hugin is installed align_image_stack should be available and we can align image stack. If you do not have own images in this tutorial http://grumpyoldprogrammer.blogspot.com/2012/11/even-more-astrophotography.html you will find download links.
We place in some empty directory JPEGs, if you have RAWs convert them, cd to that directory and execute:

$ align_image_stack -a tif *.JPG

Option -a tif means we want tif indexed output, so after a while we will see tif0000.tif, tif0001.tif and so on. Parameter *.JPG is input list, align all JPEGs. Alternatively we can specify file by file. Once alignment is done we can start GIMP and open all images as layers.



In order to check alignment we can change mode for top layer from Normal to Difference in Layers - Brushes floating window. To check further we make top layer invisible and repeat the same procedure for next layer.



Once we are happy we can stack images as described in previous tutorials or we can use GMI’C plugin. GMI’C is located under Filters and it opens as separate window. We expand Layers, select Average and set Input layers to All and Output mode to New image.



Clicking Apply or OK button will create new image. If you have new version of GIMP Median is also interesting. Average produces two layers and Median only one, we can stack them again. For final processing you may like to do some contrast stretching, maybe some curves as well.

Thursday, December 6, 2012

RESTful web service for picture upload Android client

In previous tutorial http://grumpyoldprogrammer.blogspot.com/2012/11/image-upload-via-restful-web-service.html I described how to create simple server application and deploy it on Tomcat. Now we are going to take a look at client application.
Simplest is to use Apache HttpComponents Client. It is possible to convert HttpMime jar for Android and import it as library. Since not all classes are required for picture upload we can download source and add the following files to project:

AbstractContentBody.java
ByteArrayBody.java
ContentBody.java
ContentDescriptor.java
FormBodyPart.java
Header.java
HttpMultipart.java
HttpMultipartMode.java
MIME.java
MinimalField.java
MultipartEntity.java
StringBody.java


Naturally whole project like this becomes Apache licensed. Some of those Java files are in org.apache.http.entity.mime.content package and others are in org.apache.http.entity.mime.
In this way we avoid compiling two files FileBody.java and InputStreamBody.java
Now will we go refactoring package names to fit them into project is of minor relevance, I usually do.
We create new Android project and we code onCreate like this:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    try {
        bm = BitmapFactory.decodeFile("/sdcard/DCIM/FinalM8.JPG");
        if(bm==null)
            throw new Exception("no picture!");
        new FetchItemsTask().execute();
    } catch (Exception e) {
        e.printStackTrace();
    }
}


Please note that image path is hardcoded, so change it accordingly. Bitmap bm is loaded, defined as field, and if it is different from null we create and execute AsyncTask to upload picture. To keep things simple as possible we will implement only doInBackground, like this:

protected Void doInBackground(Void... arg0) {
    // TODO Auto-generated method stub
    try {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bm.compress(CompressFormat.JPEG, 50, bos);
        byte[] data = bos.toByteArray();
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost postRequest =
            new HttpPost("http://localhost:8080/WebApplication3/xyz/generic/images");
        ByteArrayBody bab = new ByteArrayBody(data, "FinalM8.JPG");
        MultipartEntity reqEntity = new MultipartEntity(
                HttpMultipartMode.BROWSER_COMPATIBLE);
        reqEntity.addPart("image", bab);
        postRequest.setEntity(reqEntity);
        HttpResponse response = httpClient.execute(postRequest);
        System.out.println("Status is "+response.getStatusLine());
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                response.getEntity().getContent(), "UTF-8"));
        String sResponse;
        StringBuilder s = new StringBuilder();
        while ((sResponse = reader.readLine()) != null) {
            s = s.append(sResponse);
        }
        System.out.println("Response: " + s);
    } catch (Exception e) {
        // handle exception here
        e.printStackTrace();
    }
    return null;
}


Image is compressed on 50%, loaded into byte array and upload is attempted. In order to run code just push onto emulator some image and change path.

Wednesday, November 28, 2012

Image upload via RESTful web service

During some project I had to write Android client for RESTful web service where between other things, image upload was goal. Server was handled by Zaries http://zaries.wordpress.com/ so it was Lisp on Hunchentoot. I didn’t want to start with two unknowns, implementing problematic multipart/form-data on Android and writing from the scratch Lisp web service, so I started searching for simple Java example of upload RESTful web service. I expected something on NetBeans but closest what I managed to find was Jersey hello world example http://www.mkyong.com/webservices/jax-rs/jersey-hello-world-example/ done using Maven. So, here I am writing user friendly tutorial for user friendly NetBeans for millions of prospective Android developers which are not quite comfortable with Java EE development, yet. Android client will be separate article.
This was done on LinuxMint Maya, IDE is NetBeans 7.2 and deployment target is Tomcat 7.0.27.
We start from New Project dialog where from group Java Web we select Web Application. With exception of Server and Settings where we want to target Apache Tomcat during all other steps we accept defaults. If we downloaded bundle, Glassfish is default target.




Now we want to add RESTful web service. We right click on project icon in left pane and select New -> RESTful Web Services from Patterns ...
Again we accept default values with exception of package name where we type in za.org.droid. Before we start coding we add two libraries, those are Jersey 1.8 and JAX-WS 2.2.6. Inside Projects pane we right click on Libraries folder and select Add Library ...


Now we can delete useless GET and PUT Hello World methods generated by IDE and copy and paste this

@POST
@Path("/images")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response imageUpload(@FormDataParam("image") InputStream hereIsImage, @FormDataParam("image") FormDataContentDisposition hereIsName) {
    String path = System.getenv("HOME")+"/tmp/";
    if(hereIsName.getSize()==0) {
        return Response.status(500).entity("image parameter is missing").build();
    }
    String name = hereIsName.getFileName();
    path += name;

    try {
        OutputStream out = new FileOutputStream(new File(path));
        int read;
        byte[] bytes = new byte[1024];
        while ((read = hereIsImage.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
        out.flush();
        out.close();
    } catch (IOException e) {
        return Response.status(500).entity(name + " was not uploaded\n"+e.getMessage()).build();
    }
    return Response.status(200).entity(name + " was uploaded").build();
}


We should create in our $HOME folder tmp folder where images will be saved. We look for image parameter and it will tell us what is image called and also it will contain raw image data. We return response informing client about how successful was upload attempt.
Since we accepted default names for RESTful web service it will have “generic” path assigned, that is important because we use that path to call it.
Only what is left is to do configuration. In WEB-INF folder we create web.xml file and paste the following in:




We can save xml and deploy web application. End-point to call will be http://localhost:8080/WebApplication3/xyz/generic/images, application name WebApplication3 may be different so please change it accordingly. To test upload one can use HttpClient, httpcomponents-client-4.2.1 contains working example. I will add blog about Android client in day or two.

Sunday, November 25, 2012

Final part of Android tutorial

Here we are going to take a look at ContentProvider, subclassing of SimpleCursorAdapter, ListView and assembling of all that into almost usable application.

ContentProvider


Most irritating concept of whole Android platform. That is some kind of grand unified interface to access all data publicly available on system. As we may expect from Internet search oriented company, there is Uri which starts with "content://" then we have “authority” and “base path”, like this:

private static final String AUTHORITY = "za.org.droidika.tutorial.SearchResultProvider";
private static final String TWEETS_BASE_PATH = "tweets";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
        + "/" + TWEETS_BASE_PATH);


That is not all, we also differentiate between operations on unit and bulk operations:

public static final int TWEETS = 100;
public static final int TWEET_ID = 110;
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE
        + "vnd.org.droidika.tutorial/tweets";
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE
        + "vnd.org.droidika.tutorial/tweets";


Further in the source code (available from here https://github.com/FBulovic/grumpyoldprogrammer) we combine our identifiers and load into UriMatcher and we add DB mappings to HashMap. That, with help of SQLiteOpenHelper, is enough of configuration and we can finally implement CRUD methods. I will explain bulk insert and you can find out what is going on in others on you own.

public int bulkInsert(Uri uri, ContentValues[] values) {
    final SQLiteDatabase db = dbInst.getWritableDatabase();
    final int match = sURIMatcher.match(uri);
    switch(match){
    case TWEETS:
        int numInserted= 0;
        db.beginTransaction();
        try {
            SQLiteStatement insert =
                db.compileStatement("insert into " + DbHelper.TABLE_NAME
                        + "(" + DbHelper.USER + "," + DbHelper.DATE
                        + "," + DbHelper.TEXT + ")"
                        +" values " + "(?,?,?)");
            for (ContentValues value : values){
                insert.bindString(1, value.getAsString(DbHelper.USER));
                insert.bindString(2, value.getAsString(DbHelper.DATE));
                insert.bindString(3, value.getAsString(DbHelper.TEXT));
                insert.execute();
            }
            db.setTransactionSuccessful();
            numInserted = values.length;
        } finally {
            db.endTransaction();
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return numInserted;
    default:
        throw new UnsupportedOperationException("unsupported uri: " + uri);
    }
}


We obtain writable instance of DB and we ask URIMatcher do we have right Uri, we do not want to attempt inserting wrong data or do bulk inserting of single row. Next we compile insert statement and open transaction. Inside for loop we assign parameters and execute inserts. If everything vent well we commit transaction and close it inside finally. At the end we ask ContentResolver to notify subscribers about new situation.
We do not pay any attention on resource management, we do not manage cursors, nothing. Suddenly SQLite is friendly and cooperative. That is probably main reason, beside ability to share data across application boundaries, why we should use providers. Naturally there is more, but it happens not in code but inside AndroidManifes.xml
Within application element we place this:

    android:name=".SearchResultProvider"
    android:authorities="za.org.droidika.tutorial.SearchResultProvider" />


Now ContentResolver knows how to find our provider.


Subclassing SimpleCursorAdapter



Since whole idea behind application was implementing something like autocompletion, we type and ListView content changes while we typing, we need custom data adapter. There is only one interesting method to implement:

public Cursor runQuery(CharSequence constraint) {
    String searchString = constraint.toString();
    if (searchString == null || searchString.length() == 0)
        c = contentResolver.query(SearchResultProvider.CONTENT_URI, null, null, null, null);
    else {
        c = contentResolver.query(SearchResultProvider.CONTENT_URI, null, DbHelper.TEXT + " like '%"
                + searchString + "%'", null, null);
    }
    if (c != null) {
        c.moveToFirst();
    }
    return c;
}


If we have search string we do like query and return cursor and if we do not have search string we return everything. Again we do not manage cursor, we just leave everything to Android and it behaves really friendly.

Assembling application


User interface is influenced with SearchableDictionary sample from Android SDK. We type in EditText on top of the screen our search string and data adapter and provider load result into ListView. In order to retrieve data we start “cron job” and it does Twitter search every three minutes and stores data into DB. MainActivity contains example how to create and use menu, how to check is network available and only nontrivial method there is this one:

private void buildList() {
    String[] columns = new String[] { DbHelper.DATE, DbHelper.TEXT,
            DbHelper.USER };
    int[] to = new int[] { R.id.textView2, R.id.textView4, R.id.textView6 };
    Cursor cursor = createCursor();
    final SearchableCursorAdapter dataAdapter = new SearchableCursorAdapter(this, R.layout.list_entry,
            cursor, columns, to);
    ListView listView = (ListView) findViewById(R.id.missingList);
    listView.setAdapter(dataAdapter);
    EditText textFilter = (EditText) findViewById(R.id.myFilter);
    textFilter.addTextChangedListener(new TextWatcher() {

        public void afterTextChanged(Editable s) {
        }

        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
        }

        public void onTextChanged(CharSequence s, int start, int before,
                int count) {
            if (dataAdapter != null) {
                    dataAdapter.getFilter().filter(s.toString());
            }
        }
    });
    dataAdapter.setFilterQueryProvider(dataAdapter);
}


We do setup of ListView, create data adapter, assign data adapter and use TextWatcher to run queries against content provider. Not very complicated.
Again, visit repository https://github.com/FBulovic/grumpyoldprogrammer retrieve code and you have quite comprehensive example, written in such way that is easy to understand. If you are going to use it in production configure HttpClient properly, how is that done is described here http://grumpyoldprogrammer.blogspot.com/2012/10/is-it-safe.html

Saturday, November 24, 2012

Install Oracle JDK in LinuxMint Maya or Ubuntu 12.04 LTS

This primarily describes setup required for Android development on 64 bit LinuxMint Maya what is very much the same as Ubuntu 12.04 but with usable window manager. For those two popular distros we have OpenJDK in repository and we can easily install it using apt-get from terminal or GUI Software Manager. But for Android development only Oracle JDK is supported and Android SDK is 32 bit what implies:

sudo apt-get install ia32-libs

Otherwise we will get confusing error message that for example adb was not found and we attempted to run it.
Current version of Oracle JDK can be downloaded from here http://www.oracle.com/technetwork/java/javase/downloads/index.html
For example we select jdk-7u7-linux-x64.tar.gz accept license and download it using Firefox. When download finishes we typically check signature of it and that is done from terminal, so cd to Downloads and run:

$ md5sum jdk-7u7-linux-x64.tar.gz
15f4b80901111f002894c33a3d78124c  jdk-7u7-linux-x64.tar.gz


Here I do Google search on md5 to be sure that I downloaded right archive. Then we unpack archive simply right clicking on it and selecting Extract Here. That creates directoru jdk1.7.0_07 in Downloads. JDK should be in /usr/lib/jvm unless we want to specify execution path every time, for example this is how it looks on my box:

/usr/lib/jvm $ ls -l
total 20
lrwxrwxrwx 1 root root   24 Oct 31 15:39 default-java -> java-1.6.0-openjdk-amd64
lrwxrwxrwx 1 root root   24 Oct 31 15:39 java-1.6.0-openjdk -> java-1.6.0-openjdk-amd64
lrwxrwxrwx 1 root root   20 Oct 31 15:39 java-1.6.0-openjdk-amd64 -> java-6-openjdk-amd64
lrwxrwxrwx 1 root root   24 Oct 31 15:39 java-6-openjdk -> java-1.6.0-openjdk-amd64
drwxr-xr-x 7 root root 4096 Nov  4 00:00 java-6-openjdk-amd64
drwxr-xr-x 3 root root 4096 May  3  2012 java-6-openjdk-common
lrwxrwxrwx 1 root root   24 Nov  1 11:26 java-6-oracle -> /usr/lib/jvm/jdk1.6.0_37
drwxr-xr-x 5 root root 4096 May  3  2012 java-7-openjdk-amd64
lrwxrwxrwx 1 root root   24 Oct 31 16:52 java-7-oracle -> /usr/lib/jvm/jdk1.7.0_07
drwxr-xr-x 8 root root 4096 Nov  1 11:22 jdk1.6.0_37
drwxr-xr-x 8 root root 4096 Aug 29 03:12 jdk1.7.0_07


In order to move jdk1.7.0_07 from downloads we can use

sudo mv jdk1.7.0_07 /usr/lib/jvm/

we are doing that from terminal in Downloads, or maybe start caja or gnome as root and do it from GUI. If we are in GUI we recursively change ownership to root using properties and if we are doing it from terminal:

sudo chown -R root:root /usr/lib/jvm/jdk1.7.0_07

Now we need symlink which we use later to switch between different versions of Java:

sudo ln -s /usr/lib/jvm/jdk1.7.0_07 /usr/lib/jvm/java-7-oracle

now we can install runtime and compiler:

sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/java-7-oracle/jre/bin/java 2
sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/java-7-oracle/bin/javac 1


That allows us to configure runtime and compiler respectively using the following two:

sudo update-alternatives --config java
sudo update-alternatives --config javac


we need simply to type number of desired version and hit enter. To check what we are actually running we can execute:

javac -version
java -version