android图片压缩上传,php服务器按照压缩比例将图片放大为原图大小后严重失真,怎么解决?

yingyoulan 2013-07-25 07:02:27
如果我直接上传原图是没有任何问题的,但是我要的是将图片进行压缩后再上传,php服务器再根据接收的图片和压缩比例,将接收的图片按比例放大为原图的大小。这些都做到了,可问题是图片失真

下面贴出我的部分java客户端代码和php服务器端代码,大家帮我看看问题出在哪里:

public class myThread extends Thread{

@Override
public void run() {
// TODO Auto-generated method stub
String r = null;
upload_fail = new ArrayList<HashMap<String, String>>();
if (!catid.equals(null)) {
for (HashMap<String, String> map : path_list) {
String path = map.get("img_path");
Bitmap bit = BitmapFactory.decodeFile(path);
float pc = (float) 100 / (float) bit.getWidth();//压缩比例
Bitmap bit2 = resize_img(bit, pc);//压缩bitmap
String filename = path.substring(path.lastIndexOf("/") + 1);
File file = saveMyBitmap(filename, bit2);

//File file = new File(path);//若上传原图则用这一行代码代替上面5行即可
upload_res = UploadUtil.uploadFile(file, pc, actionUrl, catid, s_sessid, s_psnId);//上传(返回一个HashMap)

String result = upload_res.get("ans").toString();
if (!result.equals("success")) {
//失败
HashMap<String, String> fail_map = new HashMap<String, String>();
fail_map.put("name", file.getName());
fail_map.put("path", path);
upload_fail.add(fail_map);
} else {
//成功
file.delete();
bit2.recycle();
bit2 = null;
System.gc();
upload_success.add(map.get("thrum_path"));
}
}
s_psnId = upload_res.get("sess_psnId").toString();
s_sessid = upload_res.get("sessionId").toString();
if (upload_fail.size() == 0) {
//全部成功
r = "success";
}else {
if (upload_success.size() == 0) {
//全部失败
r = upload_res.get("ans").toString();
} else {
//部分失败
r = "对不起,图片 [ ";
for (HashMap<String, String> map : upload_fail) {
r += map.get("name") + " ";
}
r += "] 上传失败!";
}

}
} else {
r = "请选择相册";
}

Message msg = myHand.obtainMessage();
Bundle b = new Bundle();
b.putString("res", r);
msg.setData(b);
myHand.sendMessage(msg);
}

}

//压缩bitmap
private Bitmap resize_img(Bitmap bitmap, float pc) {

Matrix matrix = new Matrix();
Log.i("mylog2", "缩放比例--" + pc);
matrix.postScale(pc, pc); // 长和宽放大缩小的比例
Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);

bitmap.recycle();
bitmap = null;
System.gc();

int width = resizeBmp.getWidth();
int height = resizeBmp.getHeight();
Log.i("mylog2", "按比例缩小后宽度--" + width);
Log.i("mylog2", "按比例缩小后高度--" + height);

return resizeBmp;
}

//将压缩的bitmap保存到sdcard卡临时文件夹img_interim,用于上传
@SuppressLint("SdCardPath")
public File saveMyBitmap(String filename, Bitmap bit) {
File dir = new File("/sdcard/img_interim/");
if (!dir.exists()) {
dir.mkdir();
}
File f = new File("/sdcard/img_interim/" + filename);
try {
f.createNewFile();
FileOutputStream fOut = null;
fOut = new FileOutputStream(f);
bit.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
f = null;
e1.printStackTrace();
}

return f;
}

下面是上传工具类的代码:

