【问题标题】:why I save the bitmap ( BitmapFactory.decodeFile's output) into a file is bigger than The original image file?为什么我将位图(BitmapFactory.decodeFile 的输出)保存到比原始图像文件大的文件中?
【发布时间】:2023-03-13 16:26:01
【问题描述】:

我使用 opencv (android-jni) 调整 Bitmapfile 的大小并将输出的位图保存到名为 /mnt/sdcard/org.jpg 的文件中

然后使用

resultBitmap = BitmapFactory.decodeFile("/mnt/sdcard/org.jpg"); 

获取位图并将这个resultBitmap重新保存到文件/mnt/sdcard/result.jpg

那么 org.jpg 大小为 100k,result.jpg 大小约为 300k

为什么?

我的 resize 方法在 jni 中使用 opencv,如下所示:

int FUN_ENTRY JNICALL Java_com_funlib_imagefilter_ImageUtily_nativeResizeBitmap(    
                                                                                JNIEnv* env, jobject obj , jstring srcPath , jstring destPath,  int w , int h , int quality)
{
    char* srcPath1 = jstringTostring(env , srcPath);
    IplImage *src = cvLoadImage(srcPath1,CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
    if(srcPath1!=NULL)
    {
        free(srcPath1);
        srcPath1 = NULL;
    }
    if(src==NULL)
    {
        return -1;
    }

    CvSize sz;
    double rate1 = ((double) src->width) / (double) w + 0.1; 
    double rate2 = ((double) src->height) / (double) h + 0.1; 

    double rate = rate1 > rate2 ? rate1 : rate2; 
    sz.width = (int) (((double) src->width) / rate); 
    sz.height = (int) (((double) src->height) / rate); 
    IplImage *desc = cvCreateImage(sz,src->depth,src->nChannels);
    if(desc==NULL)
    {
        cvReleaseImage(&src);
        return -1;
    }
    cvResize(src,desc,CV_INTER_CUBIC);
    if(desc==NULL)
    {
        cvReleaseImage(&src);
        return -1;
    }
    char* destPath1 = jstringTostring(env , destPath);

    int p[3];
    p[0] = CV_IMWRITE_JPEG_QUALITY;
    p[1] = quality;
    p[2] = 0;

    cvSaveImage(destPath1 , desc , p);
    cvReleaseImage(&src);
    cvReleaseImage(&desc);
    if(destPath1!=NULL)
    {
        free(destPath1);
        destPath1 = NULL;
    }

    return 0;
}

我的主要是

File f = new File(filePath);
    String tmpDestPath = f.getParent();
    if(!tmpDestPath.endsWith(File.separator))
        tmpDestPath += File.separator;
    tmpDestPath += "org.jpg";
    int ret = nativeResizeBitmap(filePath, tmpDestPath, width, height , quality);         //get the org.jpg file
    Bitmap bmp = null;
    if(ret == 0){
        bmp = BitmapFactory.decodeFile(tmpDestPath);
    }

    try {
        ImageUtily.saveBitmapToFile("result", bmp);  //get the result.jpg file
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

我的 saveBitmapToFile 是

    public static void saveBitmapToFile(String fileName, Bitmap bmp) throws IOException
{
    File f = new File("/sdcard/DCIM/TEMP/" + fileName + ".jpg");
    f.createNewFile();
    FileOutputStream fOut = null;
    try {
        fOut = new FileOutputStream(f);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    bmp.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
    try {
        fOut.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        fOut.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

【问题讨论】:

  • 尝试将bmp.compress(Bitmap.CompressFormat.JPEG, 100, fOut); 中的quality 参数从100 调低。 100 = 最大质量,不会为您提供小的 JPEG 图像。

标签: android opencv bitmap filesize bitmapfactory


【解决方案1】:

我不知道 OpenCV / Android-JNI,所以我可以尝试给你一个提示。

我想函数saveBitmapToFile 会按照它在锡上所说的那样做:保存一个位图(如BMP file format)。您需要先压缩bmp,也许this 可以为您指明正确的方向。

至于为什么新文件更大:如果您真的想知道(并且不只是对如何修复它感兴趣),请启动您选择的十六进制编辑器并查看file header。位图使用了不同的位深度和压缩方式,在这个过程中可能已经改变了。

【讨论】:

  • 你可以保存一个 ARGB_8888 位图,这是默认的,至少我认为是推荐的(检查 Bitmap.Config)。如果您的原始 bmp 是 RGB_565,它是一半大小,因为 ARGB_8888 = 32 位,RGB_565 = 16 位。
猜你喜欢
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
  • 2018-04-29
  • 2018-06-15
  • 1970-01-01
  • 2019-08-05
  • 2011-05-08
  • 1970-01-01
相关资源
最近更新 更多