拍摄照片通过数码相机,在字节组发送到服务器发送到、字节、数码相机、服务器

2023-09-05 04:43:23 作者:从此、陌路

我工作的11014633中,我希望用户能够拍摄照片,然后将其保存我送过来给服务器。现在,我送图片作为一个字节数组到服务器。当我尝试字节数组保存到一个文件作为PNG文件,然后尝试打开该文件,图像查看器抱怨说,PNG有错误,无法显示。该PNG文件大小为122KB。

I am working on an Andorid application in which I would like the user to take a picture and then to save it I am sending it over to the server. Now, I am sending the picture as a byte-array to the server. When I try to save the byte-array to a file as a PNG file, and then try to open the file, the image-viewer complains that the PNG has errors and cannot be displayed. The PNG file size was 122Kb.

当我试图用Scalr库来调整图片的大小,它说的图像源不能为空。直接节约了字节数组是造成腐败的PNG。我应该如何转换并正确发送文件到服务器,所以有没有错误。 这里是$ C $下的摄像头,我使用并发送过来。

When I tried to use Scalr library to resize the image, it says the image source cannot be null. Directly saving the byte-array is causing a corrupt PNG. How should I convert and send the file properly to server, so there are no errors. Here is the code for camera which I am using and sending it over.

public class AddPhotoForUser extends DrawerLoader {

    private static final int CAMERA_PIC_REQUEST = 22;
    Button BtnSelectImage;
    private ImageView ImgPhoto;
    private static volatile Bitmap photo;
    private static volatile ByteArrayOutputStream stream = new ByteArrayOutputStream();

    final PersonServiceImpl personService = new PersonServiceImpl();

