android - Picture convertion colours onPreviewFrame with NV21 to JPEG -
for 15 days 'm stuck on recording of frames in event onpreviewframe android camera . goal simple, want record 5 consecutive images @ click of button. not want block preview of camera , use previewframe . during recording of image in jpeg on sd card green , pink many horizontal bars. term send list of byte [] on web api.
i lot of research , trying change picturesize , previewsize nothing changes .
another option not go through recording video , extract frame of ?
here code in fragment :
package rocketweb.com.videocatcher.fragment; import android.content.context; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.graphics.imageformat; import android.graphics.rect; import android.graphics.yuvimage; import android.hardware.camera; import android.os.asynctask; import android.os.bundle; import android.os.environment; import android.util.displaymetrics; import android.util.log; import android.view.display; import android.view.layoutinflater; import android.view.surface; import android.view.surfaceholder; import android.view.surfaceview; import android.view.view; import android.view.viewgroup; import android.view.windowmanager; import android.widget.button; import android.widget.framelayout; import android.widget.toast; import org.apache.http.httpresponse; import org.apache.http.client.clientprotocolexception; import org.apache.http.client.httpclient; import org.apache.http.client.responsehandler; import org.apache.http.client.methods.httppost; import org.apache.http.entity.mime.content.bytearraybody; import org.apache.http.impl.client.basicresponsehandler; import org.apache.http.impl.client.defaulthttpclient; import java.io.bufferedreader; import java.io.bytearrayoutputstream; import java.io.datainputstream; import java.io.file; import java.io.filenotfoundexception; import java.io.fileoutputstream; import java.io.ioexception; import java.io.inputstreamreader; import java.nio.charset.charset; import java.util.arraylist; import java.util.list; import rocketweb.com.videocatcher.r; import rocketweb.com.videocatcher.utilities.imagehelper; import org.apache.http.entity.mime.multipartentity; import org.apache.http.entity.mime.content.stringbody; import org.apache.http.entity.mime.httpmultipartmode; import org.apache.http.protocol.basichttpcontext; import org.apache.http.protocol.httpcontext; /** * created bastien on 15/03/2015. */ public class camerafragment extends basefragment { private camera mcamera; private camerapreview mpreview; private view mcameraview; private list<byte[]> imagesframe; private boolean activeframecapture = false; public camerafragment(){ super(); } public static camerafragment newinstance(int sectionnumber) { camerafragment fragment = new camerafragment(); bundle args = new bundle(); args.putint(arg_section_number, sectionnumber); fragment.setarguments(args); return fragment; } @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view view = inflater.inflate(r.layout.fragment_video_catcher, container, false); boolean opened = safecameraopeninview(view); if(opened == false){ log.d("camera", "error, camera failed open"); return view; } button capturebutton = (button) view.findviewbyid(r.id.button_capture); capturebutton.setonclicklistener( new view.onclicklistener() { @override public void onclick(view v) { activeframecapture = !activeframecapture; } } ); imagesframe = new arraylist<byte[]>(){}; return view; } private boolean safecameraopeninview(view view) { boolean qopened = false; releasecameraandpreview(); mcamera = getcamerainstance(); mcameraview = view; qopened = (mcamera != null); if(qopened == true){ mpreview = new camerapreview(getactivity().getbasecontext(), mcamera,view); framelayout preview = (framelayout) view.findviewbyid(r.id.camera_preview); preview.addview(mpreview); mpreview.startcamerapreview(); } return qopened; } public static camera getcamerainstance(){ camera c = null; try { c = camera.open(); // attempt camera instance } catch (exception e){ e.printstacktrace(); } return c; // returns null if camera unavailable } @override public void onpause() { super.onpause(); } @override public void ondestroy() { super.ondestroy(); releasecameraandpreview(); } private void releasecameraandpreview() { if (mcamera != null) { mcamera.stoppreview(); mcamera.release(); mcamera = null; } if(mpreview != null){ mpreview.destroydrawingcache(); mpreview.mcamera = null; } } class camerapreview extends surfaceview implements surfaceholder.callback { private surfaceholder mholder; private camera mcamera; private context mcontext; private camera.size mpreviewsize; private list<camera.size> msupportedpreviewsizes; private list<string> msupportedflashmodes; private list<camera.size> msupportedsizepicture; private view mcameraview; public camerapreview(context context, camera camera, view cameraview) { super(context); // capture context mcameraview = cameraview; mcontext = context; setcamera(camera); // install surfaceholder.callback notified when // underlying surface created , destroyed. mholder = getholder(); mholder.addcallback(this); mholder.setkeepscreenon(true); // deprecated setting, required on android versions prior 3.0 mholder.settype(surfaceholder.surface_type_push_buffers); mcamera.setpreviewcallback(new camera.previewcallback() { public void onpreviewframe(byte[] data, camera camera) { if (activeframecapture && imagesframe.size() <= 5) { camera.parameters parameters = camera.getparameters(); camera.size size = parameters.getpreviewsize(); yuvimage im = new yuvimage(data, imageformat.nv21, size.width,size.height, null); rect r = new rect(0,0,size.width,size.height); bytearrayoutputstream baos = new bytearrayoutputstream(); im.compresstojpeg(r, parameters.getjpegquality(), baos); try{ fileoutputstream output = new fileoutputstream(string.format( "/sdcard/%s_%d.jpg", "test", system.currenttimemillis())); output.write(baos.tobytearray()); output.flush(); output.close(); }catch(filenotfoundexception e) { e.printstacktrace(); }catch(ioexception e){ e.printstacktrace(); } imagesframe.add(data); } } }); } public void startcamerapreview() { try{ mcamera.setpreviewdisplay(mholder); mcamera.startpreview(); } catch(exception e){ e.printstacktrace(); } } private void setcamera(camera camera) { mcamera = camera; msupportedpreviewsizes = mcamera.getparameters().getsupportedpreviewsizes(); msupportedflashmodes = mcamera.getparameters().getsupportedflashmodes(); msupportedsizepicture = mcamera.getparameters().getsupportedpicturesizes(); camera.parameters parameters = mcamera.getparameters(); // set camera auto flash mode. if (msupportedflashmodes != null && msupportedflashmodes.contains(camera.parameters.flash_mode_auto)) parameters.setflashmode(camera.parameters.flash_mode_auto); mcamera.setparameters(parameters); requestlayout(); } public void surfacecreated(surfaceholder holder) { try { mcamera.setpreviewdisplay(holder); } catch (ioexception e) { e.printstacktrace(); } } public void surfacedestroyed(surfaceholder holder) { if (mcamera != null){ mcamera.setpreviewcallback(null); mcamera.stoppreview(); mcamera.release(); } } public void surfacechanged(surfaceholder holder, int format, int w, int h) { // if preview can change or rotate, take care of events here. // make sure stop preview before resizing or reformatting it. if (mholder.getsurface() == null){ // preview surface not exist return; } // stop preview before making changes try { camera.parameters parameters = mcamera.getparameters(); // set auto-focus mode "continuous" parameters.setfocusmode(camera.parameters.focus_mode_continuous_picture); // preview size must exist. if(mpreviewsize != null) { // 0 = landscape // 90 = portrait int rotation = getactivity().getwindowmanager().getdefaultdisplay().getrotation(); int degrees = 0; switch (rotation) { case surface.rotation_0: degrees = 90; break; case surface.rotation_90: degrees = 0; break; } mcamera.setdisplayorientation(degrees); if(degrees == 0) parameters.setpreviewsize(mpreviewsize.width, mpreviewsize.height); else parameters.setpreviewsize(mpreviewsize.height, mpreviewsize.width); } mcamera.setparameters(parameters); mcamera.startpreview(); } catch (exception e){ e.printstacktrace(); } } /** * calculate measurements of layout * @param widthmeasurespec * @param heightmeasurespec */ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { // source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails final int width = resolvesize(getsuggestedminimumwidth(), widthmeasurespec); final int height = resolvesize(getsuggestedminimumheight(), heightmeasurespec); setmeasureddimension(width, height); if (msupportedpreviewsizes != null){ mpreviewsize = getoptimalpreviewsize(msupportedpreviewsizes, width, height); } } @override protected void onlayout(boolean changed, int left, int top, int right, int bottom) { // source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails if (changed) { final int width = right - left; final int height = bottom - top; int previewwidth = width; int previewheight = height; if (mpreviewsize != null){ display display = ((windowmanager)mcontext.getsystemservice(context.window_service)).getdefaultdisplay(); switch (display.getrotation()) { case surface.rotation_0: previewwidth = mpreviewsize.height; previewheight = mpreviewsize.width; mcamera.setdisplayorientation(90); break; case surface.rotation_90: previewwidth = mpreviewsize.width; previewheight = mpreviewsize.height; break; case surface.rotation_180: previewwidth = mpreviewsize.height; previewheight = mpreviewsize.width; break; case surface.rotation_270: previewwidth = mpreviewsize.width; previewheight = mpreviewsize.height; mcamera.setdisplayorientation(180); break; } } final int scaledchildheight = previewheight * width / previewwidth; mcameraview.layout(0, height - scaledchildheight, width, height); } } private camera.size getoptimalpreviewsize(list<camera.size> sizes, int width, int height) { // source: http://stackoverflow.com/questions/7942378/android-camera-will-not-work-startpreview-fails camera.size optimalsize = null; final double aspect_tolerance = 0.1; double targetratio = (double) height / width; // try find size match suits whole screen minus menu on left. (camera.size size : sizes){ if (size.height != width) continue; double ratio = (double) size.width / size.height; if (ratio <= targetratio + aspect_tolerance && ratio >= targetratio - aspect_tolerance){ optimalsize = size; } } // if cannot find 1 matches aspect ratio, ignore requirement. if (optimalsize == null) { // todo : backup in case don't size. } return optimalsize; } } }
the layout of fragment :
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <framelayout android:id="@+id/camera_preview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> <relativelayout android:id="@+id/innerrelativelayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentbottom="true" > <button android:id="@+id/button_capture" android:text="capture" android:layout_width="fill_parent" android:layout_height="50dp" android:layout_margin="10dp" android:layout_gravity="bottom" /> </relativelayout> </relativelayout>
my project configuration :
apply plugin: 'com.android.application' android { compilesdkversion 21 buildtoolsversion "21.1.2" defaultconfig { applicationid "rocketweb.com.videocatcher" minsdkversion 15 targetsdkversion 21 versioncode 1 versionname "1.0" } buildtypes { release { minifyenabled false proguardfiles getdefaultproguardfile('proguard-android.txt'), 'proguard-rules.pro' } } packagingoptions { exclude 'meta-inf/dependencies.txt' exclude 'meta-inf/notice.txt' exclude 'meta-inf/license.txt' } } dependencies { compile filetree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:21.0.3' compile 'com.google.code.gson:gson:2.3.1' compile "org.apache.httpcomponents:httpmime:4.2.3" }
end exemple of image result : dropbox link pictures
i can upload android studio project if needed. thank in advance help
i think problem might when try setpreviewsize()
according rotation of camera. please make sure set supported preview size contained in parameters.getsupportedpreviewsizes()
without swapping dimensions.
i suspect problem trying swap supported (width,height) pair , setting camera , it's being rejected capture parameter, still being improperly used when telling new yuvimage(...)
constructor how interpret image byte array.
Comments
Post a Comment