关于Android的图片压缩

最近有项目需要压缩图片(300 x 300)传入服务器展示

但是效果却不近人情,到这个size 图片就糊掉了 ,但是IOS却没问题经过反复查证IOS和android 在底层的OnDraw方法用的是同一个包,但是IOS在底层绘制的时候把一些属性都加上(smooth化、锐化操作)了所以大小和质量都比android 质量高一些。

对于这样的问题下android本身目前是没有办法去修改的。

但是目前有三种方法去提高一些质量

1.android方面

根据相关的方法等比压缩对图片resize 操作

public static  Bitmap getResizedBitmap(Bitmap bitmap,float newWidth, float newHeight) {    if (bitmap.getHeight()>bitmap.getWidth()){        newHeight=300f;        newWidth= (int) (bitmap.getWidth()*(newHeight/(float) bitmap.getHeight()));    }else{        newWidth=300f;        newHeight= (int) (bitmap.getHeight()*(newWidth/(float) bitmap.getWidth()));    }    Bitmap resizedBitmap = Bitmap.createBitmap((int)newWidth,(int) newHeight, Bitmap.Config.ARGB_8888);    float scaleX = newWidth / (float) bitmap.getWidth();    float scaleY = newHeight / (float) bitmap.getHeight();    float pivotX = 0;    float pivotY = 0;    Matrix scaleMatrix = new Matrix();    scaleMatrix.setScale(scaleX, scaleY, pivotX, pivotY);    Canvas canvas = new Canvas(resizedBitmap);    canvas.setMatrix(scaleMatrix);    canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG |            Paint.DITHER_FLAG |            Paint.ANTI_ALIAS_FLAG));    return resizedBitmap;}

 

结论:压缩500X500以下的图片 会模糊

 

2. jni方面

加载bither库

微信处理压缩方法

有压缩以及resize的方法

压缩首先

int generateJPEG(BYTE* data, int w, int h, int quality,
        const char* outfilename, jboolean optimize) {
    int nComponent = 3;

    struct jpeg_compress_struct jcs;

    struct my_error_mgr jem;

    jcs.err = jpeg_std_error(&jem.pub);
    jem.pub.error_exit = my_error_exit;
        if (setjmp(jem.setjmp_buffer)) {
            return 0;
         }
    jpeg_create_compress(&jcs);
    FILE* f = fopen(outfilename, "wb");
    if (f == NULL) {
        return 0;
    }
    jpeg_stdio_dest(&jcs, f);
    // if(w>h){
 //     jcs.image_width = 396;
 //     jcs.image_height = (int)(h*(396/w));
    // }else{
    //     jcs.image_height = 396;
 //        jcs.image_width = (int)(w*(396/h));
    // }

    jcs.image_height = h;
    jcs.image_width = w;
    if (optimize) {
        LOGI("optimize==ture");
    } else {
        LOGI("optimize==false");
    }

    jcs.arith_code = false;
    jcs.input_components = nComponent;
    if (nComponent == 1)
        jcs.in_color_space = JCS_GRAYSCALE;
    else
        jcs.in_color_space = JCS_RGB;

    jpeg_set_defaults(&jcs);
    jcs.optimize_coding = optimize;
    jpeg_set_quality(&jcs, quality, true);

    jpeg_start_compress(&jcs, TRUE);

    JSAMPROW row_pointer[1];
    int row_stride;
    row_stride = jcs.image_width * nComponent;
    while (jcs.next_scanline < jcs.image_height) {
        row_pointer[0] = &data[jcs.next_scanline * row_stride];

        jpeg_write_scanlines(&jcs, row_pointer, 1);
    }

    if (jcs.optimize_coding) {
            LOGI("optimize==ture");
        } else {
            LOGI("optimize==false");
        }

    jpeg_finish_compress(&jcs);
    jpeg_destroy_compress(&jcs);
    fclose(f);

    return 1;
}

typedef struct {
    uint8_t r;
    uint8_t g;
    uint8_t b;
} rgb;