    private String[] navMenuTitles;
    private TypedArray navMenuIcons;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.upload_user_photo);

        navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);
        navMenuIcons = getResources()
                .obtainTypedArray(R.array.nav_drawer_icons);

        set(navMenuTitles, navMenuIcons);

        Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton);
        uploadImageButton.setVisibility(View.INVISIBLE);

        ImgPhoto = (ImageView) findViewById(R.id.userPhotoImageView);
        BtnSelectImage = (Button) findViewById(R.id.userPhotoButtonSelect);
        BtnSelectImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {

                    Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                    startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);

                } catch (Exception e) {
                    Toast.makeText(getApplicationContext(), "Couldn't load photo", Toast.LENGTH_LONG).show();
                }
            }
        });

        uploadImageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!(v == null)) {
                    uploadImage();
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Intent intent = new Intent(AddPhotoForUser.this, RestaurantList.class);
                    startActivity(intent);
                    finish();

                }
            }
        });

    }

    @Override
    public void onBackPressed() {
        Intent intent = new Intent(AddPhotoForUser.this, Login.class);
        startActivity(intent);
        finish();
    }

    @Override
    public void onActivityResult(final int requestCode, int resultCode, Intent data) {
        try {
            switch (requestCode) {
                case CAMERA_PIC_REQUEST:
                    if (resultCode == RESULT_OK) {
                        try {
                            photo = (Bitmap) data.getExtras().get("data");
                            if (!(photo == null)) {
                                ImgPhoto.setImageBitmap(photo);
                                Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton);
                                uploadImageButton.setVisibility(View.VISIBLE);

                            }
                        } catch (Exception e) {
                            Toast.makeText(this, "Couldn't load photo", Toast.LENGTH_LONG).show();
                        }
                    }
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    private void uploadImage() {

        if (!(photo == null)) {
            photo.compress(Bitmap.CompressFormat.PNG, 100, stream);
            byte[] byteArray = stream.toByteArray();
            personService.addUserProfilePhoto(byteArray);
        }

    }
}

下面是服务器端code将图像保存到磁盘:

Here is the server side code to save the image to disk :

 @Override
    public Boolean updateProfilePhoto(byte[] photo) {
        Person person = getCurrentlyAuthenticatedPerson();
        try{
           InputStream in = new ByteArrayInputStream(photo);
            BufferedImage image = ImageIO.read(in);
            image = Scalr.resize(image, Scalr.Method.QUALITY, 100, 100);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            baos.flush();
            File file = new File(userImagePath);
            if (file.exists() && file.isDirectory()) {
                OutputStream outputStream = new FileOutputStream(new File(userImagePath + person.getUserId()+".png"));
                outputStream.write(baos.toByteArray());
                outputStream.close();
            } else {
                File file1 = new File(userImagePath+person.getUserId()+".png");
                if (file1.exists()) {
                    try {
                        OutputStream outputStream = new FileOutputStream(file1);
                        outputStream.write(baos.toByteArray());
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();

                    }
                } else {
                   boolean result = file1.createNewFile();
                    System.out.println("Result of file1 creation is "+result);
                    OutputStream outputStream = new FileOutputStream(file1);
                    outputStream.write(baos.toByteArray());
                    outputStream.close();
                }
            }
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

如果我不使用Scalr库,没有错误,但其损坏的文件。这里是Scalr错误日志:

If I don't use the Scalr library, there are no errors, but its a corrupt file. Here is the Scalr error log :

java.lang.IllegalArgumentException: src cannot be null
    at org.imgscalr.Scalr.resize(Scalr.java:1564)
    at org.imgscalr.Scalr.resize(Scalr.java:1415)
    at com.journaldev.spring.service.PersonServiceImpl.updateProfilePhoto(PersonServiceImpl.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at com.sun.proxy.$Proxy51.updateProfilePhoto(Unknown Source)
    at com.journaldev.spring.Controller.PersonController.addProfilePhotoForUser(PersonController.java:100)

任何帮助将是很好。多谢。 : - )

Any help would be nice. Thanks a lot. :-)

更新code 的

public class AddPhotoForUser extends DrawerLoader {


    Button BtnSelectImage;
    private ImageView ImgPhoto;

    private static volatile ByteArrayOutputStream stream = new ByteArrayOutputStream();

    final PersonServiceImpl personService = new PersonServiceImpl();

    private String[] navMenuTitles;
    private TypedArray navMenuIcons;

    private static final int CAMERA_PHOTO = 111;
    private Uri imageToUploadUri;

    Bitmap reducedSizeBitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.upload_user_photo);

        navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);
        navMenuIcons = getResources()
                .obtainTypedArray(R.array.nav_drawer_icons);

        set(navMenuTitles, navMenuIcons);

        Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton);
        uploadImageButton.setVisibility(View.INVISIBLE);

        ImgPhoto = (ImageView) findViewById(R.id.userPhotoImageView);
        BtnSelectImage = (Button) findViewById(R.id.userPhotoButtonSelect);
        BtnSelectImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {

                    captureCameraImage();
                } catch (Exception e) {
                    Toast.makeText(getApplicationContext(), "Couldn't load photo", Toast.LENGTH_LONG).show();
                }
            }
        });

        uploadImageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!(v == null)) {
                    uploadImage();
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Intent intent = new Intent(AddPhotoForUser.this, RestaurantList.class);
                    startActivity(intent);
                    finish();

                }
            }
        });

    }

    private Bitmap getBitmap(String path) {

        Uri uri = Uri.fromFile(new File(path));
        InputStream in = null;
        try {
            final int IMAGE_MAX_SIZE = 12000000; // 12MP
            in = getContentResolver().openInputStream(uri);

            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(in, null, o);
            in.close();


            int scale = 1;
            while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) >
                    IMAGE_MAX_SIZE) {
                scale++;
            }
            Log.d("", "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight);

            Bitmap b = null;
            in = getContentResolver().openInputStream(uri);
            if (scale > 1) {
                scale--;
                // scale to max possible inSampleSize that still yields an image
                // larger than target
                o = new BitmapFactory.Options();
                o.inSampleSize = scale;
                b = BitmapFactory.decodeStream(in, null, o);

                // resize to desired dimensions
                int height = b.getHeight();
                int width = b.getWidth();
                Log.d("", "1th scale operation dimenions - width: " + width + ", height: " + height);

                double y = Math.sqrt(IMAGE_MAX_SIZE
                        / (((double) width) / height));
                double x = (y / height) * width;

                Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,
                        (int) y, true);
                b.recycle();
                b = scaledBitmap;
                System.gc();
            } else {
                b = BitmapFactory.decodeStream(in);
            }
            in.close();

            Log.d("", "bitmap size - width: " + b.getWidth() + ", height: " +
                    b.getHeight());
            return b;
        } catch (IOException e) {
            Log.e("", e.getMessage(), e);
            return null;
        }
    }

    private void captureCameraImage() {
        Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File f = new File(Environment.getExternalStorageDirectory(), "POST_IMAGE.jpg");
        chooserIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
        imageToUploadUri = Uri.fromFile(f);
        startActivityForResult(chooserIntent, CAMERA_PHOTO);
    }

    @Override
    public void onBackPressed() {
        Intent intent = new Intent(AddPhotoForUser.this, Login.class);
        startActivity(intent);
        finish();
    }

    @Override
    protected void onActivityResult(final int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == CAMERA_PHOTO && resultCode == Activity.RESULT_OK) {
            if(imageToUploadUri != null){
                Uri selectedImage = imageToUploadUri;
                getContentResolver().notifyChange(selectedImage, null);
                reducedSizeBitmap = getBitmap(imageToUploadUri.getPath());
                if(reducedSizeBitmap != null){
                    ImgPhoto.setImageBitmap(reducedSizeBitmap);
                    Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton);
                    uploadImageButton.setVisibility(View.VISIBLE);
                }else{
                    Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show();
                }
            }else{
                Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show();
            }
        }

    }

    private void uploadImage() {
        if(!(reducedSizeBitmap == null)){
            reducedSizeBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
            byte[] byteArray = stream.toByteArray();
            this.personService.addUserProfilePhoto(byteArray);
        }
    }
}

推荐答案

如果您使用捆绑额外= data.getExtras(); onActivityResult()那么它将返回缩略图不是实际图像。

If you use Bundle extras = data.getExtras(); in your onActivityResult() then it will return thumbnail image not actual image.

