takePicture rawCallback返回一个空指针。 getPictureFormat仅允许使用.jpg。虽然可以使用getParameters()setJpegQuality(100)setParameters改进jpeg,但返回的图像仍然是jpeg。要获取位图图像需要调用BitmapFactory.decodeByteArray,这可能需要1/2秒才能处理。
我正在处理的应用程序需要相机可以生成的最详细的图像,这并不一定意味着漂亮。原始相机芯片捕获格式是拜耳。
答案 0 :(得分:10)
android(至少是我的)有2个相机参数"rawsave-mode"
和"rawfname"
,默认为rawsave-mode=0
。通过设置rawsave-mode=1
,相机将保存原始相机图像文件,并照常执行其他相机功能。
Camera.Parameters parameters=preview.camera.getParameters();
parameters.set("rawsave-mode", "1");
parameters.set("rawfname", "/mnt/sdcard/test.raw");
preview.camera.setParameters(parameters);
preview.camera.takePicture(shutterCallback, null, jpegCallback);
生成的文件的实际名称将被修改为包含正在生成的原始文件的参数。对于我的某个机器人,生成的名称为"test__1604x1206_10_2.raw"
,其为a1 1604x1206
图片,10bit
格式为2.而"test__1284x966_10_3.raw"
为1284x966图片,10 bit
格式3. 10 bytes
存储为2 byte short int (little endian)
。
parameters.set("rawsave-mode", "2");
// setting the rawsave-mode to 2 increased the resolution to 3204x2406
// and output the file test__3204x2406_10_2.raw
图像数据大致为8 bit
,但浮在10 bit
内,其中较亮的图像可能使用较高的值而较暗的较低。这允许图像处理软件创建直方图并捕获图像的有用范围。由于光不是常数,因此也可能需要以不同的方式调整一个通道,以使图像看起来颜色正确。网上有很多关于色彩理论的信息,可以完全解释这一点,但是新用户要注意,10 bit
到8
的转换很快就会深入。如果你想要漂亮的图片,请使用android图片捕获而不是原始图片!
格式表示位的拜耳模式。 Bayer是一种格式,其中行和列的奇数/偶数值指示像素表示的颜色,其中RGB
对于每个像素的每个颜色通道具有8 bit
值,拜耳只有一个{{ 1}}像素值,其中一个像素为红色,然后是下一个绿色,红色,绿色,红色,绿色。然后下一行有蓝色,绿色,蓝色,绿色,蓝绿色。要确定像素的10 bit
值,需要解释周围的像素。
RGB
格式3的像素顺序为
Format 2 has pixel order
// 0 1 2 3 4 5
// 0 G R G R G R
// 1 B G B G B G
// 2 G R G R G R
// 3 B G B G B G
我不确定这种技术是否适用于其他机器人,或者它是否适用于未来的机器人。如果有人试图这样做,请添加成功或失败的评论。我的手机是直接中国进口解锁iHTC Android手机已根植。
答案 1 :(得分:2)
捕获原始图像的代码:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.os.Looper;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.Window;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.view.KeyEvent;
import android.app.ProgressDialog;
import android.app.Dialog;
import android.os.Handler;
import android.os.Message;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import android.hardware.Camera.Size;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.util.Log;
public class Camera extends Activity implements SurfaceHolder.Callback {
private int mMode;
private boolean mIssdcardExist = false;
private VideoPreview mVideoPreview; //缺VideoPreview这个类
private int mPrvW = 640, mPrvH = 480;
private int mDispW = 640, mDispH = 480;
private int mPicW = 2560, mPicH = 1920;
private Camera mCamera;
private Camera.Parameters mCameraParam;
private int mIsPreviewing = 0;
private volatile int mIsFocused = 0;
private volatile int mIsCapture = 0;
private long mFocusStartTime;
private long mFocusCallbackTime;
private long mCaptureStartTime;
private long mShutterCallbackTime;
private long mRawPictureCallbackTime;
private long mJpegPictureCallbackTime;
private final AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback();
private final ShutterCallback mShutterCallback = new ShutterCallback();
private final RawPictureCallback mRawPictureCallback = new RawPictureCallback();
private static final String CAMERA_IMAGE_BUCKET_NAME = Environment.getExternalStorageDirectory().toString() + "/DCIM/CameraEM/";
private int mAFEngMode = 0;
public static final int CAPTURE_ID = Menu.FIRST;
private String TAG = "EM-Camera";
private final int DIALOG_PROGRESS = 1000;
private ProgressDlgHandler mProgressDlgHandler = new ProgressDlgHandler();
private final int EVENT_FULL_SCAN_START = 100;
private final int EVENT_FULL_SCAN_COMPLETE = 101;
private boolean mIsTest = false;
private boolean mProgressDlgExists = false;
private boolean mIsRawCapture = false;
private String mRawCaptureFileName;
private boolean mIsOnPause = false;
private int mPos = 0;
private static final int MSG_AF_MODE1_EVENT = 1001;
private static final int MSG_AF_MODE3_EVENT = 1003;
private static final int MSG_AF_MODE4_EVENT = 1004;
private mAFMode1FirstThread threadFirst;
private AFMode1Thread mode1Thread;
private AFMode2Thread mode2Thread;
private AFMode3Thread mode3Thread;
private AFMode4Thread mode4Thread;
private RawCaptureThread mRawCaptureThread;
private boolean mCanBack = true;
private Button mButtonPass;
private Button mButtonFail;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_test);
Window win = getWindow();
win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if(Environment.getExternalStorageState().equals(Environment.MEDIA_REMOVED))
{
mIssdcardExist = false;
}
else
{
File file = new File(CAMERA_IMAGE_BUCKET_NAME);
if(!file.isDirectory())
{
file.mkdirs();
}
mIssdcardExist = true;
}
mButtonPass = (Button) findViewById(R.id.camera_test_pass);
mButtonPass.setOnClickListener(mButtonHandler);
mButtonFail = (Button) findViewById(R.id.camera_test_fail);
mButtonFail.setOnClickListener(mButtonHandler);
}
@Override
public void onResume() {
super.onResume();
Log.i(TAG, "onResume ");
mVideoPreview = (VideoPreview) findViewById(R.id.camera_preview);
mVideoPreview.setAspectRatio(mPrvW, mPrvH);
SurfaceHolder holder = mVideoPreview.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mIsTest = false;
mIsOnPause = false;
}
@Override
public void onPause() {
mIsOnPause = true;
if(null != mode1Thread && true == mode1Thread.isAlive()){
try{
mode1Thread.join();
}catch(Exception e){
}
}
if(null != threadFirst && true == threadFirst.isAlive()){
try{
threadFirst.join();
}catch(Exception e){
}
}
if(null != mode2Thread && true == mode2Thread.isAlive()){
try{
mode2Thread.join();
}catch(Exception e){
}
}
if(null != mode3Thread && true == mode3Thread.isAlive()){
try{
mode3Thread.join();
}catch(Exception e){
}
}
if(null != mode4Thread && true == mode4Thread.isAlive()){
try{
mode4Thread.join();
}catch(Exception e){
}
}
if(null != mRawCaptureThread && true == mRawCaptureThread.isAlive()){
try{
mRawCaptureThread.join();
}catch(Exception e){
}
}
super.onPause();
Log.i(TAG, "super onPause.");
this.finish();
}
@Override
protected Dialog onCreateDialog(int id){
if(id == DIALOG_PROGRESS){
ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("It is in full scan, please wait......");
dialog.setCancelable(false);
return dialog;
}
return null;
}
private class ProgressDlgHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_FULL_SCAN_START:
showDialog(DIALOG_PROGRESS);
mProgressDlgExists = true;
break;
case EVENT_FULL_SCAN_COMPLETE:
dismissDialog(DIALOG_PROGRESS);
mProgressDlgExists = false;
break;
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
mDispW = w;
mDispH = h;
Log.i(TAG, "surfaceChanged width is : " + w);
Log.i(TAG, "surfaceChanged height is : " + h);
startPreview();
}
public void surfaceCreated(SurfaceHolder holder) {
openCamera();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
closeCamera();
Log.i(TAG, "surfaceCreated closeCamera ");
}
}
public void surfaceDestroyed(SurfaceHolder arg0) {
stopPreview();
closeCamera();
Log.i(TAG, "surfaceDestroyed closeCamera ");
}
private void openCamera() {
if (mCamera == null) {
mCamera = Camera.open();
Log.i(TAG, "Enter openCamera to init the mCamera.");
if(null == mCamera){
Log.i(TAG, "init the mCamera is null.");
}
}
}
private void closeCamera() {
if(null != mCamera){
mCamera.release();
mCamera = null;
}
}
private void startPreview() {
mCameraParam = mCamera.getParameters();
//GW616 Camera preview problem
// Set a preview size that is closest to the viewfinder height and has
// the right aspect ratio.
Size size = mCameraParam.getPictureSize();
List<Size> sizes = mCameraParam.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(
sizes, (double) size.width / size.height);
if (optimalSize != null) {
mCameraParam.setPreviewSize(optimalSize.width, optimalSize.height);
}
//end
// mCameraParam.setPreviewSize(mPrvW, mPrvH);
mCameraParam.set("fps-mode", 0); // Frame rate is normal
mCameraParam.set("cam-mode", 0); // Cam mode is preview
mCamera.setParameters(mCameraParam);
Log.i(TAG, "startPreview width is : " + mPrvW);
Log.i(TAG, "startPreview height is : " + mPrvH);
mCamera.startPreview();
mIsPreviewing = 1;
}
private void stopPreview() {
if(null != mCamera){
mCamera.stopPreview();
}
mIsPreviewing = 0;
}
private Size getOptimalPreviewSize(List<Size> sizes, double targetRatio) {
final double ASPECT_TOLERANCE = 0.05;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
// Because of bugs of overlay and layout, we sometimes will try to
// layout the viewfinder in the portrait orientation and thus get the
// wrong size of mSurfaceView. When we change the preview size, the
// new overlay will be created before the old one closed, which causes
// an exception. For now, just get the screen size
Display display = getWindowManager().getDefaultDisplay();
int targetHeight = Math.min(display.getHeight(), display.getWidth());
if (targetHeight <= 0) {
// We don't know the size of SurefaceView, use screen height
WindowManager windowManager = (WindowManager)
getSystemService(this.WINDOW_SERVICE);
targetHeight = windowManager.getDefaultDisplay().getHeight();
}
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
Log.v(TAG, "No preview size match the aspect ratio");
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
Log.v(TAG, String.format(
"Optimal preview size is %sx%s",
optimalSize.width, optimalSize.height));
return optimalSize;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_CAMERA:
this.CapturePicture();
return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
return true;
case KeyEvent.KEYCODE_SEARCH:
return true;
case KeyEvent.KEYCODE_FOCUS:
return true;
}
return super.onKeyDown(keyCode, event);
}
private void CapturePicture(){
if(false == mIssdcardExist)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("sdcard not available");
builder.setMessage("Please insert sdcard.");
builder.setPositiveButton("OK" , null);
builder.create().show();
return;
}
if(Environment.getExternalStorageState().equals(Environment.MEDIA_SHARED))
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("sdcard is busy");
builder.setMessage("Sorry, your SD card is busy.");
builder.setPositiveButton("OK" , null);
builder.create().show();
return;
}
if(true == mIsTest)
{
Toast.makeText(this,"It is in capturing, can not repeat capture.",Toast.LENGTH_LONG).show();
if(true == mProgressDlgExists)
{
showDialog(DIALOG_PROGRESS);
}
return;
}
Intent intent = getIntent();
int TestMode = intent.getIntExtra("TestMode", 0);
Log.i(TAG, "The value of TestMode is :" + TestMode);
if(1 == TestMode)//AF Mode
{
mMode = intent.getIntExtra("AFMode", 0);
switch(mMode){
case 1:
captureMode1();
break;
case 2:
captureMode2();
break;
case 3:
captureMode3();
break;
case 4:
captureMode4();
break;
}
}
else if(2 == TestMode)//RawCapture Mode
{
RawCapture();
}
else//not select mode yet
{
Toast.makeText(this,"Please select the test mode first!",Toast.LENGTH_LONG).show();
}
}
private void captureMode1()
{
Log.i(TAG, "Enter captureMode1 function.");
threadFirst = new mAFMode1FirstThread();
threadFirst.start();
}
class mAFMode1FirstThread extends Thread{
public void run(){
Log.i(TAG, "mAFMode1FirstThread");
mIsTest = true;
mAFEngMode = 0;
mCameraParam.set("afeng-mode", mAFEngMode);
mCameraParam.set("focus-mode", "auto");
mCameraParam.set("focus-meter", "spot");
mCamera.setParameters(mCameraParam);
mFocusStartTime = System.currentTimeMillis();
mIsFocused = 0;
mCamera.autoFocus(mAutoFocusCallback);
mCanBack = false;
takePicture();
mAFEngMode = 1;
mCameraParam.set("afeng-mode", mAFEngMode);
mCameraParam.set("focus-mode", "manual");
mCamera.setParameters(mCameraParam);
mPos = 0;
mCameraParam.set("afeng-pos", mPos);
mCamera.setParameters(mCameraParam);
startPreview();
mCanBack = true;
Sleep(2000);
mHandler.sendEmptyMessage(MSG_AF_MODE1_EVENT);
Log.i(TAG, "mAFMode1FirstThread finish.");
}
}
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg){
switch(msg.what){
case MSG_AF_MODE1_EVENT:
mode1Thread = new AFMode1Thread();
mode1Thread.start();
break;
case MSG_AF_MODE3_EVENT:
mode3Thread = new AFMode3Thread();
mode3Thread.start();
break;
case MSG_AF_MODE4_EVENT:
mode4Thread = new AFMode4Thread();
mode4Thread.start();
break;
default:
break;
}
}
};
@Override
public void onBackPressed() {
if(false == mCanBack){
return;
}
super.onBackPressed();
}
class AFMode1Thread extends Thread{
public void run(){
Log.i(TAG, "mAFMode1Thread");
if(true == mIsOnPause){
mHandler.removeMessages(MSG_AF_MODE1_EVENT);
return;
}
mCanBack = false;
takePicture();
mPos ++;
mCameraParam.set("afeng-pos", mPos);
mCamera.setParameters(mCameraParam);
startPreview();
mCanBack = true;
Sleep(2000);
if(false == mIsOnPause && mPos <= 50){
mHandler.sendEmptyMessage(MSG_AF_MODE1_EVENT);
}
if(mPos > 50){
mIsTest = false;
}
}
}
private void captureMode2()
{
Log.i(TAG, "Enter captureMode2 function.");
mode2Thread = new AFMode2Thread();
mode2Thread.start();
}
class AFMode2Thread extends Thread{
public void run(){
Log.i(TAG, "mAFMode2Thread");
mIsTest = true;
mCanBack = true;
mAFEngMode = 1;
mCameraParam.set("afeng-mode", mAFEngMode);
mCameraParam.set("focus-mode", "fullscan");
mCamera.setParameters(mCameraParam);
mIsFocused = 0;
mCamera.autoFocus(mAutoFocusCallback);
mProgressDlgHandler.sendEmptyMessage(EVENT_FULL_SCAN_START);
mCanBack = false;
takePicture();
startPreview();
mCanBack = true;
mIsTest = false;
Sleep(2000);
}
}
private void captureMode3()
{
Log.i(TAG, "Enter captureMode3 function.");
mPos = 0;
mode3Thread = new AFMode3Thread();
mode3Thread.start();
}
class AFMode3Thread extends Thread{
public void run(){
Log.i(TAG, "mAFMode3Thread");
if(true == mIsOnPause){
mHandler.removeMessages(MSG_AF_MODE3_EVENT);
return;
}
mIsTest = true;
mAFEngMode = 1;
mCameraParam.set("afeng-mode", mAFEngMode);
mCameraParam.set("focus-mode", "fullscan");
mCamera.setParameters(mCameraParam);
mIsFocused = 0;
mCamera.autoFocus(mAutoFocusCallback);
mProgressDlgHandler.sendEmptyMessage(EVENT_FULL_SCAN_START);
mCanBack = false;
takePicture();
mPos ++;
startPreview();
mCanBack = true;
Sleep(2000);
if(false == mIsOnPause && mPos <= 50){
mHandler.sendEmptyMessage(MSG_AF_MODE3_EVENT);
}
if(mPos > 50){
mIsTest = false;
}
}
}
private void captureMode4()
{
Log.i(TAG, "Enter captureMode4 function.");
mPos = 0;
mode4Thread = new AFMode4Thread();
mode4Thread.start();
}
class AFMode4Thread extends Thread{
public void run(){
Log.i(TAG, "mAFMode4Thread");
if(true == mIsOnPause){
mHandler.removeMessages(MSG_AF_MODE4_EVENT);
return;
}
mIsTest = true;
mAFEngMode = 0;
mCameraParam.set("afeng-mode", mAFEngMode);
mCameraParam.set("focus-mode", "auto");
mCameraParam.set("focus-meter", "spot");
mCamera.setParameters(mCameraParam);
mIsFocused = 0;
mCamera.autoFocus(mAutoFocusCallback);
mCanBack = false;
takePicture();
mPos ++;
startPreview();
mCanBack = true;
Sleep(2000);
if(false == mIsOnPause && mPos <= 50){
mHandler.sendEmptyMessage(MSG_AF_MODE4_EVENT);
}
if(mPos > 50){
mIsTest = false;
}
}
}
private void RawCapture()
{
Log.i(TAG, "Enter RawCapture function.");
mRawCaptureThread = new RawCaptureThread();
mRawCaptureThread.start();
}
class RawCaptureThread extends Thread{
public void run(){
Log.i(TAG, "mAFMode4Thread");
mCanBack = true;
mIsTest = true;
mIsRawCapture = true;
mCameraParam.set("rawsave-mode", "on");
long dateTaken = System.currentTimeMillis();
mRawCaptureFileName = CAMERA_IMAGE_BUCKET_NAME + createName(dateTaken);
mCameraParam.set("rawfname", mRawCaptureFileName + ".raw");
mCamera.setParameters(mCameraParam);
mCamera.autoFocus(mAutoFocusCallback);
mCanBack = false;
takePicture();
startPreview();
mCanBack = true;
mIsRawCapture = false;
mIsTest = false;
Sleep(2000);
}
}
private final class AutoFocusCallback implements android.hardware.Camera.AutoFocusCallback {
public void onAutoFocus(boolean focused, android.hardware.Camera camera) {
mFocusCallbackTime = System.currentTimeMillis();
mIsFocused = 1;
if(1 == mAFEngMode)
{
mProgressDlgHandler.sendEmptyMessage(EVENT_FULL_SCAN_COMPLETE);
}
}
}
private final class ShutterCallback implements android.hardware.Camera.ShutterCallback {
public void onShutter() {
mShutterCallbackTime = System.currentTimeMillis();
}
}
private final class RawPictureCallback implements PictureCallback {
public void onPictureTaken(byte [] rawData, android.hardware.Camera camera) {
mRawPictureCallbackTime = System.currentTimeMillis();
}
}
private final class JpegPictureCallback implements PictureCallback {
public void onPictureTaken(byte [] jpegData, android.hardware.Camera camera) {
mJpegPictureCallbackTime = System.currentTimeMillis();
if (jpegData != null) {
storeImage(jpegData);
}
mIsCapture = 0;
}
}
private void takePicture()
{
while (mIsFocused == 0) {
Sleep(100);
}
mIsCapture = 1;
mCaptureStartTime = System.currentTimeMillis();
mCamera.takePicture(mShutterCallback, mRawPictureCallback, new JpegPictureCallback());
while (mIsCapture == 1) {
Sleep(100);
}
}
private void Sleep(long time)
{
try{
Thread.sleep(time);
} catch (InterruptedException e){
e.printStackTrace();
}
}
private void storeImage(byte[] jpegData) {
long time;
long dateTaken = System.currentTimeMillis();
String name = CAMERA_IMAGE_BUCKET_NAME + createName(dateTaken) + ".jpg";
if(true == mIsRawCapture)
{
name = mRawCaptureFileName + ".jpg";
}
File fHandle = new File(name);
try {
OutputStream bos = new FileOutputStream(fHandle);
bos.write(jpegData);
bos.close();
time = System.currentTimeMillis();
} catch (Exception ex) {
fHandle.delete();
}
}
private static String createName(long dateTaken) {
return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
}
OnClickListener mButtonHandler = new OnClickListener() {
public void onClick(View v) {
SharedPreferences sharedPre = getSharedPreferences("test_results", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPre.edit();
if (v.getId() == R.id.camera_test_pass) {
Log.i("CameraTest", "-----mButtonHandler----onClick()----camera_test_pass");
editor.putBoolean("CameraTest", true);
} else if (v.getId() == R.id.camera_test_fail) {
Log.i("CameraTest", "-----mButtonHandler----onClick()----camera_test_fail");
editor.putBoolean("CameraTest", false);
}
editor.commit();
Intent intent = new Intent();
intent.setClass(CameraTest.this, SpeakerTest.class);
startActivity(intent);
finish();
}
};
}
答案 2 :(得分:1)
//将拜耳转换为rgb的丑陋代码
//test__1604x1206_10_2b.raw
//test__1284x966_10_3.raw
#include <stdio.h>
unsigned short int bayerImage[2500][3500]; //times 3 allows for forming an RGB image for debugging
unsigned char bmpImage[30000000]; //times 3 allows for forming an RGB image for debugging
#include <iomanip>
#include <iostream>
#include "bayer2rgb.h"
#include <memory.h>
#include <string.h>
/*****************************************************************************
**
*/
int DumpImage( char* pszFilename, BYTE* pImage, int bmpWidth, int bmpHeight,int bmpBits,int bmpFormat)
{
FILE *bayerFile;
FILE *rgbFile;
int x,y;
unsigned char lowOrder,highOrder;
unsigned char bmpchar;
unsigned short bayerVal;
unsigned char bmpheader[62];
char FullFilename[MY_MAX_PATH];
unsigned int bmrgbFilesize;
unsigned int minPixel=100000;
unsigned int maxPixel=0;
static unsigned int rgbValues[4][1024];
/*expecting 10 bit bayer */
if(bmpBits!=10)
{
printf("invalid bit specification\n");
return(-1);
}
if(bmpHeight >= 0)
{
bmrgbFilesize = (((bmpWidth*24+31)/32)*4)*bmpHeight;
}
else
{
bmrgbFilesize = (((bmpWidth*24+31)/32)*4)*(-bmpHeight);
}
#ifdef LINUX
strcpy( FullFilename, pszFilename );
rgbFile = fopen( FullFilename, "w+b" );
if( rgbFile )
#else
strcpy_s( FullFilename, sizeof(FullFilename), pszFilename );
errno_t errno;
errno = fopen_s( &bayerFile, FullFilename, "r+b" );
if(errno == 0)
{
printf("size %d", strlen(FullFilename)-4);
memcpy(&FullFilename[strlen(FullFilename)-4],".bmp",4);
errno = fopen_s( &rgbFile, FullFilename, "w+b" );
}
if ( errno == 0 )
#endif
{
/* 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 */
/* 0 R G R G R G 0 G R G R G R 0 B G B G B G */
/* 1 G B G B G B 1 B G B G B G 1 G R G R G R */
/* 2 R G R G R G 2 G R G R G R 2 B G B G B G */
/* 3 G B G B G B 3 B G B G B G 3 G R G R G R */
memset(bmpImage,255,sizeof(bmpImage));
switch(bmpFormat)
{
case 2:
// 0 1 2 3 4 5
// 0 G R G R G R
// 1 B G B G B G
// 2 G R G R G R
// 3 B G B G B G
for(y=0;y<bmpHeight;y++)
{
for(x=0;x<bmpWidth;x++)
{
lowOrder=fgetc(bayerFile);
highOrder=fgetc(bayerFile);
bayerVal=(highOrder * 0x100);
bayerVal+=lowOrder;
bayerImage[y][x]=bayerVal;
if(bayerVal<minPixel)
{
minPixel=bayerVal;
}
if(bayerVal>maxPixel)
{
maxPixel=bayerVal;
}
if(y%2==0)
{
if(x%2==0)
{
//green
bayerImage[y][x]=bayerVal/2;
//if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
//bayerImage[y][x]*=.65;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[0][bayerVal]++;
}
else
{
//red
bayerImage[y][x]=bayerVal/2;
//if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
//bayerImage[y][x]*=.85;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[1][bayerVal]++;
}
}
else
{
if(x%2==0)
{
//blue
bayerImage[y][x]=bayerVal/2;
//if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
//bayerImage[y][x]*=.85;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[2][bayerVal]++;
}
else
{
//green
bayerImage[y][x]=bayerVal/2;
//if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
//bayerImage[y][x]*=.65;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[3][bayerVal]++;
}
}
}
}
for(y=1;y<bmpHeight-1;y++)
{
for(x=1;x<bmpWidth-1;x++)
{
bmpchar=bayerImage[y][x]/4;
if(y%2==0)
{
if(x%2==0)
{
//green pixel bayerImage[y][x]
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//red
}
else
{
//red pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y][x]);//red
}
}
else
{
if(x%2==0)
{
//blue pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=bayerImage[y][x];//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//red
}
else
{
//green pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//red
}
}
}
}
break;
case 3:
printf("format 3\n");
// 0 1 2 3 4 5
// 0 R G R G R G
// 1 G B G B G B
// 2 R G R G R G
// 3 G B G B G B
for(y=0;y<bmpHeight;y++)
{
for(x=0;x<bmpWidth;x++)
{
lowOrder=fgetc(bayerFile);
highOrder=fgetc(bayerFile);
bayerVal=(highOrder * 0x100);
bayerVal+=lowOrder;
bayerImage[y][x]=bayerVal;
if(bayerVal<minPixel)
{
minPixel=bayerVal;
}
if(bayerVal>maxPixel)
{
maxPixel=bayerVal;
}
if(y%2==0)
{
if(x%2==0)
{
//red
bayerImage[y][x]=bayerVal;
if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
//bayerImage[y][x]*=.85;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[1][bayerVal]++;
}
else
{
//green
bayerImage[y][x]=bayerVal;
if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
bayerImage[y][x]*=.65;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[0][bayerVal]++;
}
}
else
{
if(x%2==0)
{
//green
bayerImage[y][x]=bayerVal;
if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
bayerImage[y][x]*=.65;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[3][bayerVal]++;
}
else
{
//blue
bayerImage[y][x]=bayerVal;
if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
//bayerImage[y][x]*=.85;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[2][bayerVal]++;
}
}
}
}
for(y=1;y<bmpHeight-1;y++)
{
for(x=1;x<bmpWidth-1;x++)
{
bmpchar=bayerImage[y][x]/4;
if(y%2==0)
{
if(x%2==0)
{
//red pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=bayerImage[y][x];//red
}
else
{
//green pixel bayerImage[y][x]
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//red
}
}
else
{
if(x%2==0)
{
//green pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//red
}
else
{
//blue pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=bayerImage[y][x];//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//red
}
}
}
}
break;
case 4:
// 0 1 2 3 4 5
// 0 G R G R G R
// 1 B G B G B G
// 2 G R G R G R
// 3 B G B G B G
for(y=0;y<bmpHeight;y++)
{
for(x=0;x<bmpWidth;x++)
{
lowOrder=fgetc(bayerFile);
highOrder=fgetc(bayerFile);
bayerVal=(highOrder * 0x100);
bayerVal+=lowOrder;
bayerImage[y][x]=bayerVal;
if(bayerVal<minPixel)
{
minPixel=bayerVal;
}
if(bayerVal>maxPixel)
{
maxPixel=bayerVal;
}
if(y%2==0)
{
if(x%2==0)
{
//green
bayerImage[y][x]=bayerVal;
if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
bayerImage[y][x]*=.65;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[0][bayerVal]++;
}
else
{
//red
bayerImage[y][x]=bayerVal;
if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
//bayerImage[y][x]*=.85;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[1][bayerVal]++;
}
}
else
{
if(x%2==0)
{
//blue
bayerImage[y][x]=bayerVal;
if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
//bayerImage[y][x]*=.85;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[2][bayerVal]++;
}
else
{
//green
bayerImage[y][x]=bayerVal;
if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
bayerImage[y][x]*=.65;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[3][bayerVal]++;
}
}
}
}
for(y=1;y<bmpHeight-1;y++)
{
for(x=1;x<bmpWidth-1;x++)
{
bmpchar=bayerImage[y][x]/4;
if(y%2==0)
{
if(x%2==0)
{
//green pixel bayerImage[y][x]
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x]+bayerImage[y][x+1]+bayerImage[y+1][x])/3;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=bmpImage[(((y*bmpWidth)+x)*3)+0];//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=bmpImage[(((y*bmpWidth)+x)*3)+0];//red
}
else
{
//red pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x]+bayerImage[y][x+1]+bayerImage[y+1][x+1])/3;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=bmpImage[(((y*bmpWidth)+x)*3)+0];//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=bmpImage[(((y*bmpWidth)+x)*3)+0];//red
}
}
else
{
if(x%2==0)
{
//blue pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x]+bayerImage[y+1][x]+bayerImage[y+1][x+1])/3;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=bmpImage[(((y*bmpWidth)+x)*3)+0];//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=bmpImage[(((y*bmpWidth)+x)*3)+0];//red
}
else
{
//green pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x]+bayerImage[y][x+1]+bayerImage[y+1][x])/3;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=bmpImage[(((y*bmpWidth)+x)*3)+0];//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=bmpImage[(((y*bmpWidth)+x)*3)+0];//red
}
}
}
}
break;
case 5:
// 0 1 2 3 4 5
// 0 G R G R G R
// 1 B G B G B G
// 2 G R G R G R
// 3 B G B G B G
for(y=0;y<bmpHeight;y++)
{
for(x=0;x<bmpWidth;x++)
{
lowOrder=fgetc(bayerFile);
highOrder=fgetc(bayerFile);
bayerVal=(highOrder * 0x100);
bayerVal+=lowOrder;
bayerImage[y][x]=bayerVal;
if(bayerVal<minPixel)
{
minPixel=bayerVal;
}
if(bayerVal>maxPixel)
{
maxPixel=bayerVal;
}
if(y%2==0)
{
if(x%2==0)
{
//green
bayerImage[y][x]=bayerVal;
//if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
bayerImage[y][x]/=256;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[0][bayerVal]++;
}
else
{
//red
bayerImage[y][x]=bayerVal;
//if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
bayerImage[y][x]/=256;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[1][bayerVal]++;
}
}
else
{
if(x%2==0)
{
//blue
bayerImage[y][x]=bayerVal;
//if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
bayerImage[y][x]/=256;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[2][bayerVal]++;
}
else
{
//green
bayerImage[y][x]=bayerVal;
//if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
bayerImage[y][x]/=256;
if(bayerImage[y][x]>255)
bayerImage[y][x]=255;
rgbValues[3][bayerVal]++;
}
}
}
}
for(y=1;y<bmpHeight-1;y++)
{
for(x=1;x<bmpWidth-1;x++)
{
bmpchar=bayerImage[y][x]/4;
if(y%2==0)
{
if(x%2==0)
{
//green pixel bayerImage[y][x]
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//red
}
else
{
//red pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y][x]);//red
}
}
else
{
if(x%2==0)
{
//blue pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=bayerImage[y][x];//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//red
}
else
{
//green pixel
bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//blue
bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//red
}
}
}
}
break;
default:
printf("undefined bit format\n");
return(-3);
break;
}
bmpheader[0]='\x42';
bmpheader[1]='\x4d';
bmpheader[2]='\x38';
bmpheader[3]='\x00';
bmpheader[4]='\x90';
bmpheader[5]='\x00';
bmpheader[6]='\x00';
bmpheader[7]='\x00';
bmpheader[8]='\x00';
bmpheader[9]='\x00';
bmpheader[10]='\x36';
bmpheader[11]='\x00';
bmpheader[12]='\x00';
bmpheader[13]='\x00';
bmpheader[14]='\x28';
bmpheader[15]='\x00';
bmpheader[16]='\x00';
bmpheader[17]='\x00';
bmpheader[18]='\x00';
bmpheader[19]='\x08';
bmpheader[20]='\x00';
bmpheader[21]='\x00';
bmpheader[22]='\x00';
bmpheader[23]='\x06';
bmpheader[24]='\x00';
bmpheader[25]='\x00';
bmpheader[26]='\x01';
bmpheader[27]='\x00';
bmpheader[28]='\x18';
bmpheader[29]='\x00';
bmpheader[30]='\x00';
bmpheader[31]='\x00';
bmpheader[32]='\x00';
bmpheader[33]='\x00';
bmpheader[34]='\x00';
bmpheader[35]='\x00';
bmpheader[36]='\x00';
bmpheader[37]='\x00';
bmpheader[38]='\x5a';
bmpheader[39]='\x37';
bmpheader[40]='\x00';
bmpheader[41]='\x00';
bmpheader[42]='\x5a';
bmpheader[43]='\x37';
bmpheader[44]='\x00';
bmpheader[45]='\x00';
bmpheader[46]='\x00';
bmpheader[47]='\x00';
bmpheader[48]='\x00';
bmpheader[49]='\x00';
bmpheader[50]='\x00';
bmpheader[51]='\x00';
bmpheader[52]='\x00';
bmpheader[53]='\x00';
memcpy(&bmpheader[2],&bmrgbFilesize,4);
memcpy(&bmpheader[18],&bmpWidth,4);
memcpy(&bmpheader[22],&bmpHeight,4);
fwrite( bmpheader, 1, 54, rgbFile );
fwrite( pImage, 1, bmrgbFilesize, rgbFile );
fclose( rgbFile );
fclose( bayerFile );
return(1);
}
return(-2);
} // end DumpImage()
int main(int argc, char* argv[])
{
if(argc !=2)
{
printf("wrong number of arugments\n");
printf("drag file to decode on top of program icon\n");
return(-1);
}
else
{
printf("%s\n",argv[0]);
printf("%s\n",argv[1]);
}
/*
char *str = "sdfadabcGGGGGGGGG";
char *result = strstr(str, "abc");
int position = result - str;
int substringLength = strlen(str) - position;
*/
char *widthStr = strstr(argv[1],"__")+2;
int widthInt=atoi(widthStr);
char *heightStr = strstr(widthStr,"x")+1;
int heightInt=atoi(heightStr);
char *bitsStr = strstr(heightStr,"_")+1;
int bitsInt=atoi(bitsStr);
char *formatStr = strstr(bitsStr,"_")+1;
int formatInt=atoi(formatStr);
//DumpImage( argv[1], bmpImage, widthInt, heightInt,bitsInt,formatInt);
DumpImage( argv[1], bmpImage, widthInt, heightInt,bitsInt,2);
printf("done\n");
return 1;
}