char* jstrinTostring(JNIEnv* env, jbyteArray barr) {
    char* rtn = NULL;
    jsize alen = (*env)->GetArrayLength(env, barr);
    jbyte* ba = (*env)->GetByteArrayElements(env, barr, 0);
    if (alen > 0) {
        rtn = (char*) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    (*env)->ReleaseByteArrayElements(env, barr, ba, 0);
    return rtn;
}

jbyteArray stoJstring(JNIEnv* env, const char* pat,int len) {
    jbyteArray bytes = (*env)->NewByteArray(env, len);
    (*env)->SetByteArrayRegion(env, bytes, 0, len,  pat);
    jsize alen = (*env)->GetArrayLength(env, bytes);
    return bytes;
}
jstring Java_包名_compressBitmap(JNIEnv* env,
        jobject thiz, jobject bitmapcolor, int w, int h, int quality,
        jbyteArray fileNameStr, jboolean optimize) {

    AndroidBitmapInfo infocolor;
    BYTE* pixelscolor;
    int ret;
    BYTE * data;
    BYTE *tmpdata;
    char * fileName = jstrinTostring(env, fileNameStr);
    if ((ret = AndroidBitmap_getInfo(env, bitmapcolor, &infocolor)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return (*env)->NewStringUTF(env, "0");;
    }
    if ((ret = AndroidBitmap_lockPixels(env, bitmapcolor, &pixelscolor)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }

    BYTE r, g, b;
    data = NULL;
    data = malloc(w * h * 3);
    tmpdata = data;
    int j = 0, i = 0;
    int color;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            color = *((int *) pixelscolor);
            r = ((color & 0x00FF0000) >> 16);
            g = ((color & 0x0000FF00) >> 8);
            b = color & 0x000000FF;
            *data = b;
            *(data + 1) = g;
            *(data + 2) = r;
            data = data + 3;
            pixelscolor += 4;

        }

    }
    AndroidBitmap_unlockPixels(env, bitmapcolor);
    int resultCode= generateJPEG(tmpdata, w, h, quality, fileName, optimize);
    free(tmpdata);
    if(resultCode==0){
        jstring result=(*env)->NewStringUTF(env, error);
        error=NULL;
        return result;
    }
    return (*env)->NewStringUTF(env, "1"); //success
}

resize方法

 jboolean  Java_包名_resizePicture(JNIEnv* env,
        jobject thiz,jstring strSource, jstring strTarget,int w, int h)
{
    int WIDTH = 396;
    int HEIGHT = 396;
    CImage oldimg;
    CImage newimg;
    oldimg.Load(strSource);
    if (oldimg.IsNull())
        return false;
    int nWidth = 0;
    int nHeight = 0;

    nWidth = oldimg.GetWidth();
    nHeight = oldimg.GetHeight();

    if (nWidth > WIDTH || nHeight > HEIGHT)
    {
        double dRatio = nWidth * 1.0 / nHeight;
        if (nWidth > nHeight)
        {
            nWidth = WIDTH;
            nHeight = (int)(nWidth / dRatio);
        }
        else
        {
            nHeight = HEIGHT;
            nWidth = (int)(nHeight * dRatio);
        }
    }

    if (!newimg.CreateEx(nWidth, nHeight, 24, BI_RGB))
    {
        oldimg.Destroy();
        return false;
    }

    int nPreMode = ::SetStretchBltMode(newimg.GetDC(), HALFTONE);
    newimg.ReleaseDC();
    oldimg.Draw(newimg.GetDC(), 0, 0, nWidth, nHeight, 0, 0, oldimg.GetWidth(), oldimg.GetHeight());
    newimg.ReleaseDC();
    ::SetBrushOrgEx(newimg.GetDC(), 0, 0, NULL);
    newimg.ReleaseDC();
    ::SetStretchBltMode(newimg.GetDC(), nPreMode);
    newimg.ReleaseDC();

    newimg.Save(strTarget);
    newimg.Destroy();
    oldimg.Destroy();

    return true;
}

结论:压缩500X500以下的图片 会模糊 想测试的同学可以通过上面方式的查看相关GitHub库或者文章

3.Opencv

加载openCV3.0 库

注:最好加载3.0库以上

@Override//    public void onResume() {//        super.onResume();//        if (!OpenCVLoader.initDebug()) {//            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);//        } else {//            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);//        }//    }//    //openCV4Android 需要加载用到//    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {//        @Override//        public void onManagerConnected(int status) {//            switch (status) {//                case LoaderCallbackInterface.SUCCESS: {//         
//                    mOpenCvCameraView.enableView();////                    mOpenCvCameraView.setOnTouchListener(ColorBlobDetectionActivity.this);//                }//                break;//                default: {//                    super.onManagerConnected(status);//                }//                break;//            }//        }//    };////    static {//        if (!OpenCVLoader.initDebug()) {//        }//    }

 

如果3.0以下 启动时会下载opencv库 在手机里 所以避免这一步最好加载3.0库

        File dirFile = getExternalCacheDir();////        File tempFile =new File(dirFile,"temp.jpg");//        NativeUtil.compressBitmap(BitmapFactory.decodeFile(photo_path),tempFile.getAbsolutePath(), false);//        BufferedImage image = new BufferedImage(182, 396, BufferedImage.TYPE_INT_RGB);//        image.getGraphics().drawImage(targetImage.getScaledInstance(182, 396, image.SCALE_SMOOTH), 0, 0, 182,//                396, null);//        double scale = 0.2; // 缩放比例//        Mat img = imread(photo_path);// 读入图片,将其转换为Mat//        Size dsize = new Size(182, 396); // 设置新图片的大小//        Mat img2 = new Mat(dsize, CvType.CV_64F);//        Mat img3= new Mat(dsize, CvType.CV_32F);//        // 创建一个新的Mat(opencv的矩阵数据类型)//        Imgproc.resize(img, img2,dsize,0,0,INTER_NEAREST);//调用Imgproc的Resize方法,进行图片缩放//        double ksize = 3.0f;//        Imgproc.blur(img2,img3,new Size(ksize,ksize));//调用Imgproc的Resize方法,进行图片缩放//        String base64Img = null;//        if(imwrite("/sdcard/temp.jpg", img2)){//将图形保存到new.jpg中//            File f = new File("/sdcard/temp.jpg");//            if(f.exists()) {//                base64Img = ImgUtil.bitmapToBase64(BitmapFactory.decodeFile(f.getAbsolutePath()));//            }//        }

 

通过这种方法来resize 图片和以上方法一样也会模糊掉。

4.OpenGL

这个我就不贴代码了

因为他还是不会对图片有什么帮助

只能在本地加载上图片后显示方面可以用锐化和smooth化修正

可以修改一定的质量但是不会对图片文件本身修改

而且治根不治本还是会模糊

 

 

android方面加载其实还是需要其他的的语言进行修改

我这边是通过java

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);         image.getGraphics().drawImage(targetImage.getScaledInstance(width, height, image.SCALE_SMOOTH), 0, 0, width,                 height, null);

去修改图片才可以修改掉

 

希望可以帮助大家

 

 

更多相关文章

  1. Android(安卓)之 Window、WindowManager 与窗口管理
  2. Android(安卓)文件保存getFilesDir()丶getCacheDir()、getExtern
  3. Android(安卓)中SQList用法详解(增删查改)
  4. Android应用程序的Life Cycle
  5. Android中水波纹使用之自定义视图实现
  6. Android中String资源文件的format方法
  7. Android视频图片缩略图的获取
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. framework的调试与编译方法
  2. Android(安卓)application context/activ
  3. android中padding和margin的区别
  4. android 中生成xml文件
  5. android EditText imeOptions属性和各属
  6. [Android(安卓)中级]Voip之CSipSimple类
  7. Android系统启动流程 -- android
  8. Android中的几种网络请求方式详解
  9. [Android1.6]动态添加View的问题
  10. Android(安卓)ADK 编程简介