下面是code我已经用于捕获和保存相机影像,然后显示给的ImageView 。您可以根据您的需要使用。

Here is code I have used for Capturing and Saving Camera Image then display it to ImageView. You can use according to your need.

您必须保存摄像机图像的具体位置,然后从该位置取出,然后将其转换为字节数组。

You have to save Camera image to specific location then fetch from that location then convert it to byte-array.

下面的方法是打开摄像机捕捉图像的活动。

Here is method for opening capturing camera image activity.

private static final int CAMERA_PHOTO = 111;
private Uri imageToUploadUri;

private void captureCameraImage() {
        Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File f = new File(Environment.getExternalStorageDirectory(), "POST_IMAGE.jpg");
        chooserIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
        imageToUploadUri = Uri.fromFile(f);
        startActivityForResult(chooserIntent, CAMERA_PHOTO);
    }

那么你的 onActivityResult()的方法应该是这样的。

then your onActivityResult() method should be like this.

@Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);

            if (requestCode == CAMERA_PHOTO && resultCode == Activity.RESULT_OK) {
                if(imageToUploadUri != null){
                    Uri selectedImage = imageToUploadUri;
                    getContentResolver().notifyChange(selectedImage, null);
                    Bitmap reducedSizeBitmap = getBitmap(imageToUploadUri.getPath());
                    if(reducedSizeBitmap != null){
                        ImgPhoto.setImageBitmap(reducedSizeBitmap);
                        Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton);
                          uploadImageButton.setVisibility(View.VISIBLE);                
                    }else{
                        Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show();
                    }
                }else{
                    Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show();
                }
            } 
        }

下面是 onActivityResult使用 getBitmap()办法()。我已经做了所有的性能提升,可有可能同时获得摄像头采集图像的位图。

Here is getBitmap() method used in onActivityResult(). I have done all performance improvement that can be possible while getting camera capture image bitmap.

private Bitmap getBitmap(String path) {

        Uri uri = Uri.fromFile(new File(path));
        InputStream in = null;
        try {
            final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
            in = getContentResolver().openInputStream(uri);

            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(in, null, o);
            in.close();


            int scale = 1;
            while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) >
                    IMAGE_MAX_SIZE) {
                scale++;
            }
            Log.d("", "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight);

            Bitmap b = null;
            in = getContentResolver().openInputStream(uri);
            if (scale > 1) {
                scale--;
                // scale to max possible inSampleSize that still yields an image
                // larger than target
                o = new BitmapFactory.Options();
                o.inSampleSize = scale;
                b = BitmapFactory.decodeStream(in, null, o);

                // resize to desired dimensions
                int height = b.getHeight();
                int width = b.getWidth();
                Log.d("", "1th scale operation dimenions - width: " + width + ", height: " + height);

                double y = Math.sqrt(IMAGE_MAX_SIZE
                        / (((double) width) / height));
                double x = (y / height) * width;

                Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,
                        (int) y, true);
                b.recycle();
                b = scaledBitmap;

                System.gc();
            } else {
                b = BitmapFactory.decodeStream(in);
            }
            in.close();

            Log.d("", "bitmap size - width: " + b.getWidth() + ", height: " +
                    b.getHeight());
            return b;
        } catch (IOException e) {
            Log.e("", e.getMessage(), e);
            return null;
        }
    }

编辑:

下面是方法上传图像到服务器。

Here is method for uploading image to server.

/**
 * Upload Image to server
 *
 * @param file              image to be saved
 * @param compressorQuality quality of image
 * @return path of uploaded image in server
 */
private String uploadImage(Bitmap file, int compressorQuality) {
    String final_upload_filename = "demo_image.png";
    String response = null;
    HttpURLConnection conn = null;
    try {
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "---------------------------14737809831466499882746641449";
        URL url = new URL("image_upload_url");
        conn = (HttpURLConnection) url.openConnection();
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("ENCTYPE", "multipart/form-data");
        conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
        conn.setRequestProperty("uploaded_file", final_upload_filename);
        DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
        dos.writeBytes(lineEnd + twoHyphens + boundary + lineEnd);
        dos.writeBytes("Content-Disposition: form-data; name=\"userfile\"; filename=\"" + final_upload_filename + "\"" + lineEnd);
        dos.writeBytes("Content-Type: application/octet-stream" + lineEnd);
        dos.writeBytes(lineEnd);
        file.compress(CompressFormat.PNG, compressorQuality, dos);
        dos.writeBytes(lineEnd);
        dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
        dos.flush();
        dos.close();
        InputStream is = conn.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int bytesRead;
        byte[] bytes = new byte[1024];
        while ((bytesRead = is.read(bytes)) != -1) {
            baos.write(bytes, 0, bytesRead);
        }
        byte[] bytesReceived = baos.toByteArray();
        baos.close();
        is.close();
        response = new String(bytesReceived);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (conn != null) {
            conn.disconnect();
        }
    }
    return response;
}

您需要做的上传脚本在后台服务器存储的图像数据在特定的文件夹。

You need to make upload script in backend server to store image data in particular folder.

我希望它能帮助!