我正在使用以下代码进行图像压缩。
代码压缩大于 2 MB 的图像文件。
但此代码需要时间,而且图像质量保持纯净。
public static String compressImage(String imagePath, Context context)
{
String resizeImagePath = null;
String filePath = imagePath;
CustomLogHandler.printDebug(TAG, "resizeImagePath:" + imagePath);
Bitmap scaledBitmap = null;
int imageScal = 1;
// File size greater then 2mb
DecimalFormat df = new DecimalFormat("0.00");
File imgFile = new File(filePath);
double bytes = imgFile.length();
double kilobytes = (bytes / 1024);
double megabytes = (kilobytes / 1024);
AppConfig.makeLog(TAG, "image size in mb:" + df.format(megabytes), 0);
double filesize = Double.parseDouble(df.format(megabytes));
if (filesize > 2.00f)
{
for (int i = 0; i < filesize; i = i + 2)
{
imageScal++;
}
int remind = imageScal / 2;
if (remind != 0)
{
imageScal = imageScal + 1;
}
makeLog(TAG, "image scale:" + imageScal, 0);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
float maxHeight = 4000;
float maxWidth = 6000;
// float imgRatio = actualWidth / actualHeight;
// float maxRatio = maxWidth / maxHeight;
if (actualHeight > maxHeight)
{
imageScal = imageScal + 4;
}
if (actualWidth > maxWidth)
{
imageScal = imageScal + 8;
}
// if (actualHeight > maxHeight || actualWidth > maxWidth)
// {
// if (imgRatio < maxRatio)
// {
// imgRatio = maxHeight / actualHeight;
// actualWidth = (int) (imgRatio * actualWidth);
// actualHeight = (int) maxHeight;
//
// }
// else if (imgRatio > maxRatio)
// {
// imgRatio = maxWidth / actualWidth;
// actualHeight = (int) (imgRatio * actualHeight);
// actualWidth = (int) maxWidth;
// }
// else
// {
// actualHeight = (int) maxHeight;
// actualWidth = (int) maxWidth;
//
// }
// }
// options.inSampleSize = utils.calculateInSampleSize(options, actualWidth, actualHeight);
options.inSampleSize = imageScal;
options.inJustDecodeBounds = false;
options.inDither = true;
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try
{
bmp = BitmapFactory.decodeFile(filePath, options);
bmp = decodeFile(filePath);
}
catch (OutOfMemoryError exception)
{
exception.printStackTrace();
}
boolean done = false;
while (!done)
{
try
{
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
// scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
done = true;
}
catch (OutOfMemoryError exception)
{
// 15923 × 1790
// 5616 × 3744
// 8150 × 9154
actualWidth = actualWidth - ((actualWidth * 2) / 100);
actualHeight = actualHeight - ((actualHeight * 2) / 100);
// scaledBitmap = Bitmap.createBitmap(5616, 3744, Bitmap.Config.ARGB_8888);
exception.printStackTrace();
}
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
// Resize image stored in sdcard
FileOutputStream out = null;
// filename =AppConfig.fileTosaveMedia(context, FileType.IMAGE, true).getAbsolutePath();
int compress = 50;
try
{
do
{
imgFile = AppConfig.fileTosaveMedia(context, FileType.IMAGE, true);
out = new FileOutputStream(imgFile);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, compress, out);
resizeImagePath = imgFile.getAbsolutePath();
// Thread.sleep(15000);
// imgFile = new File(filename);
bytes = imgFile.length();
kilobytes = (bytes / 1024);
megabytes = (kilobytes / 1024);
System.out.println("resized image size in mb:" + df.format(megabytes));
filesize = Double.parseDouble(df.format(megabytes));
if (filesize > 2.00f)
{
compress = 30;
}
} while (filesize > 2.00f);
scaledBitmap.recycle();
}
catch (Exception e)
{
e.printStackTrace();
}
}
else
{
FileOutputStream out = null;
// FileInputStream in = null;
imgFile = AppConfig.fileTosaveMedia(context, FileType.IMAGE, true);
resizeImagePath = imgFile.getAbsolutePath();
InputStream in = null;
OutputStream outTemp = null;
try
{
// create output directory if it doesn't exist
in = new FileInputStream(filePath);
outTemp = new FileOutputStream(resizeImagePath);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1)
{
outTemp.write(buffer, 0, read);
}
in.close();
in = null;
// write the output file (You have now copied the file)
outTemp.flush();
outTemp.close();
outTemp = null;
}
catch (FileNotFoundException fnfe1)
{
Log.e("tag", fnfe1.getMessage());
}
catch (Exception e)
{
Log.e("tag", e.getMessage());
}
// try
// {
// Bitmap bmp = decodeFile(filePath);
// // in = new FileInputStream(new File(imagePath));
// // persistImage(bitmap, name);
// out = new FileOutputStream(resizeImagePath);
// bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
// out.flush();
// out.close();
// // FileIO.copyStream(in, out);
// }
// catch (Exception e)
// {
// e.printStackTrace();
// }
}
CustomLogHandler.printDebug(TAG, "resizeImagePath:" + resizeImagePath);
return resizeImagePath;
}
我花了很多时间在 Google 搜索和阅读博客上。然后在创建上面的代码后,我发现this .
上面的代码正确吗?或者有没有其他库可以用来压缩图片?
请帮帮我。
最佳答案
试试下面的代码:-
public String compressImage(String imageUri) {
String filePath = getRealPathFromURI(imageUri);
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
// by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
// you try the use the bitmap here, you will get null.
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
// max Height and width values of the compressed image is taken as 816x612
float maxHeight = 816.0f;
float maxWidth = 612.0f;
float imgRatio = actualWidth / actualHeight;
float maxRatio = maxWidth / maxHeight;
// width and height values are set maintaining the aspect ratio of the image
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) { imgRatio = maxHeight / actualHeight; actualWidth = (int) (imgRatio * actualWidth); actualHeight = (int) maxHeight; } else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
// setting inSampleSize value allows to load a scaled down version of the original image
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
// inJustDecodeBounds set to false to load the actual bitmap
options.inJustDecodeBounds = false;
// this options allow android to claim the bitmap memory if it runs low on memory
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try {
// load the bitmap from its path
bmp = BitmapFactory.decodeFile(filePath, options);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight,Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
// check the rotation of the image and display it properly
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif: " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
true);
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream out = null;
String filename = getFilename();
try {
out = new FileOutputStream(filename);
// write the compressed bitmap at the destination specified by filename.
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return filename;
}
有关信息,请参阅以下链接:-
http://voidcanvas.com/whatsapp-like-image-compression-in-android/
关于android - 图像压缩,如 Whatsapp 和 Android 上的其他信使,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26928597/
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问
我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新rubygems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent
我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path