java代码拍摄 java自拍

用java做图像处理,得到数码相片的亮度值,再根据亮度计算出拍摄环境的环境光? 求算法

算法能计算出个图片的亮度,但实际根本不可能计算出当时的环境光;

创新互联建站是一家集网站建设,锦州企业网站建设,锦州品牌网站建设,网站定制,锦州网站建设报价,网络营销,网络优化,锦州网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

比如你在环境光亮度 10000单位的时候 拍摄一个反光率只有0.01%的黑色物体 ,那么亮度只有1单位,你计算这个照片的亮度,只会得到“亮度=1” 这个结果

在另外一个照度为100单位的场景 拍摄反光率100%的镜子, 计算出的亮度 则是“亮度=100”

Media Module之Camera(四) 拍照 底层分析

下面主要介绍拍照流程的底层实现。

当指定了Camera的预览类,并开始预览之后,就可以通过takePicture()方法进行拍照了。它将以异步的方式从Camera中获取图像,具有多个回调类作为参数,并且都可以为null,下面分别介绍这些参数的意义:

• shutter:在按下快门的时候回调,这里可以播放一段声音。

• raw:从Camera获取到未经处理的图像。

• postview:从Camera获取一个快速预览的图片,不是所有设备都支持。

• jpeg:从Camera获取到一个经过压缩的jpeg图片。

虽然raw、postview、jpeg都是Camera.PictureCallback回调,但是一般我们只需要获取jpeg,其他传null即可,Camera.PictureCallback里需要实现一个方法onPictureTaken(byte[] data,Camera camera),data及为图像数据。值得注意的是,一般taskPicture()方法拍照完成之后,SurfaceView都会停留在拍照的瞬间,需要重新调用startPreview()才会继续预览。

如果直接使用taskPicture()进行拍照的话,Camera是不会进行自动对焦的,这里需要使用Camera.autoFocus()方法进行对焦,它传递一个Camera.AutoFocusCallback参数,用于自动对焦完成后回调,一般会在它对焦完成在进行taskPicture()拍照。

首先拍照的流程直接从Camera.java的takePicture开始分析。

可以看出,在方法中对各种回调的值进行了赋值,继续看底层对调函数的处理。

在应用层注册回调。

packages\apps\SnapdragonCamera\src\com\android\camera\AndroidCameraManagerImpl.java

在应用层实现回调。

这里就是真正存储数据的地方了,在android系统有四个地方可以存储共同数据区,

ContentProvider,sharedpreference、file、sqlite这几种方式,这里利用的是file方式。

然后调用到JNI层相应方法。

根据之前分析的binder机制,Camera.cpp - ICamera.cpp - CameraClient.cpp(server端)

此处的takepicture是在CameraHardwareInterface.h定义的方法。

frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h

在CameraClient.cpp开始调用到HAL层中进行处理,接下来主要分析在

hardware/qcom/camera/QCamera2/HAL/QCamera2HWI.cpp得具体实现。

在此方法中去更新状态机的状态。

hardware/qcom/camera/QCamera2/HAL/QCameraStateMachine.cpp

首先调用回QCamera2HWI.cpp的prepareHardwareForSnapshot方法。

接着调用到mm_camera_interface.c的mm_camera_intf_prepare_snapshot方法。

hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c

接着调用mm_camera.c的mm_camera_prepare_snapshot方法,去与V4L2通信,准备拍照。

hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera.c

当底层对拍照准备完成之后,会调用到QCamera2HWICallbacks.cpp里,处理metadata

数据的方法metadata_stream_cb_routine中。

hardware/qcom/camera/QCamera2/HAL/QCamera2HWICallbacks.cpp

之后返回到QCamera2HWI.cpp类里的take_picture方法,继续下面的操作。

此处又返回到QCamera2HWI.cpp类里的takePicture()方法中。

首先先停止并删除了preview的channel,然后调用addCaptureChannel()方法。

可以看出,在此方法中创建并初始化了channel,并且添加mediadata,postview,snapshot数据流到channel中。

返回到hardware/qcom/camera/QCamera2/HAL/QCamera2HWI.cpp的takePicture()方法中,继续调用到开启capture的channel。

