I've encountered a problem during processing an image using c# , when I try to save my Image. the error is coming from system.drawing , which says parameter is invalid,here is my complete code , any ideas?!
thanks.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Drawing;
using System.Collections;
namespace ipp
{
class Program
{
public static byte[] ImageToArray(Image image,
System.Drawing.Imaging.ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
// Convert Image to byte[]
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();
return imageBytes;
}
}
public static Image ArrayToImage(byte[] imageBytes)
{
using (var ms = new MemoryStream(imageBytes))
{
return Image.FromStream(ms);
}
}
static void Main(string[] args)
{
Console.WriteLine("Welcome, The Operation Has Begun.");
var img = new System.Drawing.Bitmap(#"E:\gray.bmp");
byte[] image1 = ImageToArray(img, System.Drawing.Imaging.ImageFormat.Bmp);
BitArray bits = new BitArray(image1);
byte[] subar0 = new byte[image1.Length];
byte[] subar1 = new byte[image1.Length];
byte[] subar2 = new byte[image1.Length];
byte[] subar3 = new byte[image1.Length];
byte[] subar4 = new byte[image1.Length];
byte[] subar5 = new byte[image1.Length];
byte[] subar6 = new byte[image1.Length];
byte[] subar7 = new byte[image1.Length];
byte[] subarf = new byte[image1.Length];
for (int i = 0; i < bits.Length; i += 8)
{
subar0[i / 8] = Convert.ToByte(bits[i]);
}
for (int i = 1; i < bits.Length; i += 8)
{
subar1[i / 8] = Convert.ToByte(bits[i]);
}
for (int i = 2; i < bits.Length; i += 8)
{
subar2[i / 8] = Convert.ToByte(bits[i]);
}
for (int i = 3; i < bits.Length; i += 8)
{
subar3[i / 8] = Convert.ToByte(bits[i]);
}
for (int i = 4; i <= bits.Length; i += 8)
{
subar4[i / 8] = Convert.ToByte(bits[i]);
}
for (int i = 5; i < bits.Length; i += 8)
{
subar5[i / 8] = Convert.ToByte(bits[i]);
}
for (int i = 6; i < bits.Length; i += 8)
{
subar6[i / 8] = Convert.ToByte(bits[i]);
}
for (int i = 7; i < bits.Length; i += 8)
{
subar7[i / 8] = Convert.ToByte(bits[i]);
}
for (int i = 0; i < image1.Length; i++)
{
subarf[i] = Convert.ToByte(128 * subar0[i] + 64 * subar1[i]);
}
Image fout = ArrayToImage(subarf);
fout.Save("E:\\merge.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
}
}
Related
I have VST2 plugin and when I add it into vsthost, It worked with Bypass equals true, when I set Bypass equals false, It only worked with Sample Rate = 48000hz and Buffer = 4800 samples (10b/s).
Below image:
vsthost image
So, I want to set that sample rate and buffer size into my code.
Below is code that I use plugin for convert audio wavein/waveout:
public static void ConnectPlugin(bool restartDevice = false, int? inputDeviceNumber = 0, int? outputDeviceNumber = 1, bool byPass = false)
{
if (!restartDevice && waveIn != null) return;
if (waveIn != null) waveIn.Dispose();
if (waveOut != null) waveOut.Dispose();
sampleRate = 48000;
blockSize = (int)(4800);
waveIn = new WaveInEvent();
waveIn.BufferMilliseconds = 50;
waveIn.DataAvailable += Plugin_DataAvailable;
waveIn.DeviceNumber = inputDeviceNumber ?? 0;
waveIn.WaveFormat = new WaveFormat((int)sampleRate, 16, 2);
waveProviderout = new BufferedWaveProvider(waveIn.WaveFormat) { DiscardOnBufferOverflow = true };
int inputCount = _vstPlugin.PluginInfo.AudioInputCount;
int outputCount = _vstPlugin.PluginInfo.AudioOutputCount;
var inputMgr = new VstAudioBufferManager(inputCount, blockSize);
var outputMgr = new VstAudioBufferManager(outputCount, blockSize);
_vstPlugin.PluginCommandStub.Commands.SetBlockSize(blockSize);
_vstPlugin.PluginCommandStub.Commands.SetSampleRate(sampleRate);
_vstPlugin.PluginCommandStub.Commands.SetProcessPrecision(VstProcessPrecision.Process32);
// set param
_vstPlugin.PluginCommandStub.Commands.SetBypass(byPass);
inputBuffers = inputMgr.Buffers.ToArray();
outputBuffers = outputMgr.Buffers.ToArray();
waveOut = new WaveOutEvent();
waveOut.DesiredLatency = 100;
waveOut.DeviceNumber = outputDeviceNumber ?? 1;
waveOut.Init(waveProviderout);
waveOut.Play();
waveIn.StartRecording();
_vstPlugin.PluginCommandStub.Commands.MainsChanged(true);
}
private static void Plugin_DataAvailable(object sender, WaveInEventArgs e)
{
var device = (WaveInEvent)sender;
var naudioBuf = e.Buffer;
try
{
unsafe
{
int j = 0;
for (int i = 0; i < e.BytesRecorded; i++)
{
byte[] tmpbytearr = new byte[2];
tmpbytearr[0] = naudioBuf[i];
i++;
tmpbytearr[1] = naudioBuf[i];
Int16 tmpint = BitConverter.ToInt16(tmpbytearr, 0);
float f = (((float)tmpint / (float)Int16.MaxValue));
inputBuffers[0][j] = f;
inputBuffers[1][j] = f;
j++;
}
}
_vstPlugin.PluginCommandStub.Commands.StartProcess();
_vstPlugin.PluginCommandStub.Commands.ProcessReplacing(inputBuffers, outputBuffers);
_vstPlugin.PluginCommandStub.Commands.StopProcess();
//_vstPlugin.PluginCommandStub.EditorIdle();
byte[] bytebuffer;
unsafe
{
float* tmpBufLeft = ((IDirectBufferAccess32)outputBuffers[0]).Buffer;
float* tmpBufRight = ((IDirectBufferAccess32)outputBuffers[1]).Buffer;
bytebuffer = new byte[outputBuffers[0].SampleCount * 2];
int j = 0;
for (int i = 0; i < (outputBuffers[0].SampleCount * 2); i++)
{
Int16 tmpint = (Int16)((float)outputBuffers[1][j] * (float)Int16.MaxValue);
byte[] tmparr = BitConverter.GetBytes(tmpint);
bytebuffer[i] = tmparr[0];
i++;
bytebuffer[i] = tmparr[1];
j++;
}
}
waveProviderout.AddSamples(bytebuffer, 0, bytebuffer.Length);
}
catch (Exception ex)
{
Console.Out.WriteLine(ex.Message);
}
}
How do I can set sample rate and buffer in my code like vsthost
vsthost image
I would like to know how to write to a .wav file, I have written the following code which supposedly writes data to the file. But when I try to play the sound file it says the file is corrupt / empty.
try
{
SaveFileDialog save = new SaveFileDialog();
save.Filter = "Wave File (*.wav)|*.wav;";
if (save.ShowDialog() != System.Windows.Forms.DialogResult.OK)
return;
using (FileStream FS = new FileStream(save.FileName, FileMode.Open, FileAccess.Write))
{
BinaryWriter wr = new BinaryWriter(FS);
int subchunk1Size = 16;
short audioFormat = 1;
short bitsPerSample = 64;
short numChannels = 2;
int sampleRate = Convert.ToInt32(samplingRateBox.Text);
int byteRate = sampleRate * numChannels * (bitsPerSample / 8);
short blockAlign = (short)(numChannels * (bitsPerSample / 8));
int numSamples = Convert.ToInt32(numberOfsamplesBox.Text);
int subChunk2Size = numSamples * numChannels * (bitsPerSample / 8);
int chunkSize = 4 + (8 + subchunk1Size) + (8 + subChunk2Size);
wr.Write(getBytes("RIFF"));
wr.Write(chunkSize);
wr.Write(getBytes("WAVE"));
wr.Write(getBytes("fmt"));
wr.Write((byte)32);
wr.Write(subchunk1Size);
wr.Write(audioFormat);
wr.Write(numChannels);
wr.Write(sampleRate);
wr.Write(byteRate);
wr.Write(blockAlign);
wr.Write(bitsPerSample);
wr.Write(getBytes("data"));
wr.Write(subChunk2Size);
double[] primArray = new double[samples.Length];
byte[] byteArray = new byte[samples.Length * 8];
for (int i = 0; i < samples.Length; i++)
{
primArray[i] = Convert.ToDouble(samples[i].Real);
}
byteArray = doubleToBytes(primArray);
for (int i = 0; i < samples.Length; i++)
{
wr.Write(byteArray[i]);
}
for (int i = 0; i < samples.Length; i++)
{
primArray[i] = Convert.ToDouble(samples[i].Imaginary);
}
byteArray = doubleToBytes(primArray);
for (int i = 0; i < samples.Length; i++)
{
wr.Write(byteArray[i]);
}
wr.Close();
wr.Dispose();
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
As you can see I have tried converting from Complex to double, plus the header.
The sampling rate and number of samples all come from textboxes. Plus I am assuming the bit depth is that of a double.
I have also tried using this method, however the length of the audio file is 0.
This used the NAudio library.
NAudio.Wave.WaveFileWriter waveWriter = null;
WaveIn wi = new WaveIn();
double[] primArray = new double[samples.Length];
for (int i = 0; i < samples.Length; i++)
{
primArray[i] = Convert.ToDouble(samples[i].Real);
}
SaveFileDialog save = new SaveFileDialog();
save.Filter = "Wave File (*.wav)|*.wav;";
if (save.ShowDialog() != System.Windows.Forms.DialogResult.OK)
return;
wi = new NAudio.Wave.WaveIn();
wi.WaveFormat = new WaveFormat(samplingRate,1);
waveWriter = new WaveFileWriter(save.FileName, wi.WaveFormat);
byte[] byteArray = new byte[samples.Length*8];
byteArray = doubleToBytes(primArray);
waveWriter.Write(byteArray, 0, byteArray.Length);
Difficulty in source conversion
I have looked up the internal functions and related documentation supported by the DLL, but I have difficulty finding matching functions or data types.
[Calibration Find value]
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using OpenCvSharp;`
namespace Project_NFT
{
class CalibrateCamera
{
public const string ImageCalibration = "C:\\Users\\JL\\Documents\\Visual Studio 2008\\Projects\\Project NET\\Project NFT\\Image/{0:D2}.jpg";
public CalibrateCamera()
{
const int IMAGE_NUM = 3;
const int PAT_ROW = 7;
const int PAT_COL = 10;
const int PAT_SIZE = PAT_ROW * PAT_COL;
const int ALL_POINTS = IMAGE_NUM * PAT_SIZE;
const float CHESS_SIZE = 24.0f;
CvSize patternSize = new CvSize(PAT_COL, PAT_ROW);
IplImage[] srcImg = new IplImage[IMAGE_NUM];
for (int i = 0; i < IMAGE_NUM; i++)
{
string path = string.Format(ImageCalibration, i);
srcImg[i] = new IplImage(path, LoadMode.Color);
}
CvPoint3D32f[] objects = new CvPoint3D32f[ALL_POINTS];
for (int i = 0; i < IMAGE_NUM; i++)
{
for (int j = 0; j < PAT_ROW; j++)
{
for (int k = 0; k < PAT_COL; k++)
{
objects[(i * PAT_SIZE) + (j * PAT_COL) + k] = new CvPoint3D32f
{
X = j * CHESS_SIZE,
Y = k * CHESS_SIZE,
Z = 0.0f
};
}
}
}
CvMat objectPoints = new CvMat(ALL_POINTS, 3, MatrixType.F32C1, objects);
int foundNum = 0;
List<CvPoint2D32f> allCorners = new List<CvPoint2D32f>(ALL_POINTS);
int[] pCount = new int[IMAGE_NUM];
using (CvWindow window = new CvWindow("Calibration", WindowMode.AutoSize))
{
for (int i = 0; i < IMAGE_NUM; i++)
{
CvPoint2D32f[] corners;
bool found = Cv.FindChessboardCorners(srcImg[i], patternSize, out corners);
Debug.Print("{0:D2}...", i);
if (found)
{
Debug.Print("ok");
foundNum++;
}
else
{
Debug.Print("fail");
}
using (IplImage srcGray = new IplImage(srcImg[i].Size, BitDepth.U8, 1))
{
Cv.CvtColor(srcImg[i], srcGray, ColorConversion.BgrToGray);
Cv.FindCornerSubPix(srcGray, corners, corners.Length, new CvSize(3, 3), new CvSize(-1, -1), new CvTermCriteria(20, 0.03));
Cv.DrawChessboardCorners(srcImg[i], patternSize, corners, found);
pCount[i] = corners.Length;
window.ShowImage(srcImg[i]);
Cv.WaitKey(0);
}
allCorners.AddRange(corners);
}
if (foundNum != IMAGE_NUM)
{
Debug.Assert(false);
}
}
CvMat imagePoints = new CvMat(ALL_POINTS, 1, MatrixType.F32C2, allCorners.ToArray());
CvMat pointCounts = new CvMat(IMAGE_NUM, 1, MatrixType.S32C1, pCount);
CvMat intrinsic, distortion, rotation, translation;
Cv.CalibrateCamera2(objectPoints, imagePoints, pointCounts, new CvSize(640, 480), out intrinsic, out distortion, out rotation, out translation, CalibrationFlag.Default);
CvMat subImagePoints, subObjectPoints;
Cv.GetRows(imagePoints, out subImagePoints, 0, PAT_SIZE);
Cv.GetRows(objectPoints, out subObjectPoints, 0, PAT_SIZE);
Cv.FindExtrinsicCameraParams2(subObjectPoints, subImagePoints, intrinsic, distortion, out rotation, out translation);
using (CvFileStorage fs = new CvFileStorage("camera.xml", null, FileStorageMode.Write))
{
fs.Write("intrinsic", intrinsic);
fs.Write("rotation", rotation);
fs.Write("translation", translation);
fs.Write("distortion", distortion);
}
foreach (IplImage img in srcImg)
{
img.Dispose();
}
Console.WriteLine(File.ReadAllText("camera.xml"));
Console.Read();
}
}
}
[Calibration Apply Value]
CvMat intrinsic, distortion, extrinsic;
CvFileNode param;
using (CvFileStorage fs = new CvFileStorage("camera.xml", null, FileStorageMode.Read))
{
param = Cv.GetFileNodeByName (fs, null, "intrinsic");
intrinsic = fs.Read<CvMat>(param);
param = Cv.GetFileNodeByName (fs, null, "distortion");
distortion = fs.Read<CvMat>(param);
}
Cv.FindExtrinsicCameraParams2(object_points, image_points,intrinsic, distortion,
out rotation_vector, out translation_vector);
The source is the Camera Calibration reference, which is difficult to convert
I have a function that takes a variable as a parameter and returns a calculated result. That function splits up into other functions each doing their own calculation. I need the function to run multi threaded.
My code:
for (int i = 0; i < pic.Width; i++)
{
for (int k = 0; k < pic.Height; k++)
{
var localK = k;
var localI = i;
Image bestPic;
new Thread(() =>
{
bestPic = new Bitmap(getBestPic(argb));//THIS IS WHERE THE WRONG VALUES ARE ASSIGNED BECAUSE OF CROSS THREADING
lock (thisLock)
{
g.DrawImage(bestPic, localI * bestPic.Width, localK * bestPic.Height, bestPic.Width, bestPic.Height);
}
}).Start();
}
}
All I need is the function getBestPic to run multi threaded. But how do I run the function getBestPic multi threaded and make the assigning of the returned result to the bestPic variable atomic?
My entire program if needed: This is a montage program.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Drawing;
namespace test
{
public partial class Form1 : Form
{
private static readonly Object thisLock = new Object();
private Graphics g;
private Bitmap returnImg;
private Bitmap pic;
private int done = 0;
private int pictureWidthAndLength = 200;
private string inputPicName = "test";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DateTime dtStart = DateTime.Now;
pic = new Bitmap(inputPicName + ".jpg");
//MessageBox.Show(pic.GetPixel(1,1).ToArgb().ToString());
//MessageBox.Show(pic.Width.ToString() + " x " + pic.Height.ToString());
returnImg = new Bitmap(pic.Width * pictureWidthAndLength, pic.Height * pictureWidthAndLength);
using (g = Graphics.FromImage(returnImg))
{
Color clr;
int[] argb = new int[4];
for (int i = 0; i < pic.Width; i++)
{
for (int k = 0; k < pic.Height; k++)
{
clr = pic.GetPixel(i, k);
argb[0] = clr.A;
argb[1] = clr.R;
argb[2] = clr.G;
argb[3] = clr.B;
var localK = k;
var localI = i;
Image bestPic;
if (cbxthreading.Checked)
{
new Thread(() =>
{
bestPic = new Bitmap(getBestPic(argb));
lock (thisLock)
{
g.DrawImage(bestPic, localI * bestPic.Width, localK * bestPic.Height, bestPic.Width, bestPic.Height);
done++;
}
}).Start();
}
else
{
//Single threaded
bestPic = new Bitmap(getBestPic(argb));
g.DrawImage(bestPic, localI * pictureWidthAndLength, localK * pictureWidthAndLength, pictureWidthAndLength, pictureWidthAndLength);
}
//MessageBox.Show(getBestPic(argb));
}
}
if (cbxthreading.Checked)
{
int loopNum = pic.Width * pic.Height;
while (done < loopNum) { }
}
}
DateTime dtEnd = DateTime.Now;
MessageBox.Show((dtEnd - dtStart).ToString());
}
//Get picture that is best suited to replace pixel
private string getBestPic(int[] argb)
{
int numOfpics = 5;
int[] currentBest = new int[2];
currentBest[0] = 255;
currentBest[1] = 150;
for (int i = 0; i < numOfpics; i++)
{
int compare = compareARGB(getAverageRGB(new Bitmap((i + 1).ToString()+".jpg")), argb);
if (compare < currentBest[0])
{
currentBest[0] = compare;
currentBest[1] = i + 1;
}
}
return currentBest[1].ToString() + ".jpg";
}
// smaller the value, closer the camparison
private int compareARGB(int[] one, int[] two)
{
int [] tmp = new int[4];
tmp[0] = Convert.ToInt32(Math.Abs(one[0] - two[0]));
tmp[1] = Convert.ToInt32(Math.Abs(one[1] - two[1]));
tmp[2] = Convert.ToInt32(Math.Abs(one[2] - two[2]));
tmp[3] = Convert.ToInt32(Math.Abs(one[3] - two[3]));
return (tmp[0] + tmp[1] + tmp[2] + tmp[3]);
}
//return int arry with size 4 containing the argb values
private int[] getAverageRGB(Bitmap img)
{
Color clr;
int aplha = 0;
int red = 0;
int green = 0;
int blue = 0;
for (int i = 0; i < img.Width; i++)
{
for (int k = 0; k < img.Height; k++)
{
clr = img.GetPixel(i, k);
aplha += clr.A;
red += clr.R;
green += clr.G;
blue += clr.B;
}
}
aplha = aplha / (img.Width * img.Height);
red = red / (img.Width * img.Height);
green = green / (img.Width * img.Height);
blue = blue / (img.Width * img.Height);
int[] re = new int[] {aplha,red,green,blue};
return re;
}
private void button2_Click(object sender, EventArgs e)
{
returnImg.Save(inputPicName+".bmp");
MessageBox.Show("Done!");
}
}
}
The single thread functionality works, but takes long. The multi threaded functionality also finishes in a third of the time of the single threaded, but the result is not correct.
getBestPic() method runs multi-thread as I understand. But the problem is the argb parameter. You initialize it ones and then overwrite its values in for loops.argb is reference type, so only the reference is passed to getBestPic(), so it's referenced values get changed while processed in getBestPic().
I would try to pass it by Value or move int[] argb = new int[4];line to the inside of the second for loop, so you every time initialize new variable. More on passing reference type params here.
Just create a copy of the Value of your argb in the getBestPic() method and use it instead of using the original one
private string getBestPic(int[] argb)
{
int[] argbCopy = argb.ToArray();
int numOfpics = 5;
int[] currentBest = new int[2];
currentBest[0] = 255;
currentBest[1] = 150;
for (int i = 0; i < numOfpics; i++)
{
int compare = compareARGB(getAverageRGB(new Bitmap((i + 1).ToString()+".jpg")), argbCopy);
if (compare < currentBest[0])
{
currentBest[0] = compare;
currentBest[1] = i + 1;
}
}
return currentBest[1].ToString() + ".jpg";
}
i am having a little problem, VS gives me 2 warnings about two values (int[] and string[]) that are null because they are never assigned, but im sure i assigned them, this is the part of the code that is relevant to my problem:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ComponentFactory.Krypton.Toolkit;
using System.IO;
namespace DA_Story_Editor
{
public partial class Form1 : ComponentFactory.Krypton.Toolkit.KryptonForm
{
public Form1()
{
InitializeComponent();
}
int[] pntrs;
string[] Strs;
private void ReadFile(string path1)
{
FileStream stream = new FileStream(path1, FileMode.Open, FileAccess.Read);
for (int i = 0; i < Pntrnum; i++)
{
stream.Position = Pntrstrt;
stream.Read(data, 0, data.Length);
pntrs[i] = BitConverter.ToInt32(data, 0);
}
for (int i = 0; i < Pntrnum; i++)
{
byte[] sttrings = new byte[pntrs[i + 1] - pntrs[i]];
stream.Position = pntrs[i];
stream.Read(sttrings, 0, sttrings.Length);
Strs[i] = Encoding.GetEncoding("SHIFT-JIS").GetString(sttrings);
ListViewItem item = new ListViewItem(new string[]
{
pntrs[i].ToString("X"),
Strs[i],
Strs[i],
});
listView1.Items.AddRange(new ListViewItem[] {item});
}
}
}
}
im not sure why it does give me those warnings, and btw it also gives me a "NullReferenceException" on the line: pntrs[i] = BitConverter.ToInt32(data, 0);
You're never constructing and assigning the variable itself - but you try to use the array:
// Need to add:
pntrs = new int[Pntrnum];
for (int i = 0; i < Pntrnum; i++)
{
stream.Position = Pntrstrt;
stream.Read(data, 0, data.Length);
pntrs[i] = BitConverter.ToInt32(data, 0);
}
// Need to add:
Strs = new string[Pntrnum];
for (int i = 0; i < Pntrnum; i++)
{
byte[] sttrings = new byte[pntrs[i + 1] - pntrs[i]];
stream.Position = pntrs[i];
stream.Read(sttrings, 0, sttrings.Length);
Strs[i] = Encoding.GetEncoding("SHIFT-JIS").GetString(sttrings);