public class UploadUtil {

private static final String TAG = "mylog2";
private static final int TIME_OUT = 10 * 1000; // 超时时间
private static final String CHARSET = "utf-8"; // 设置编码

/**
*
* 上传文件到服务器
* @param file 需要上传的文件
* @param RequestURL 请求的rul
* @return 返回响应的内容
*/
public static HashMap<String, Object> uploadFile(File file, float pc, String RequestURL,
String catid, String sessionid, String psnid) {
HashMap<String, Object> response_map = new HashMap<String, Object>();
int res = 0;
String result = null;
String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
String PREFIX = "--", LINE_END = "\r\n";
String CONTENT_TYPE = "multipart/form-data"; // 内容类型
try {
RequestURL += "?sessionId=" + sessionid + "&sess_psnId=" + psnid;
RequestURL += "&catid=" + catid + "&pc=" + pc;
URL url = new URL(RequestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(TIME_OUT);
conn.setConnectTimeout(TIME_OUT);
conn.setDoInput(true); // 允许输入流
conn.setDoOutput(true); // 允许输出流
conn.setUseCaches(false); // 不允许使用缓存
conn.setRequestMethod("GET"); // 请求方式
conn.setInstanceFollowRedirects(true);
conn.setRequestProperty("Charset", CHARSET); // 设置编码
conn.setRequestProperty("connection", "keep-alive");
conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary="
+ BOUNDARY);
conn.connect();
if (file != null) {
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());

StringBuffer sb = new StringBuffer();
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINE_END);

sb.append("Content-Disposition: form-data; name=\"uploadedimg\"; filename=\""
+ file.getName() + "\"" + LINE_END);

sb.append("Content-Type: application/octet-stream; charset="
+ CHARSET + LINE_END);

sb.append(LINE_END);

dos.write(sb.toString().getBytes());

InputStream is = new FileInputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
while ((len = is.read(bytes)) != -1) {
dos.write(bytes, 0, len);
}
is.close();
dos.write(LINE_END.getBytes());
byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END)
.getBytes();
dos.write(end_data);

dos.flush();

//获取响应码 200=成功 当响应成功,获取响应的流
res = conn.getResponseCode();
if (res == 200) {
InputStream input = conn.getInputStream();
StringBuffer sb1 = new StringBuffer();
int ss;
while ((ss = input.read()) != -1) {
sb1.append((char) ss);
}
result = sb1.toString();
Log.i("mylog2", "--" + result);
result = result.substring(result.indexOf("{"));
try {
JSONObject obj = new JSONObject(result);
String info = obj.getString("ans");
if (info.equals("success")) {
response_map.put("catid", obj.getString("catid"));
}
response_map.put("ans", info);
response_map.put("sessionId", obj.getString("sessionid"));
response_map.put("sess_psnId", obj.getString("session_psn_id"));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
Log.e(TAG, "request error");
}

}

} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response_map;

}

}

php服务器端代码:

$ans = array();

$pc = $_GET['pc'];

$ans['ans'] = "";
if (isset($_FILES['uploadedimg'])) {
$target_path = $_SERVER['DOCUMENT_ROOT']."/uploads/";//接收文件目录
$file_name = basename($_FILES['uploadedimg']['name']);
$str = explode('.', $file_name);
$img_type = $str[count($str) - 1];
$target_path .= $file_name;
if (move_uploaded_file($_FILES['uploadedimg']['tmp_name'], $target_path)) {
$src_info = @getimagesize($target_path);
$src_w = $src_info[0];
$src_h = $src_info[1];
$dst_w = $src_w / $pc;
$dst_h = $src_h / $pc;

$ans['imginfo'] = round($dst_w) . "--" + round($dst_h);

if($img_type == "jpg" || $img_type == "jpeg") {
$img_ty = 1;
$src_im = imagecreatefromjpeg($target_path);
} else if ($img_type == "png") {
$img_ty = 2;
$src_im = imagecreatefrompng($target_path);
} else if ($img_type == "gif") {
$img_ty = 3;
$src_im = imagecreatefromgif($target_path);
}

$dst_im = imagecreatetruecolor(round($dst_w), round($dst_h));
$bg = imagecolorallocate($dst_im, 255, 255, 255);
imagefill($dst_im, 0, 0, $bg);

imagecopyresampled($dst_im, $src_im, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h);

switch ($img_ty) {
case 1 :
imagejpeg($dst_im, $target_path, 100);
$ans['ans'] = "success";
break;
case 2 :
imagepng($dst_im, $target_path);
$ans['ans'] = "success";
break;
case 3 :
imagegif($dst_im, $target_path);
$ans['ans'] = "success";
break;
default :
$ans['ans'] = "格式无法识别";
}
}

}

echo json_encode($ans);

最后得到的图片大小与原图一致,但严重失真
...全文
3761 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
luanshimingliu 2014-11-13
  • 打赏
  • 举报
回复
你压缩太狠了
nbahuazi 2013-08-21
  • 打赏
  • 举报
回复
你好本人是菜鸟,能不能打包源码发个给我,谢谢啊709530851@qq.com 急求个android上传图片到php服务器的案例,谢谢啦!
顾小林 2013-07-26
  • 打赏
  • 举报
