Closed javidnoutash closed 6 years ago
The bigger the resolution, the longer it takes for your device to process the image.
To provide a custom resolution you need to implement your own resolution selector. It is actually pretty simple - you are given a list of available resolutions from which you need to select one. Unfortunately, you can't just say which size you want - you need to select one from what Camera provides you.
Here is how highest and lowest resolution selectors are implemented: https://github.com/Fotoapparat/Fotoapparat/blob/master/fotoapparat/src/main/java/io/fotoapparat/selector/ResolutionSelectors.kt
For example, the selector which picks the second highest resolution would look like that:
fun customResolutionSelector(): ResolutionSelector = {
// In current context "this" is the list of resolutions.
return sortedByDescending(Resolution::area) // we sort the list by resolutions - the highest resolutions first
.drop(1) // let's ignore the highest resolution
.firstOrNull() // ... and pick the next one
?: first() // it could be that the original list contained only 1 resolution. If that is the case we need to default to something.
}
I use this method to select the resolution with custom megapixel.
fotoapparat = Fotoapparat.with(mActivity)
.into(preview)
.previewScaleType(ScaleType.CenterCrop)
.previewResolution(new Function1<Iterable<Resolution>, Resolution>() {
@Override
public Resolution invoke(Iterable<Resolution> resolutions) {
return getResolutionWithMp(1.2f, resolutions);
}
})
.photoResolution(new Function1<Iterable<Resolution>, Resolution>() {
@Override
public Resolution invoke(Iterable<Resolution> resolutions) {
return getResolutionWithMp(5f, resolutions);
}
})
.build();
private Resolution getResolutionWithMp(float megapixel, Iterable<Resolution> resolutions) {
LinkedList<Resolution> resolutionsList = new LinkedList<>();
for (Resolution res : resolutions) {
resolutionsList.add(res);
}
Collections.sort(resolutionsList, new Comparator<Resolution>() {
@Override
public int compare(Resolution r0, Resolution r1) {
if (r1.getArea() < r0.getArea()){
return 1;
} else {
return -1;
}
}
});
for (Resolution size : resolutionsList) {
float sizeMp = size.getArea() / 1000000f;
if (sizeMp > megapixel) {
Log.e("Fotoapparat", "Selected: " + String.valueOf(sizeMp));
return size;
}
}
Resolution highest = highestResolution().invoke(resolutions);
Log.e("Fotoapparat", "Selected: " + String.valueOf(highest.getArea() / 1000000f));
return highest;
}
That is pretty neat! Would look even prettier in Kotlin :)
Thanks for the replies guys :)
I made a kotlin version :)
pictureResolution = {
var resolution: Resolution? = null
for (size in this) {
val sizeMp = size.area / 1000000F
if (sizeMp > 2F && sizeMp < 4F) {
resolution = size
break
}
}
resolution
}
also reworked the java version a bit.
.photoResolution(this::preferredResolution)
private Resolution preferredResolution(Iterable<Resolution> resolutions) {
Resolution resolution = null;
for (Resolution size : resolutions) {
float sizeMp = size.getArea() / 1000000F;
if (sizeMp > 2F && sizeMp < 4F) {
resolution = size;
break;
}
}
return resolution;
}
The time taken for capturing photo can be lessen using low resolutions. By default fotoapparat provides ResolutionSelector with highestResolution or LowestResolution.
Even I am finding any way to provide manual resolution.
I tried taking photos in lowestResolution is awesome fast, so If I can reduce the resolution upto my need it would be better.