【问题标题】:Android : Compress & Insert images into SQLite DatabaseAndroid:将图像压缩并插入 SQLite 数据库
【发布时间】:2017-05-15 12:33:49
【问题描述】:

我正在开发一个应用程序,我需要以 BLOB 格式存储超过 1600 张图像 (.PNG)。每张图片的大小接近 230KB。

我想要做的是将图像压缩到 20KB 以下。因此,图像的整体大小将约为 32 MB (1600 x 20KB),并且最终的 apk 大小将减小。

解释更多:我想做的是将图像从 230KB 压缩到 20KB 以下,以节省数据库中的更多空间。在将其集成到 apk 之前,数据库将填充数据和图像。

所以如果我压缩存储在数据库中的图像。数据库大小将减小。并且在 APK 内不会占用太多空间

关于如何做到这一点的任何建议?

注意:数据库将在集成到应用程序之前填充信息。

【问题讨论】:

  • 这样做有什么问题?
  • 将图像放入数据库与您的 apk 甚至您的 apk 的大小有什么关系?连接在哪里?你如何整合它?
  • 我做了更新。我到底想要什么。
  • 我仍然不明白该数据库在您的 apk 中的位置。我还是不明白你想要的东西有哪些问题。
  • @greenapps 数据库通常存在于 apk 内的 Assets 文件夹中。如果您曾经将预填充的数据库集成到 APK 中,您就会知道我在说什么。

标签: android image sqlite compression blob


【解决方案1】:

我认为最好将这些图像存储在服务器上,一旦用户下载您的应用程序,您应该将图像传输到应用程序。 1600 对于未安装的应用来说确实是一个很大的数字...

【讨论】:

    【解决方案2】:

    我不知道这是否是使用 SQLite 节省存储空间的最佳方法,我仍在寻找它,但我们开始了。

    您可以选择图片的来源,例如图库或相机,下面是代码。

    private void selectProductImage() {
            final CharSequence[] itens = {"Use Camera", "Gallery", "Cancel"};
    
            AlertDialog.Builder builder = new AlertDialog.Builder(this,R.style.AlertDialog);
            builder.setItems(itens, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    if (itens[which].equals("Use Camera")) {
                        Toast.makeText(YourActivity.this, "Use Camera", Toast.LENGTH_SHORT).show();
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            requestPermissions(new String[]{Manifest.permission.CAMERA}, MY_CAMERA_PERMISSION_CODE);
                        } else {
                            Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                            startActivityForResult(cameraIntent, CAMERA_REQUEST);
                        }
    
                    } else if (itens[which].equals("Gallery")) {
                        Toast.makeText(YourActivity.this, "Gallery", Toast.LENGTH_SHORT).show();
                        Intent galleryIntent = new Intent();
                        galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
                        galleryIntent.setType("image/*");
                        startActivityForResult(galleryIntent, REQUEST_GALLERY_PHOTO);
    
                    } else if (itens[which].equals("Cancel")) {
                        dialog.dismiss();
                    }
                }
            });
            builder.show();
        }
    

    也许您需要获得使用相机的权限

    @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    
            if (requestCode == MY_CAMERA_PERMISSION_CODE) {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //Toast.makeText(this, "camera permission granted", Toast.LENGTH_LONG).show();
                    Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                    startActivityForResult(cameraIntent, CAMERA_REQUEST);
                } else {
                    Toast.makeText(this, "camera permission denied", Toast.LENGTH_LONG).show();
                }
                return;
            }
    
        }
    

    这里是如何处理来自您选择的来源的图像。

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
            Bitmap bitmap = Bitmap.createScaledBitmap((Bitmap) data.getExtras().get("data"),96, 96, true);
            mProductImage.setImageBitmap(bitmap);
            isPriviteImage = true;
        }
    
        if (requestCode == REQUEST_GALLERY_PHOTO && resultCode == RESULT_OK && data != null) {
            //mProductImage.setImageURI(data.getData());
    
            // INSERT IMAGE INTO SQLite
            Uri uri = data.getData();
    
            try {
                InputStream inputStream = getContentResolver().openInputStream(uri);
                Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(inputStream),96, 96, true);
                mProductImage.setImageBitmap(bitmap);
                isPriviteImage = true;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    正如您在我的示例中所看到的,没有地方可以保存您选择 camera 的图像,我将图像放在名为 mProductImageImageView 变量上.

    从现在开始,您可以使用 按钮 将图像保存在 SQLite 数据库中。这是您可以使用的功能。

    private void saveImage() {
    
        productTablePath = Environment.getExternalStorageDirectory()+"/YourAditionalPath/";
    
        ProductDatabaseHelper productDatabaseHelper = new ProductDatabaseHelper(getApplicationContext(), "dbname.db", productTablePath);
        productListTable = productDatabaseHelper.getWritableDatabase();
        productRepository = new ProductRepository(productListTable);
    
        try {
    
            if (isPriviteImage) {
                productRepository.addProduct(imageViewToByte(mProductImage));
                isPriviteImage = false;
    
            } else {
                productRepository.addProduct(null);
    
            }
    
            mProductImage.setImageResource(R.drawable.shopping_cart_black_48dp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    
    }
    

    imageViewToByte 函数在哪里:

    private byte[] imageViewToByte(CircleImageView image) {
        Bitmap bitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG,100,stream);
        byte[] byteArray = stream.toByteArray();
        return byteArray;
    }
    

    现在您需要实现 SQLiteOpenHelper。您需要为此创建一个新类。我为此使用的 java 文件名是 ProductDatabaseHelper.java

    public class ProductDatabaseHelper extends SQLiteOpenHelper {
    
        private static int dbVersion = 1;
    
        public ProductDatabaseHelper(Context context, String name, String storageDirectory) {
            super(context, storageDirectory+name, null, dbVersion);
        }
    
        @Override
        public void onCreate(SQLiteDatabase db) {
    
            StringBuilder sql = new StringBuilder();
    
            sql.append("CREATE TABLE IF NOT EXISTS PRODUCTLIST (");
    
            sql.append("        IMAGE        BLOB,");
    
    
            db.execSQL(sql.toString());
    
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
        }
    }
    

    现在您需要实现 CRUD(创建新项目、读取、更新和删除)。

    public class ProductRepository {
    
        SQLiteDatabase instance;
    
        public ProductRepository(SQLiteDatabase instance) {
            this.instance = instance;
        }
    
        public void addProduct(byte[] image){
    
            ContentValues contentValues = new ContentValues();
    
            contentValues.put("IMAGE",image);
    
            instance.insertOrThrow("PRODUCTLIST",null, contentValues);
        }
    
    
    }
    

    值得一提的是,图像的压缩是在onActivityResult() 中针对源图像(相机和画廊)进行的。

    使用命令:

    Bitmap bitmap = Bitmap.createScaledBitmap(capturedImage, width, height, true);
    

    除此之外,这里有一个链接,我们可以在这里阅读一些关于压缩的内容。

    https://androidwave.com/capture-image-from-camera-gallery/

    如果您有更好的方法来压缩图像以保存在 SQLite 数据库中,请在此处发布您的代码!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-22
      • 2023-02-07
      • 1970-01-01
      • 2011-07-16
      • 2021-09-13
      • 1970-01-01
      相关资源
      最近更新 更多