RedApparat / Fotoapparat

Making Camera for Android more friendly. 📸
Apache License 2.0
3.82k stars 405 forks source link

jpegQuality doesn't seem to work #231

Closed ashishkrishnan closed 6 years ago

ashishkrishnan commented 6 years ago

I'm trying to compress the image taken by camera and have been using jpegQuality method to do a bit compression, but it doesn't seem to work. Attached are the code snippets I used to achieve quality reduction.

Before applying: Size: 2.3 MB

After applying: Size: 2.3 MB

    fotoapparat = Fotoapparat
        .with(cameraView.context)
        .into(cameraView)
        .previewScaleType(ScaleType.CenterCrop)
        .lensPosition(back())
        .jpegQuality(manualJpegQuality(70))
        .focusMode(firstAvailable(continuousFocusPicture(), autoFocus(), fixed()))
        .logger(logcat())
        .build()

I also tried setting the quality using a CameraConfiguration. Unfortunately, this also doesn't work.

fotoapparat.updateConfiguration(CameraConfiguration(jpegQuality = manualJpegQuality(70)))
Diolor commented 6 years ago

What means "work" ? What do you get, and what are you expectations?

ashishkrishnan commented 6 years ago

Trying to output a lesser quality image.

have updated the issue.

fotoapparat .takePicture() .saveToFile(File(photoPath))

Diolor commented 6 years ago

Well this is what the android camera gives. We cannot do anything about it. Out of curiosity can you try manualJpegQuality(10) ?

ashishkrishnan commented 6 years ago

:stuck_out_tongue: Did that already. No change. It is the same result.

Like you said, if that is what the camera gives what is the use of jpeqQuality method in the Fotoapparat.Builder?

What does it exactly do?

Diolor commented 6 years ago

It adjusts the jpeg compression rate.

In some devices it has effect. Apparently your testing device(s) might not support it. Which device(s) do you test it with?

Here are the official android docs btw https://developer.android.com/reference/android/hardware/Camera.Parameters.html#setJpegQuality(int)

ashishkrishnan commented 6 years ago

Hahah, the functionality, I guessed it correctly. But, talking of documentation looks like you referenced a Camera v1 API.

Does the Camera2 API also support this?. I couldn't find any API exposure in the corresponding documentation.

My Testing device Lenovo P2 running Nougat qualifies for Camera2.

Will check with other devices as well.

Diolor commented 6 years ago

Fotoapparat uses camera 1. You can try use directly camera 2 instead of Fotoapparat if it fits better your needs

ashishkrishnan commented 6 years ago

Oh, I didn't realise that. Do you plan to write a wrapper over the Camera2 API or in your opinion is it needed?

Diolor commented 6 years ago

We had. Unfortunately camera 2 is not as performant as camera 1, so we dropped it. Camera 1 can work with all devices. Also the ones 21+

ashishkrishnan commented 6 years ago

Well, that's true. Although, My Team and I used the toBitmap() to collect and the bitmap and then reduce using Bitmap.compress(......) and then pass it down.

Hence, we look good with this. Thank you for the clarifications.

ashishkrishnan commented 6 years ago

@Diolor Hey, I might have found something. setting a jpegQuality does work. It gives me smaller compressed images.

Although, rotating the flash (in my case) by updating the camera configuration actually resets the jpeg quality settings.

fotoapparat.updateConfiguration(CameraConfiguration
        .builder()
        .jpegQuality { JPEG_QUALITY }
        .flash { toFlashSelector(flash) }
        .build())

So, basically any update to the camera configuration resets it. Tried putting the jpegQuality settings again in the camera configuration as well. But no positive result.

Here are the logs:

Before setting the custom flash config
New camera parameters are: CameraParameters
flashMode:      io.fotoapparat.parameter.Flash$Off@53a0673
focusMode:      io.fotoapparat.parameter.FocusMode$ContinuousFocusPicture@37dd0eb
jpegQuality:        50
previewFpsRange:        FpsRange(min=15000, max=30000)
antiBandingMode:        io.fotoapparat.parameter.AntiBandingMode$Auto@23276f4
 sensorSensitivity:     null
pictureResolution:      Resolution(width=4128, height=3096)
previewResolution:      Resolution(width=1440, height=1080)

After configuration is updated:

D: Device: updateConfiguration
D: CameraDevice: getCapabilities$suspendImpl
D: CameraDevice: updateParameters$suspendImpl

New camera parameters are: CameraParameters
flashMode:      io.fotoapparat.parameter.Flash$Off@53a0673
focusMode:      io.fotoapparat.parameter.FocusMode$ContinuousFocusPicture@37dd0eb
jpegQuality:        90
imGurpreetSK commented 6 years ago

@ashishkrishnan @Diolor Facing the same issue in my application as well. Probable cause might be the default quality value of 90 which is set in CameraConfiguration. It resets itself everytime the camera configuration is updated.

Diolor commented 6 years ago

@GurpreetSK95 Are you using CameraConfiguration inside the updateConfiguration? You should use UpdateConfiguration instead

ashishkrishnan commented 6 years ago

@Diolor

  val configuration = UpdateConfiguration
        .builder()
        .flash { toFlashSelector(flash) }
        .jpegQuality { 55 }
        .build()
    fotoapparat.updateConfiguration(configuration)
  }

Still the same.

Can you explain the lifecycle of the updateConfiguration call? If you look into

line 45 Fotoapparat.kt cameraConfiguration: CameraConfiguration = CameraConfiguration.default(),

in the library, I think this is the call that resets it everytime. Have tried debugging.

Diolor commented 6 years ago

The method has no lifecycle. If you mean the cameraConfiguration: CameraConfiguration object then it's the same as a FA instance or until changed

455908068 commented 5 years ago

@Diolor I think the problem is "Device. Kt "class, code snippet as follows ` /**