channel的start方法在之前的preview流程中具体介绍过,在此不做分析。

之后又调用了QCameraChannel.cpp的startAdvancedCapture方法,然后是mm-camera-interface.c的process_advanced_capture方法,然后是mm-camera.c的mm_camera_channel_advanced_capture方法,这一系列方法设置了当前管道是拍照模式。

通过mm-jpeg-interface.c处理数据流,并且生成jpeg文件,然后在QCamera2HWI.cpp中处理从mm-jpeg-interface.c发出的jpeg相关事件。

此处更改了状态机的状态。

然后调用回QCamera2HWI.cpp的processJpegNotify方法

此处调用的是QCameraPostProc.cpp的processJpegEvt方法。

hardware/qcom/camera/QCamera2/HAL/QCameraPostProc.cpp

接着调用sendDataNotify方法。

可以看出此处在给回调的对象装填数据,并且发出通知notifyCallback回调。并且,类型为CAMERA_MSG_COMPRESSED_IMAGE。

之后的流程与preview的流程相似,将数据向上层抛送,通过JNI返回到java层的回调函数中。

java如何实现压缩图片且保留图片原文件属性,比如拍摄日期

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.util.zip.ZipEntry;

import java.util.zip.ZipInputStream;

import java.util.zip.ZipOutputStream;public class Zip {

// 压缩

public static void zip(String zipFileName, String inputFile)

throws Exception {

File f = new File(inputFile);

ZipOutputStream out = new ZipOutputStream(new FileOutputStream(

zipFileName));

zip(out, f, null);

System.out.println("zip done");

out.close();

} private static void zip(ZipOutputStream out, File f, String base)

throws Exception {

System.out.println("zipping " + f.getAbsolutePath());

if (f != null f.isDirectory()) {

File[] fc = f.listFiles();

if (base != null)

out.putNextEntry(new ZipEntry(base + "/"));

base = base == null ? "" : base + "/";

for (int i = 0; i fc.length; i++) {

zip(out, fc[i], base + fc[i].getName());

}

} else {

out.putNextEntry(new ZipEntry(base));

FileInputStream in = new FileInputStream(f);

int b;

while ((b = in.read()) != -1)

out.write(b);

in.close();

}

} // 解压

public static void unzip(String zipFileName, String outputDirectory)

throws Exception {

ZipInputStream in = new ZipInputStream(new FileInputStream(zipFileName));

ZipEntry z;

while ((z = in.getNextEntry()) != null) {

String name = z.getName();

if (z.isDirectory()) {

name = name.substring(0, name.length() - 1);

File f = new File(outputDirectory + File.separator + name);

f.mkdir();

System.out.println("MD " + outputDirectory + File.separator

+ name);

} else {

System.out.println("unziping " + z.getName());

File f = new File(outputDirectory + File.separator + name);

f.createNewFile();

FileOutputStream out = new FileOutputStream(f);

int b;

while ((b = in.read()) != -1)

out.write(b);

out.close();

}

}

in.close();

} public void deleteFolder(File dir) {

File filelist[] = dir.listFiles();

int listlen = filelist.length;

for (int i = 0; i listlen; i++) {

if (filelist[i].isDirectory()) {

deleteFolder(filelist[i]);

} else {

filelist[i].delete();

}

}

dir.delete();// 删除当前目录

} public static void main(String[] args) {

try {

// TestZip t = new TestZip();

// t.zip("c:\\test.zip","c:\\test");

// t.unzip("c:\\test.zip","c:\\test2");

} catch (Exception e) {

e.printStackTrace(System.out);

}

}

}

通过JAVA压缩图片技术,想要保留原属性,比如拍摄日期之类的,求大神详

parse方法就是把一个字符串类型的日期,转换成真正意义上日期格式的日期。比如“2013-01-01”,人眼一下就能看出来是个日期,但是对于java来说只是一个字符串,必须要转换成为Date类型java才知道这是个日期。


分享名称:java代码拍摄 java自拍
本文来源:http://hbruida.cn/article/dodjcep.html