Pintura com luz: longa exposição no Android





Olá a todos, meu nome é Dmitry e sou um desenvolvedor Android na MEL Science. Hoje quero contar como é possível implementar suporte para longa exposição em smartphones, para que a imagem resultante possa ser observada logo no processo de criação. E para os interessados, no final do artigo, preparei um link para um aplicativo de teste - para que você mesmo possa tirar uma foto legal de longa exposição.





Exposição longa

Velocidade do obturador é um termo do mundo da fotografia que define o momento em que o obturador abre ao fotografar. Quanto mais tempo o obturador fica aberto, mais tempo a luz fica exposta ao sensor de luz. Simplificando, torna a foto mais brilhante. As câmeras modernas usam velocidades de obturador de 1/2000 segundo, o que permite obter uma fotografia iluminada, mas não superexposta. Uma velocidade lenta do obturador significa abri-lo por um segundo ou mais. Com a cena certa, isso permite fotografias fantásticas, capazes de capturar o movimento da luz através da lente da câmera. Além disso, você pode tirar fotos de qualquer coisa: ruas noturnas com carros de corrida ou um pêndulo com uma lanterna acoplada, permitindo desenhar as figuras de Lissajous. Ou você mesmo pode pintar com luz e obter imagens inteiras, fotografias.





Ruas da cidade fotografadas com longa exposição
,

:





  • -





  • -





- . - . - Android 30 .





.





API CameraX. . OpenGL ES . , , .









, usecase . , .





, Camera2Interop , Camera2API. , .. .





val imageCaptureBuilder = ImageCapture.Builder()
Camera2Interop.Extender(imageCaptureBuilder).apply {  
  setCaptureRequestOption(
    CaptureRequest.CONTROL_AE_MODE,
    CaptureRequest.CONTROL_AE_MODE_OFF
  )
  setCaptureRequestOption(
    CaptureRequest.SENSOR_EXPOSURE_TIME,
    EXPOSURE_TIME_SEC * NANO_IN_SEC
  )
}
      
      



, , cameraCharacteristics







val manager = getSystemService(CAMERA_SERVICE) as CameraManager
for (cameraId in manager.cameraIdList) {
  val chars = manager.getCameraCharacteristics(cameraId)
  val range = chars.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE)  
  Log.e("CameraCharacteristics", "Camera $cameraId range: ${range.toString()}")
}
      
      







.





  1. , .





  2. , .





  3. .





, . . , . 





, 2 : . .





#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform mat4 stMatrix;
uniform texType0 tex_sampler;
uniform texType1 old_tex_sampler;
varying vec2 v_texcoord;
void main() {    
    vec4 color = texture2D(tex_sampler, (stMatrix * vec4(v_texcoord.xy, 0, 1)).xy);
    vec4 oldColor = texture2D(old_tex_sampler, v_texcoord);  
    float oldBrightness = oldColor.r * 0.2126 + oldColor.g * 0.7152 + oldColor.b * 0.0722 + oldColor.a; 
    float newBrightness = color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722 + color.a;
  //  
}
      
      



:





  1. .













, , - “ ”. , , , . , , .. , . 





. . . , .





:





if (newBrightness > oldBrightness) {
  gl_FragColor = color;
} else {
  gl_FragColor = oldColor;
}
      
      



, . .





Exposição longa

, .. ! - , , ? . - . . ( , - ).  





if (newBrightness > oldBrightness) {  
  gl_FragColor = mix(color, oldColor, 0.01);
} else { 
  gl_FragColor = mix(oldColor, color, 0.01);
}
      
      



Aqui estão alguns exemplos com diferentes taxas e tempos de decaimento de luz.
Odds 0,001
Odds 0,001
Coeficiente 0,01
Coeficiente 0,01
Probabilidades 0,5
Probabilidades 0,5

Conclusão

Aqui estão alguns exemplos do que o aplicativo resultante pode fazer.  Afinal, não sou um artista: (O que você vai desenhar?
Aqui estão alguns exemplos do que o aplicativo resultante pode fazer. Afinal, não sou um artista: (O que você vai desenhar?

Isso é tudo por hoje. Para quem quiser experimentar por conta própria, o código completo do aplicativo e o apk podem ser encontrados aqui .








All Articles