blob: 32ed8364e422f1089e757dbace8889b097950c82 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* 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://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License 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.
*/
package com.cooliris.media;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.MediaStore;
import android.widget.Toast;
import com.cooliris.app.App;
import com.cooliris.app.Res;
public class Utils {
private static final int UNCONSTRAINED = -1;
public static void playVideo(final Context context, final MediaItem item) {
// this is a video
App.get(context).getHandler().post(new Runnable() {
public void run() {
try {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(item.mContentUri));
intent.setDataAndType(Uri.parse(item.mContentUri), item.mMimeType);
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(context, context.getResources().getString(Res.string.video_err), Toast.LENGTH_SHORT).show();
}
}
});
}
public static final void writeUTF(DataOutputStream dos, String string) throws IOException {
if (string == null) {
dos.writeUTF(new String());
} else {
dos.writeUTF(string);
}
}
public static final String readUTF(DataInputStream dis) throws IOException {
String retVal = dis.readUTF();
if (retVal.length() == 0)
return null;
return retVal;
}
public static final Bitmap resizeBitmap(Bitmap bitmap, int maxSize) {
int srcWidth = bitmap.getWidth();
int srcHeight = bitmap.getHeight();
int width = maxSize;
int height = maxSize;
boolean needsResize = false;
if (srcWidth > srcHeight) {
if (srcWidth > maxSize) {
needsResize = true;
height = ((maxSize * srcHeight) / srcWidth);
}
} else {
if (srcHeight > maxSize) {
needsResize = true;
width = ((maxSize * srcWidth) / srcHeight);
}
}
if (needsResize) {
Bitmap retVal = Bitmap.createScaledBitmap(bitmap, width, height, true);
return retVal;
} else {
return bitmap;
}
}
private static final long POLY64REV = 0x95AC9329AC4BC9B5L;
private static final long INITIALCRC = 0xFFFFFFFFFFFFFFFFL;
private static boolean init = false;
private static long[] CRCTable = new long[256];
/**
* A function thats returns a 64-bit crc for string
*
* @param in
* : input string
* @return 64-bit crc value
*/
public static final long Crc64Long(String in) {
if (in == null || in.length() == 0) {
return 0;
}
// http://bioinf.cs.ucl.ac.uk/downloads/crc64/crc64.c
long crc = INITIALCRC, part;
if (!init) {
for (int i = 0; i < 256; i++) {
part = i;
for (int j = 0; j < 8; j++) {
int value = ((int) part & 1);
if (value != 0)
part = (part >> 1) ^ POLY64REV;
else
part >>= 1;
}
CRCTable[i] = part;
}
init = true;
}
int length = in.length();
for (int k = 0; k < length; ++k) {
char c = in.charAt(k);
crc = CRCTable[(((int) crc) ^ c) & 0xff] ^ (crc >> 8);
}
return crc;
}
/**
* A function that returns a human readable hex string of a Crx64
*
* @param in
* : input string
* @return hex string of the 64-bit CRC value
*/
public static final String Crc64(String in) {
if (in == null)
return null;
long crc = Crc64Long(in);
/*
* The output is done in two parts to avoid problems with
* architecture-dependent word order
*/
int low = ((int) crc) & 0xffffffff;
int high = ((int) (crc >> 32)) & 0xffffffff;
String outVal = Integer.toHexString(high) + Integer.toHexString(low);
return outVal;
}
public static long getBucketIdFromUri(final ContentResolver cr, final Uri uri) {
if (uri.getScheme().equals("file")) {
String string = "/";
List<String> paths = uri.getPathSegments();
int numPaths = paths.size();
for (int i = 0; i < numPaths - 1; ++i) {
string += paths.get(i);
if (i != numPaths - 2)
string += "/";
}
return LocalDataSource.getBucketId(string);
} else {
Cursor cursor = null;
try {
long id = ContentUris.parseId(uri);
cursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.ImageColumns.BUCKET_ID }, MediaStore.Images.ImageColumns._ID + "=" + id,
null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
long setVal = cursor.getLong(0);
cursor.close();
return setVal;
}
}
cursor = cr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Video.VideoColumns.BUCKET_ID }, MediaStore.Images.ImageColumns._ID + "=" + id,
null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
long setVal = cursor.getLong(0);
cursor.close();
return setVal;
}
}
} catch (Exception e) {
;
}
return Shared.INVALID;
}
}
public static String getBucketNameFromUri(final ContentResolver cr, final Uri uri) {
final long bucketId = getBucketIdFromUri(cr, uri);
if (bucketId != Shared.INVALID) {
try {
Cursor cursor = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME },
MediaStore.Images.ImageColumns.BUCKET_ID + "='" + bucketId + "'", null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
String setName = cursor.getString(0);
cursor.close();
return setName;
}
}
cursor = cr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Video.VideoColumns.BUCKET_DISPLAY_NAME }, MediaStore.Video.VideoColumns.BUCKET_ID
+ "='" + bucketId + "'", null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
String setName = cursor.getString(0);
cursor.close();
return setName;
}
}
} catch (Exception e) {
;
}
}
return "";
}
// Copies src file to dst file.
// If the dst file does not exist, it is created
public static void Copy(File src, File dst) throws IOException {
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
copyStream(in, out);
}
public static void copyStream(InputStream in, OutputStream out) throws IOException {
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
/*
* Compute the sample size as a function of minSideLength
* and maxNumOfPixels.
* minSideLength is used to specify that minimal width or height of a
* bitmap.
* maxNumOfPixels is used to specify the maximal size in pixels that is
* tolerable in terms of memory usage.
*
* The function returns a sample size based on the constraints.
* Both size and minSideLength can be passed in as IImage.UNCONSTRAINED,
* which indicates no care of the corresponding constraint.
* The functions prefers returning a sample size that
* generates a smaller bitmap, unless minSideLength = IImage.UNCONSTRAINED.
*
* Also, the function rounds up the sample size to a power of 2 or multiple
* of 8 because BitmapFactory only honors sample size this way.
* For example, BitmapFactory downsamples an image by 2 even though the
* request is 3. So we round up the sample size to avoid OOM.
*/
public static int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,
maxNumOfPixels);
int roundedSize;
if (initialSize <= 8 ) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}
return roundedSize;
}
public static int computeInitialSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;
int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 :
(int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == UNCONSTRAINED) ? 128 :
(int) Math.min(Math.floor(w / minSideLength),
Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
// return the larger one when there is no overlapping zone.
return lowerBound;
}
if ((maxNumOfPixels == UNCONSTRAINED) &&
(minSideLength == UNCONSTRAINED)) {
return 1;
} else if (minSideLength == UNCONSTRAINED) {
return lowerBound;
} else {
return upperBound;
}
}
}