| /* |
| * 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; |
| } |
| } |
| |
| } |