回复
失真肯定是会发生的了,这个你要选取一个范围,既保证质量,有保证上传,这个你需要自己综合考虑。
yingyoulan 2013-07-26
  • 打赏
  • 举报
回复
引用 1 楼 shen332401890 的回复:
http://bbs.csdn.net/topics/390432950 参考一下这个帖子
你好,参考了你提供的这个帖子才明白resize_img()这个压缩bitmap宽高的方法纯属多余 只需要保留saveMyBitmap() 改变bit.compress(Bitmap.CompressFormat.JPEG, 100, fOut);这个100的这个值就可以了 但是参考帖中,你贴出的那大段代码中为什么也在压缩KB大小前对图片宽高进行了压缩呢? 这是用于上传吗? 我是在边做项目边学android,此前没接触过android,自学能力也实在是不怎么样,快半年了对很多问题都还不了解,很多功能即便做出来了也是照着网上查的资料依样画葫芦,而对于其原理,却没有去探究过,所以对于android,基本上还是一窍不通 现在做图片上传,原图上传是成功了,但对于压缩这块,上网查了很多资料,都是对图片的宽高进行压缩 当时就觉得奇怪:宽高压缩了,图片就不是原图大小,再放大应该也会失真 我当时也怀疑是不是根本就不是用于上传,而仅仅是用于在手机屏幕上的显示而已 可查到的资料又很清楚的说明了是用于上传,于是我以为在服务器解压缩时有什么特别的方法可以让图片不失真 现在才知道改变bit.compress(Bitmap.CompressFormat.JPEG, 100, fOut);100的这个值就可以压缩KB大小,而不影响图片宽高和清晰度。 但是对于在压缩KB大小前对图片宽高进行压缩,这一点能不能解说一下是为什么呢?这样上传的图片不就跟我帖子中提到的情况一样了吗:如果后台不处理,直接保存传过来的图片,那么图片就会比原图小很多;如果后台进行放大处理,把传过来的图片放大为与原图一致,图片就会严重失真
woshilisao 2013-07-26
  • 打赏
  • 举报
回复
貌似压缩就会失真
yingyoulan 2013-07-26
  • 打赏
  • 举报
回复
引用 7 楼 shen332401890 的回复:
可以将临时文件放到 /data/data/yourpackage/files目录下 我也忘了具体方法了你可以搜搜看 上传完成以后再删除就OK了
谢谢
顾小林 2013-07-26
  • 打赏
  • 举报
回复
可以将临时文件放到 /data/data/yourpackage/files目录下 我也忘了具体方法了你可以搜搜看 上传完成以后再删除就OK了
mmorss 2013-07-26
  • 打赏
  • 举报
回复
引用 5 楼 yingyoulan 的回复:
[quote=引用 4 楼 shen332401890 的回复:] 失真肯定是会发生的了,这个你要选取一个范围,既保证质量,有保证上传,这个你需要自己综合考虑。
哦,明白了。我想再问一下我上传时是把压缩后的bitmap转为File保存的sdcard卡再上传【saveMyBitmap(String filename, Bitmap bit)】,上传成功后再删除 有没有什么方法可以不用保存到sd卡,直接上传文件呢[/quote]
引用 5 楼 yingyoulan 的回复:
[quote=引用 4 楼 shen332401890 的回复:] 失真肯定是会发生的了,这个你要选取一个范围,既保证质量,有保证上传,这个你需要自己综合考虑。
哦,明白了。我想再问一下我上传时是把压缩后的bitmap转为File保存的sdcard卡再上传【saveMyBitmap(String filename, Bitmap bit)】,上传成功后再删除 有没有什么方法可以不用保存到sd卡,直接上传文件呢[/quote] 你那图片是从哪里来的嘛
yingyoulan 2013-07-26
  • 打赏
  • 举报
回复
引用 4 楼 shen332401890 的回复:
失真肯定是会发生的了,这个你要选取一个范围,既保证质量,有保证上传,这个你需要自己综合考虑。
哦,明白了。我想再问一下我上传时是把压缩后的bitmap转为File保存的sdcard卡再上传【saveMyBitmap(String filename, Bitmap bit)】,上传成功后再删除 有没有什么方法可以不用保存到sd卡,直接上传文件呢
顾小林 2013-07-25
  • 打赏
  • 举报
回复
http://bbs.csdn.net/topics/390432950 参考一下这个帖子

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