将图片压缩成Android上传到服务器的过程
我想写我自己的代码来压缩图片,然后将其上传到服务器。将图片压缩成Android上传到服务器的过程
我看过很多帖子,比如this,还有很多其他帖子,但是到处都只有代码示例。它在任何地方都没有被解释。我无法从给定的代码中理解。
我只想知道压缩图像的整体方法,以便我可以自己开始编写代码。
我不在寻找代码,只有一个人需要遵循的步骤来压缩图像。
我认为Chetan Joshi的答案是迄今为止最接近的答案。但要进一步解释,
“压缩”图像和“缩放”(调整大小)图像是不同的。由于您只是想在上传到服务器时减少网络上的带宽(kb/Mb),因此您最有可能会谈论“缩放”,因为这会对图像的大小产生最大的影响。
请注意,正如其他答案Android一样,您需要使用Bitmaps。您需要使用与Bitmaps相关的API调用来执行您想要的操作。
起点:
如果你让你的应用程序使用相机拍照或从图库中选择,你会得到一个开放的,它允许你打开这样的InputStream:
InputStream is = getContext().getContentResolver().openInputStream(photoUri);
这是第一步。下一部分是你想要的东西的伪代码:
- 获取照片/所选图片的
InputStream
。这只是表示图像的字节流。 - 使用
BitmapFactory.decodeStream(InputStream src)
- 量表(调整大小),使用
Bitmap.createScaledBitmap(src, dstWidth, dstHeight, filter);
位图解码流引入Bitmap
。你必须决定你想要的目标宽度和目标高度。查看下一组伪代码。 - 压缩使用
imageFormat.getBitmapCompressFormat(), 100, output)
的位图,其中输出为ByteArrayOutputStream
- 一个实例现在,您可以拨打
output.toByteArray();
得到的字节数。 - 字节是你想要发送到服务器。
注意有关如何选择目标的宽度和高度可扩展到:
- 决定一个最大高度和最大宽度,说240×240。你会与实际高度进行比较这一点,位图的实际宽度。
- 如果太高(实际高度>最大高度),计算缩放因子是最大高度/实际高度
- 如果太宽(实际宽度>最大宽度),计算缩放因子是最大宽度/实际宽度
- 您的实际比例因子是这两个比例的最低因素
- 返回实际高度*比例系数和实际宽度*比例因子
共有高层次的过程是这样的:
- 打开图像
- 的字节流转换字节成位图
- 量表位图
- 压缩位图
- 转换所述位图回字节
既然你实际上并没有寻找代码(如一个算法编写程序即伪之前写的),这里是学习图像压缩背后的思维过程一个梦幻般的资源Data Compression Theory
有很多种这些算法利用不同的技术来利用所涉及的不同变量。计算复杂度,存储空间,压缩比和保留图像质量都是这些不同算法(或文件格式)寻求优化的因素,通常偏向于另一个属性。例如PNG与JPEG质量与空间的对比
Java提供的ImageIO
API可以帮助压缩图像,并选择压缩质量和因子。 ImageWriter
和ImageWriteParam
提供了开箱即用的功能。
您是否打算根据您的要求自定义其他一些原因编写自己的API?
如果不使用开箱即用的API,高级方法可能是: 1)读取图像文件。 2)使用ImageIO,根据图像类型获取ImageWriter,例如(jpeg,png等) 3)从writer中获取ImageWriteParam对象,并根据需要设置压缩参数。 4)写图片。
让我知道它是否不适合你。
链接中的代码描述的并不是太多的压缩,而是以较低的密度对图像进行采样并缩小比例。所以它不是真正的压缩,而是质量(像素数量和大小)的减少,使其变小。良好的压缩算法通常会找到一种方法来保存图像,而不会过多地影响质量(使用数学和物体),从而占用更少的空间。在Android的
图像压缩意味着我们正在处理位图,而我们则是压缩任何大的图像,以降低那么我们有方法地压缩Bitmap类,但如果原来的位图的大小之间的差异,并希望位图过highr则位图的质量始终减少。
要压缩高质量的位图,我们必须使用递归过程来压缩任何位图,而不是直接从原始高度宽度压缩任何位图到想要的高度和宽度,例如,如果我们的图像大小为1000x1000
,想要宽度和高度300x300
然后我们采用递归过程要做到这一点象下面这样:
1000 x 1000
850 x 850
650 x 650
300 x 300
这样,我们的位图的质量不会降低,但要确保不产生新的位图对象每次都使用相同的位图对象分配压缩位图,否则你必须面对OutOfmemmory问题。
作物图像,然后发送到服务器。其工作良好,
添加依赖于gradle,
compile 'com.soundcloud.android:android-crop:[email protected]'
画廊意图,
private static final int PICK_FROM_FILE = 3;
private Uri mImageCaptureUri=null;
File sdCard = Environment.getExternalStorageDirectory();
String pathName;
File filepath;
Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, PICK_FROM_FILE);
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK)
return;
switch (requestCode) {
case PICK_FROM_FILE:
mImageCaptureUri = data.getData();
// METHOD FOR CROP
beginCrop(mImageCaptureUri);
System.out.println("CHECK_GALLERY_path :" + mImageCaptureUri);
break;
case Crop.REQUEST_CROP:
handleCrop(resultCode, data);
break;
}
}
private void beginCrop(Uri source) {
Uri destination = Uri.fromFile(new File(getCacheDir(), "cropped"));
Crop.of(source, destination).start(this);
}
private void handleCrop(int resultCode, Intent result) {
if (resultCode == RESULT_OK) {
mImageCaptureUri = Crop.getOutput(result);
pathName = mImageCaptureUri.getPath();
//uploadImageToServer();
// getImageUri(mImageCaptureUri);
Picasso.with(Activity_My_Account.this).load(mImageCaptureUri).into(getimage); //IMAGE SAVE TO STORAGE
getImageUri(mImageCaptureUri);
System.out.println("path_name+++" + mImageCaptureUri);
} else if (resultCode == Crop.RESULT_ERROR) {
Toast.makeText(this, Crop.getError(result).getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void getImageUri(Uri mImageCaptureUri) {
Bitmap photo = null;
try {
InputStream image_stream = getContentResolver().openInputStream(mImageCaptureUri);
java.util.Date date = new java.util.Date();
pathName = sdCard + "/" + "LEUF";
File myDir = new File(pathName);
System.out.println("GET_CHECK_PATH_NAME :" + pathName);
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";
File file = new File(myDir, fname);
// if (file.exists()) file.delete();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
Bitmap bitmapOrg = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(image_stream), 350, 350, false);
photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
filepath=file;
try {
// file.createNewFile();
FileOutputStream fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.flush();
fo.close();
} catch (IOException e) {
e.printStackTrace();
}
//here call to upload image to server
public void UploadProfilePic(filepath){
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
你可以只使用了Android SDK - bitmap.compress();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
if (myBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos)) {
//image is now compressed into the output stream
uploadImage(bos);
} else {
//compress failed
}
可以随时检查Android源代码,以更多地了解它,但如果你是Android开发人员,我觉得把时间学习如何压缩不应该是你的主要焦点特别是当你有这样的简单的解决方案,如果你仍然认为你我会先学习如何先压缩文件,然后我会移动到图像,然后我会看看源代码
看看[this](https://developer.android.com/topic/performance/network-xfer.html)了解图像压缩。要了解作为初学者的压缩,请查看[LZW Compression](https://www.youtube.com/watch?v=rZ-JRCPv_O8)。 –