MTK图片处理的工具类
来源:互联网 发布:mac换主板 编辑:程序博客网 时间:2024/05/22 17:05
import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.lang.Math;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Bitmap.CompressFormat;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.drawable.Drawable;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.Typeface;import android.media.ExifInterface;import android.util.Log;import com.android.videoeditor.R;import com.android.videoeditor.service.MovieOverlay;/** * Image utility methods */public class ImageUtils { /** * Logging */ private static final String TAG = "ImageUtils"; // The resize paint private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG); // The match aspect ratio mode for scaleImage public static int MATCH_SMALLER_DIMENSION = 1; public static int MATCH_LARGER_DIMENSION = 2; /** * It is not possible to instantiate this class */ private ImageUtils() { } /** * Resize a bitmap to the specified width and height. * * @param filename The filename * @param width The thumbnail width * @param height The thumbnail height * @param match MATCH_SMALLER_DIMENSION or MATCH_LARGER_DIMMENSION * * @return The resized bitmap */ public static Bitmap scaleImage(String filename, int width, int height, int match) throws IOException { final BitmapFactory.Options dbo = new BitmapFactory.Options(); dbo.inJustDecodeBounds = true; BitmapFactory.decodeFile(filename, dbo); final int nativeWidth = dbo.outWidth; final int nativeHeight = dbo.outHeight; final Bitmap srcBitmap; float scaledWidth, scaledHeight; final BitmapFactory.Options options = new BitmapFactory.Options(); if (nativeWidth > width || nativeHeight > height) { float dx = ((float) nativeWidth) / ((float) width); float dy = ((float) nativeHeight) / ((float) height); float scale = (match == MATCH_SMALLER_DIMENSION) ? Math.max(dx,dy) : Math.min(dx,dy); scaledWidth = nativeWidth / scale; scaledHeight = nativeHeight / scale; // Create the bitmap from file. options.inSampleSize = (scale > 1.0f) ? ((int) scale) : 1; } else { scaledWidth = width; scaledHeight = height; options.inSampleSize = 1; } srcBitmap = BitmapFactory.decodeFile(filename, options); if (srcBitmap == null) { throw new IOException("Cannot decode file: " + filename); } // Create the canvas bitmap. final Bitmap bitmap = Bitmap.createBitmap(Math.round(scaledWidth), Math.round(scaledHeight), Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(srcBitmap, new Rect(0, 0, srcBitmap.getWidth(), srcBitmap.getHeight()), new Rect(0, 0, Math.round(scaledWidth), Math.round(scaledHeight)), sResizePaint); // Release the source bitmap srcBitmap.recycle(); return bitmap; } /** * Rotate a JPEG according to the EXIF data * * @param inputFilename The name of the input file (must be a JPEG filename) * @param outputFile The rotated file * * @return true if the image was rotated */ public static boolean transformJpeg(String inputFilename, File outputFile) throws IOException { final ExifInterface exif = new ExifInterface(inputFilename); final int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Exif orientation: " + orientation); } // Degrees by which we rotate the image. int degrees = 0; switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: { degrees = 90; break; } case ExifInterface.ORIENTATION_ROTATE_180: { degrees = 180; break; } case ExifInterface.ORIENTATION_ROTATE_270: { degrees = 270; break; } } rotateAndScaleImage(inputFilename, degrees, outputFile); return degrees != 0; } /** * Rotates an image according to the specified {@code orientation}. * We limit the number of pixels of the scaled image. Thus the image * will typically be downsampled. * * @param inputFilename The input filename * @param orientation The rotation angle * @param outputFile The output file */ private static void rotateAndScaleImage(String inputFilename, int orientation, File outputFile) throws FileNotFoundException, IOException { // In order to avoid OutOfMemoryError when rotating the image, we scale down the size of the // input image. We set the maxmimum number of allowed pixels to 2M and scale down the image // accordingly. // Determine width and height of the original bitmap without allocating memory for it, BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inJustDecodeBounds = true; BitmapFactory.decodeFile(inputFilename, opt); // Determine the scale factor based on the ratio of pixel count over max allowed pixels. final int width = opt.outWidth; final int height = opt.outHeight; final int pixelCount = width * height; final int MAX_PIXELS_FOR_SCALED_IMAGE = 2000000; double scale = Math.sqrt( (double) pixelCount / MAX_PIXELS_FOR_SCALED_IMAGE); if (scale <= 1) { scale = 1; } else { // Make the scale factor a power of 2 for faster processing. Also the resulting bitmap may // have different dimensions than what has been requested if the scale factor is not a // power of 2. scale = nextPowerOf2((int) Math.ceil(scale)); } // Load the scaled image. BitmapFactory.Options opt2 = new BitmapFactory.Options(); opt2.inSampleSize = (int) scale; final Bitmap scaledBmp = BitmapFactory.decodeFile(inputFilename, opt2); // Rotation matrix used to rotate the image. final Matrix mtx = new Matrix(); mtx.postRotate(orientation); final Bitmap rotatedBmp = Bitmap.createBitmap(scaledBmp, 0, 0, scaledBmp.getWidth(), scaledBmp.getHeight(), mtx, true); if (rotatedBmp != scaledBmp) scaledBmp.recycle(); // Save the rotated image to a file in the current project folder final FileOutputStream fos = new FileOutputStream(outputFile); rotatedBmp.compress(CompressFormat.JPEG, 100, fos); fos.close(); rotatedBmp.recycle(); } /** * Returns the next power of two. * Returns the input if it is already power of 2. * Throws IllegalArgumentException if the input is <= 0 or the answer overflows. */ private static int nextPowerOf2(int n) { if (n <= 0 || n > (1 << 30)) throw new IllegalArgumentException(); n -= 1; n |= n >> 16; n |= n >> 8; n |= n >> 4; n |= n >> 2; n |= n >> 1; return n + 1; } /** * Build an overlay image * * @param context The context * @param inputBitmap If the bitmap is provided no not create a new one * @param overlayType The overlay type * @param title The title * @param subTitle The subtitle * @param width The width * @param height The height * * @return The bitmap */ public static Bitmap buildOverlayBitmap(Context context, Bitmap inputBitmap, int overlayType, String title, String subTitle, int width, int height) { final Bitmap overlayBitmap; if (inputBitmap == null) { overlayBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); } else { overlayBitmap = inputBitmap; } overlayBitmap.eraseColor(Color.TRANSPARENT); final Canvas canvas = new Canvas(overlayBitmap); switch (overlayType) { case MovieOverlay.OVERLAY_TYPE_CENTER_1: { drawCenterOverlay(context, canvas, R.drawable.overlay_background_1, Color.WHITE, title, subTitle, width, height); break; } case MovieOverlay.OVERLAY_TYPE_BOTTOM_1: { drawBottomOverlay(context, canvas, R.drawable.overlay_background_1, Color.WHITE, title, subTitle, width, height); break; } case MovieOverlay.OVERLAY_TYPE_CENTER_2: { drawCenterOverlay(context, canvas, R.drawable.overlay_background_2, Color.BLACK, title, subTitle, width, height); break; } case MovieOverlay.OVERLAY_TYPE_BOTTOM_2: { drawBottomOverlay(context, canvas, R.drawable.overlay_background_2, Color.BLACK, title, subTitle, width, height); break; } default: { throw new IllegalArgumentException("Unsupported overlay type: " + overlayType); } } return overlayBitmap; } /** * Build an overlay image in the center third of the image * * @param context The context * @param canvas The canvas * @param drawableId The overlay background drawable if * @param textColor The text color * @param title The title * @param subTitle The subtitle * @param width The width * @param height The height */ private static void drawCenterOverlay(Context context, Canvas canvas, int drawableId, int textColor, String title, String subTitle, int width, int height) { final int INSET = width / 72; final int startHeight = (height / 3) + INSET; final Drawable background = context.getResources().getDrawable(drawableId); background.setBounds(INSET, startHeight, width - INSET, ((2 * height) / 3) - INSET); background.draw(canvas); final Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); p.setTypeface(Typeface.DEFAULT_BOLD); p.setColor(textColor); final int titleFontSize = height / 12; final int maxWidth = width - (2 * INSET) - (2 * titleFontSize); final int startYOffset = startHeight + (height / 6); if (title != null) { p.setTextSize(titleFontSize); title = StringUtils.trimText(title, p, maxWidth); canvas.drawText(title, (width - (2 * INSET) - p.measureText(title)) / 2, startYOffset - p.descent(), p); } if (subTitle != null) { p.setTextSize(titleFontSize - 6); subTitle = StringUtils.trimText(subTitle, p, maxWidth); canvas.drawText(subTitle, (width - (2 * INSET) - p.measureText(subTitle)) / 2, startYOffset - p.ascent(), p); } } /** * Build an overlay image in the lower third of the image * * @param context The context * @param canvas The canvas * @param drawableId The overlay background drawable if * @param textColor The text color * @param title The title * @param subTitle The subtitle * @param width The width * @param height The height */ private static void drawBottomOverlay(Context context, Canvas canvas, int drawableId, int textColor, String title, String subTitle, int width, int height) { final int INSET = width / 72; final int startHeight = ((2 * height) / 3) + INSET; final Drawable background = context.getResources().getDrawable(drawableId); background.setBounds(INSET, startHeight, width - INSET, height - INSET); background.draw(canvas); final Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); p.setTypeface(Typeface.DEFAULT_BOLD); p.setColor(textColor); final int titleFontSize = height / 12; final int maxWidth = width - (2 * INSET) - (2 * titleFontSize); final int startYOffset = startHeight + (height / 6); if (title != null) { p.setTextSize(titleFontSize); title = StringUtils.trimText(title, p, maxWidth); canvas.drawText(title, (width - (2 * INSET) - p.measureText(title)) / 2, startYOffset - p.descent(), p); } if (subTitle != null) { p.setTextSize(titleFontSize - 6); subTitle = StringUtils.trimText(subTitle, p, maxWidth); canvas.drawText(subTitle, (width - (2 * INSET) - p.measureText(subTitle)) / 2, startYOffset - p.ascent(), p); } } /** * Build an overlay preview image * * @param context The context * @param canvas The canvas * @param overlayType The overlay type * @param title The title * @param subTitle The subtitle * @param startX The start horizontal position * @param startY The start vertical position * @param width The width * @param height The height */ public static void buildOverlayPreview(Context context, Canvas canvas, int overlayType, String title, String subTitle, int startX, int startY, int width, int height) { switch (overlayType) { case MovieOverlay.OVERLAY_TYPE_CENTER_1: case MovieOverlay.OVERLAY_TYPE_BOTTOM_1: { drawOverlayPreview(context, canvas, R.drawable.overlay_background_1, Color.WHITE, title, subTitle, startX, startY, width, height); break; } case MovieOverlay.OVERLAY_TYPE_CENTER_2: case MovieOverlay.OVERLAY_TYPE_BOTTOM_2: { drawOverlayPreview(context, canvas, R.drawable.overlay_background_2, Color.BLACK, title, subTitle, startX, startY, width, height); break; } default: { throw new IllegalArgumentException("Unsupported overlay type: " + overlayType); } } } /** * Build an overlay image in the lower third of the image * * @param context The context * @param canvas The canvas * @param drawableId The overlay background drawable if * @param title The title * @param subTitle The subtitle * @param width The width * @param height The height */ private static void drawOverlayPreview(Context context, Canvas canvas, int drawableId, int textColor, String title, String subTitle, int startX, int startY, int width, int height) { final int INSET = 0; final int startHeight = startY + INSET; final Drawable background = context.getResources().getDrawable(drawableId); background.setBounds(startX + INSET, startHeight, startX + width - INSET, height - INSET + startY); background.draw(canvas); final Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); p.setTypeface(Typeface.DEFAULT_BOLD); p.setColor(textColor); final int titleFontSize = height / 4; final int maxWidth = width - (2 * INSET) - (2 * titleFontSize); final int startYOffset = startHeight + (height / 2); if (title != null) { p.setTextSize(titleFontSize); title = StringUtils.trimText(title, p, maxWidth); canvas.drawText(title, (width - (2 * INSET) - p.measureText(title)) / 2, startYOffset - p.descent(), p); } if (subTitle != null) { p.setTextSize(titleFontSize - 6); subTitle = StringUtils.trimText(subTitle, p, maxWidth); canvas.drawText(subTitle, (width - (2 * INSET) - p.measureText(subTitle)) / 2, startYOffset - p.ascent(), p); } } private static final boolean LOG = true; //please see MediaItemView for more info private static final float MAX_ASPECT_RATIO = 18.2F;//18.2 = 2048 * 2048 / 480 / 480 //generateProjectThumbnail() in VideoEditorImpl and other functions in both java/native layer //will occur exception if we import big ratio image. public static boolean isPermitedImage(String filename) { boolean permited = true; float ratio = 0; int width = 0, height = 0; if (filename != null) { BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inJustDecodeBounds = true; BitmapFactory.decodeFile(filename, opt); width = opt.outWidth; height = opt.outHeight; if (width < 16 || height < 16) { //MDP cannot decode image file size < 4*4, here app set it to 16*16 for FPM's dicision. //MediaImageItem will >> 1 << 1, if width or height <= 1, it will be 0. permited = false; } else { ratio = width > height ? ((float)width / height) : ((float)height / width); if (ratio > MAX_ASPECT_RATIO) { permited = false; } } } if (LOG) MtkLog.v(TAG, "isPermitedRatio(" + filename + ") width=" + width + ", height=" + height + ", ratio=" + ratio + ", return " + permited); return permited; }}
0 0
- MTK图片处理的工具类
- 处理图片的工具类
- 处理图片的工具类
- 处理图片的工具类
- MTK图片处理
- 图片处理工具类
- 图片处理工具类
- 图片处理工具类
- 图片处理工具类
- 图片处理工具类
- 图片处理工具类
- 图片处理工具类
- 图片处理工具类
- android 处理图片的工具类
- Java的图片处理工具类
- Java的图片处理工具类
- Java的图片处理工具类
- Java的图片处理工具类
- ConcurrentHashMap 高并发性的实现机制
- c++之引用,指针 ;
- android的问题
- 矩阵的旋转
- ClassNotFoundException: org.hibernate.hql.ast.HqlToken问题
- MTK图片处理的工具类
- c#避免弹出窗口获取焦点
- java中HashSet详解
- android的混乱
- 软件工程(需求分析)
- LeetCode—Max Points on a Line解题报告
- javaScript 运算符 && 和 || 的返回值
- javascript中的变量、作用域
- POJ 1195 Mobile Phone 最基础的二维线段树