My name is Miguel, and I'm trying to get each single pixel in one .bmp, but so far, when i initialize the bitmap, it doesn't get any value, so i guess that i have initialized it wrong. This is my current code:(Snippet)
Bitmap *PerlinImage;
void OpenPerlinFile()
{
PerlinImage = new Bitmap((WCHAR*)"C:\\Users\\Utilizador\\Documents\\Visual Studio 2012\\Projects\\Cube3D\\IDTech_JavaOpenGL_Port\\perlinNoise.bmp");
}
// END
void Initialize(void)
{
OpenPerlinFile();
Unit tempunit;
Color color;
int ccount = 0;
for (int h = 0; h != PerlinImage->GetHeight(); h++)
......
Now, can you look at my code, and maybe predict what I'm doing wrong.
Thank You
Miguel Petersen
Assuming you've got the path correct, the following:
PerlinImage = new Bitmap((WCHAR*)"C:\\Users\\Utilizador\\Documents\\Visual Studio 2012\\Projects\\Cube3D\\IDTech_JavaOpenGL_Port\\perlinNoise.bmp");
should be:
PerlinImage = new Bitmap(_T("C:\\Users\\Utilizador\\Documents\\Visual Studio 2012\\Projects\\Cube3D\\IDTech_JavaOpenGL_Port\\perlinNoise.bmp"));
Or, without the helper macro:
PerlinImage = new Bitmap(L"C:\\Users\\Utilizador\\Documents\\Visual Studio 2012\\Projects\\Cube3D\\IDTech_JavaOpenGL_Port\\perlinNoise.bmp");
Invoking GdiplusStartup is needed.
Also check value of PerlinImage, if it's not NULL, then you could check error with PerlinImage->GetLastStatus(). If PerlinImage is NULL, then you may forget to call GdiplusStartup.
Related
I'm having problem with the strings in cocos2dx & C++. I want to pass the variable background to Sprite::create(background) however, I get an error. If it was in java the following code will work, but since I'm not used to C++ it may be different. Plus, if it was a int how will I pass it ? How will I be able to solve this? Some tips or samples will be great! I will love to hear from you!
void GameLayer::initBackground()
{
UserDefault *_userDef = UserDefault::getInstance();
//int型
auto _int =_userDef->getIntegerForKey("back");
auto string background = "Background1.png";
if (_int == 0) {
background = "Background2.png";
}
auto bgForCharacter = Sprite::create(background);
bgForCharacter->setAnchorPoint(Point(0, 1));
bgForCharacter->setPosition(Point(0, WINSIZE.height));
addChild(bgForCharacter, ZOrder::BgForCharacter);
auto bgForPuzzle = Sprite::create("Background2.png");
bgForPuzzle->setAnchorPoint(Point::ZERO);
bgForPuzzle->setPosition(Point::ZERO);
addChild(bgForPuzzle, ZOrder::BgForPuzzle);
}
auto userDefault=UserDefault::getInstance();
int value=userDefault->getIntegerForKey("back"); //find value for back if exist then it return that value else return 0
auto sprite = Sprite::create(value==0?"Background2.png":"Background1.png");
sprite->setPosition(100, 100);
this->addChild(sprite, 0);
When you want to change your background just put any value rather than 0
UserDefault::getInstance()->setIntegerForKey("back", 1);
My engine was recently converted to run with SDL2 for input, and video. However, I am having a hard time getting the resolution mode list building working correctly. I did study the Migration Guide for SDL2, as well as heavily research links -- I am not sure how to go about it, several failed attempts later.
So, for starters, I have a file, called i_video.cc, that handles SDL2 video code. 99% of the engine runs in OpenGL, so SDL is only there to initialize the window and set any variables.
So, here was the old way of grabbing resolution into our screen mode class. For reference, the screen mode class is defined in r_modes.cc.
With that said, here is the old SDL1-based code that builds the screen mode list, that I cannot, for the LIFE of me, get running under SDL2. This code starts at line 190 in i_video.cc. For reference, the old code:
// -DS- 2005/06/27 Detect SDL Resolutions
const SDL_VideoInfo *info = SDL_GetVideoInfo();
SDL_Rect **modes = SDL_ListModes(info->vfmt,
SDL_OPENGL | SDL_DOUBLEBUF | SDL_FULLSCREEN);
if (modes && modes != (SDL_Rect **)-1)
{
for (; *modes; modes++)
{
scrmode_c test_mode;
test_mode.width = (*modes)->w;
test_mode.height = (*modes)->h;
test_mode.depth = info->vfmt->BitsPerPixel; // HMMMM ???
test_mode.full = true;
if ((test_mode.width & 15) != 0)
continue;
if (test_mode.depth == 15 || test_mode.depth == 16 ||
test_mode.depth == 24 || test_mode.depth == 32)
{
R_AddResolution(&test_mode);
}
}
}
// -ACB- 2000/03/16 Test for possible windowed resolutions
for (int full = 0; full <= 1; full++)
{
for (int depth = 16; depth <= 32; depth = depth + 16)
{
for (int i = 0; possible_modes[i].w != -1; i++)
{
scrmode_c mode;
mode.width = possible_modes[i].w;
mode.height = possible_modes[i].h;
mode.depth = depth;
mode.full = full;
int got_depth = SDL_VideoModeOK(mode.width, mode.height,
mode.depth, SDL_OPENGL | SDL_DOUBLEBUF |
(mode.full ? SDL_FULLSCREEN : 0));
if (R_DepthIsEquivalent(got_depth, mode.depth))
{
R_AddResolution(&mode);
}
}
}
}
It is commented out, and you can see the SDL2 code above it that sets SDL_CreateWindow. The video is just fine in-game, but without resolution building, we cannot get screen-resolution changes without passing command-line arguments first before the program loads. I wish they left SOME kind of compatibility layer, because it seems SDL2 has a slight learning curve over the way I've always handled this under SDL1.
I know that ListModes and VideoInfo no longer exist, and I've tried replacing them with equivalent SDL2 functions, such as GetDisplayModes, but the code just doesn't work correctly. I am not sure how I'm supposed to do this, or if r_modes.cc just needs to be completely refactored, but all I need it to do is grab a list of video modes to populate my scrmode_c class (in r_modes.cc).
When I try to replace everything with SDL2, I get an invalid cast from SDL_Rect* to SDL_Rect**, so maybe I am just doing this all wrong. Several months I've spent trying to get it working, and it just doesn't want to. I don't care much about setting bits-per-pixel, as modern machines can just default to 24 now and we don't need any reason to set it to 16 or 8 anymore (nowadays, everyone has an OpenGL card that can go above 16-bit BPP) ;)
Any advice, help...anything at this point would be greatly appreciated =)
Thank you!
-Coraline
Use a combination of SDL_GetNumDisplayModes and SDL_GetDisplayMode, then push these back into a vector of SDL_DisplayMode.
std::vector<SDL_DisplayMode> mResolutions;
int display_count = SDL_GetNumVideoDisplays();
SDL_Log("Number of displays: %i", display_count);
for (int display_index = 0; display_index <= display_count; display_index++)
{
SDL_Log("Display %i:", display_index);
int modes_count = SDL_GetNumDisplayModes(display_index);
for (int mode_index = 0; mode_index <= modes_count; mode_index++)
{
SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
if (SDL_GetDisplayMode(display_index, mode_index, &mode) == 0)
{
SDL_Log(" %i bpp\t%i x %i # %iHz",
SDL_BITSPERPIXEL(mode.format), mode.w, mode.h, mode.refresh_rate);
mResolutions.push_back(mode);
}
}
}
I am trying to implement an MFT which is able to rotate a video. The rotation itself would be done inside a transform function. For that i need to change the output frame size but i don´t know how to do that.
As a starting point, i used the MFT_Grayscale example given by Microsoft. I included this MFT in a partial topology as a transform node
HRESULT Player::AddBranchToPartialTopology(
IMFTopology *pTopology,
IMFPresentationDescriptor *pSourcePD,
DWORD iStream
)
{
...
IMFTopologyNode pTransformNode = NULL;
...
hr = CreateTransformNode(CLSID_GrayscaleMFT, &pTransformNode);
...
hr = pSourceNode->ConnectOutput(0, pTransformNode, 0);
hr = pTransformNode->ConnectOutput(0, pOutputNode, 0);
...
}
This code is working so far. The grayscale mft is applied and working as expected. Anyway i want to change this mft to handle video rotation. So lets assume i want to rotate a video by 90 degrees. For that the width and height of my input frame have to be switched. I tried different things but none of them workes as expected.
Based on the first comment in this thread How to change Media Foundation Transform output frame(video) size? i started changing the implementation of SetOutputType. i called GetAttributeSize inside GetOutputType to receive the actual frame_size. It fails when i try to set a new frame_size (when starting playback i receive hresult 0xc00d36b4 (Data specified is invalid, inconsistent, or not supported by this object)
HRESULT CGrayscale::SetOutputType(
DWORD dwOutputStreamID,
IMFMediaType *pType, // Can be NULL to clear the output type.
DWORD dwFlags
)
{ ....
//Receive the actual frame_size of pType (works as expected)
hr = MFGetAttributeSize(
pType,
MF_MT_FRAME_SIZE,
&width,
&height
));
...
//change the framesize
hr = MFSetAttributeSize(
pType,
MF_MT_FRAME_SIZE,
height,
width
));
}
I am sure i miss something here, so any hint will be greatly appreciated.
Thanks in advance
There is a transform available in W8+ that is supposed to do rotation. I haven't had much luck with it myself, but presumably it can be made to work. I'm going to assume that's not a viable solution for you.
The more interesting case is creating an MFT to do the transform.
It turns out there are a number of steps to turn 'Grayscale' into a rotator.
1) As you surmised, you need to affect the frame size on the output type. However, changing the type being passed to SetOutputType is just wrong. The pType being sent to SetOutputType is the type that the client is asking you to support. Changing that media type to something other than what they requested, then returning S_OK to say you support it makes no sense.
Instead what you need to change is the value sent back from GetOutputAvailableType.
2) When calculating the type to send back from GetOutputAvailableType, you need to base it on the IMFMediaType the client sent to SetInputType, with a few changes. And yes, you want to adjust MF_MT_FRAME_SIZE, but you probably also need to adjust MF_MT_DEFAULT_STRIDE, MF_MT_GEOMETRIC_APERTURE, and (possibly) MF_MT_MINIMUM_DISPLAY_APERTURE. Conceivably you might need to adjust MF_MT_SAMPLE_SIZE too.
3) You didn't say whether you intended the rotation amount to be fixed at start of stream, or something that varies during play. When I wrote this, I used the IMFAttributes returned from IMFTransform::GetAttributes to specify the rotation. Before each frame is processed, the current value is read. To make this work right, you need to be able to send MF_E_TRANSFORM_STREAM_CHANGE back from OnProcessOutput.
4) Being lazy, I didn't want to figure out how to rotate NV12 or YUY2 or some such. But there are functions readily available to do this for RGB32. So when my GetInputAvailableType is called, I ask for RGB32.
I experimented with supporting other input types, like RGB24, RGB565, etc, but ran into a problem. When your output type is RGB24, MF adds another MFT downstream to convert the RGB24 back into something it can more easily use (possibly RGB32). And that MFT doesn't support changing media types mid-stream. I was able to get this to work by accepting the variety of subtypes for input, but always outputting RGB32, rotated as specified.
This sounds complicated, but mostly it isn't. If you read the code you'd probably go "Oh, I get it." I'd offer you my source code, but I'm not sure how useful it would be for you. It's in c#, and you were asking about c++.
On the other hand, I'm making a template to make writing MFTs easier. ~A dozen lines of c# code to create the simplest possible MFT. The c# rotation MFT is ~131 lines as counted by VS's Analyze/Calculate code metrics (excluding the template). I'm experimenting with a c++ version, but it's still a bit rough.
Did I forget something? Probably a bunch of things. Like don't forget to generate a new Guid for your MFT instead of using Grayscale's. But I think I've hit the high points.
Edit: Now that my c++ version of the template is starting to work, I feel comfortable posting some actual code. This may make some of the points above clearer. For instance in #2, I talk about basing the output type on the input type. You can see that happening in CreateOutputFromInput. And the actual rotation code is in WriteIt().
I've simplified the code a bit for size, but hopefully this will get you to "Oh, I get it."
void OnProcessSample(IMFSample *pSample, bool Discontinuity, int InputMessageNumber)
{
HRESULT hr = S_OK;
int i = MFGetAttributeUINT32(GetAttributes(), AttribRotate, 0);
i &= 7;
// Will the output use different dimensions than the input?
bool IsOdd = (i & 1) == 1;
// Does the current AttribRotate rotation give a different
// orientation than the old one?
if (IsOdd != m_WasOdd)
{
// Yes, change the output type.
OutputSample(NULL, InputMessageNumber);
m_WasOdd = IsOdd;
}
// Process it.
DoWork(pSample, (RotateFlipType)i);
// Send the modified input sample to the output sample queue.
OutputSample(pSample, InputMessageNumber);
}
void OnSetInputType()
{
HRESULT hr = S_OK;
m_imageWidthInPixels = 0;
m_imageHeightInPixels = 0;
m_cbImageSize = 0;
m_lInputStride = 0;
IMFMediaType *pmt = GetInputType();
// type can be null to clear
if (pmt != NULL)
{
hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &m_imageWidthInPixels, &m_imageHeightInPixels);
ThrowExceptionForHR(hr);
hr = pmt->GetUINT32(MF_MT_DEFAULT_STRIDE, &m_lInputStride);
ThrowExceptionForHR(hr);
// Calculate the image size (not including padding)
m_cbImageSize = m_imageHeightInPixels * m_lInputStride;
}
else
{
// Since the input must be set before the output, nulling the
// input must also clear the output. Note that nulling the
// input is only valid if we are not actively streaming.
SetOutputType(NULL);
}
}
IMFMediaType *CreateOutputFromInput(IMFMediaType *inType)
{
// For some MFTs, the output type is the same as the input type.
// However, since we are rotating, several attributes in the
// media type (like frame size) must be different on our output.
// This routine generates the appropriate output type for the
// current input type, given the current state of m_WasOdd.
IMFMediaType *pOutputType = CloneMediaType(inType);
if (m_WasOdd)
{
HRESULT hr;
UINT32 h, w;
// Intentionally backward
hr = MFGetAttributeSize(inType, MF_MT_FRAME_SIZE, &h, &w);
ThrowExceptionForHR(hr);
hr = MFSetAttributeSize(pOutputType, MF_MT_FRAME_SIZE, w, h);
ThrowExceptionForHR(hr);
MFVideoArea *a = GetArea(inType, MF_MT_GEOMETRIC_APERTURE);
if (a != NULL)
{
a->Area.cy = h;
a->Area.cx = w;
SetArea(pOutputType, MF_MT_GEOMETRIC_APERTURE, a);
}
a = GetArea(inType, MF_MT_MINIMUM_DISPLAY_APERTURE);
if (a != NULL)
{
a->Area.cy = h;
a->Area.cx = w;
SetArea(pOutputType, MF_MT_MINIMUM_DISPLAY_APERTURE, a);
}
hr = pOutputType->SetUINT32(MF_MT_DEFAULT_STRIDE, w * 4);
ThrowExceptionForHR(hr);
}
return pOutputType;
}
void WriteIt(BYTE *pBuffer, RotateFlipType fm)
{
Bitmap *v = new Bitmap((int)m_imageWidthInPixels, (int)m_imageHeightInPixels, (int)m_lInputStride, PixelFormat32bppRGB, pBuffer);
if (v == NULL)
throw (HRESULT)E_OUTOFMEMORY;
try
{
Status s;
s = v->RotateFlip(fm);
if (s != Ok)
throw (HRESULT)E_UNEXPECTED;
Rect r;
if (!m_WasOdd)
{
r.Width = (int)m_imageWidthInPixels;
r.Height = (int)m_imageHeightInPixels;
}
else
{
r.Height = (int)m_imageWidthInPixels;
r.Width = (int)m_imageHeightInPixels;
}
BitmapData bmd;
bmd.Width = r.Width,
bmd.Height = r.Height,
bmd.Stride = 4*bmd.Width;
bmd.PixelFormat = PixelFormat32bppARGB;
bmd.Scan0 = (VOID*)pBuffer;
bmd.Reserved = NULL;
s = v->LockBits(&r, ImageLockModeRead + ImageLockModeUserInputBuf, PixelFormat32bppRGB, &bmd);
if (s != Ok)
throw (HRESULT)E_UNEXPECTED;
s = v->UnlockBits(&bmd);
if (s != Ok)
throw (HRESULT)E_UNEXPECTED;
}
catch(...)
{
delete v;
throw;
}
delete v;
}
I am trying to mix two wav files using LibSoX on Windows. I can do this by using sox from the command line using the following command:
sox -m f1.wav f2.wav out.wav
However I want to do this programmatically using a C/C++ function and linking with LibSoX. I have built LibSoX successfully and have tried out the sample programs which do not cover a "mix" of two audio files.
Has someone done this earlier? It would be great if you can give a code snippet or at least some pointers to do this using LibSoX calls
Want to share the solution (workaround) which I made for the above issue. Basically, mixing is not exposed as an exported function call. Mixing can be done via the command line of course, so there could be two solutions: 1) spawning a process (sox.exe) via the program and 2) via libsox. I needed a libsox based solution as the function which was going to call the mixing function, could not spawn a process (constraint). So I moved the main function functionality from sox to a new method in libsox which I exported :) . So now I can pass the same command line switches to my function, and get the job done using libsox! This would be a "workaround" ideally, till Chris Bagwell exposes the mixing (and other missing) functionality from libsox.
Though this is an old question, I came across this same problem recently. In order to use the sox.c main method from your code, you'll need to reset all the globals after a call is made. sox.c was intended to run once then exit. To do that you can add a function like below. Then you can rename main, sox_main_private and things will basically work to use the command line calls directly building your argv array manually by calling sox_main()
// reset the globals so that multiple calls can be made to sox_main
static void cleanup_globals(void)
{
file_count = 0;
input_count = 0;
output_count = 0;
current_input = 0;
input_wide_samples = 0;
read_wide_samples = 0;
output_samples = 0;
input_eof = sox_false;
output_eof = sox_false;
user_abort = sox_false;
user_skip = sox_false;
user_restart_eff = sox_false;
success = 0;
files = NULL;
user_efftab = NULL;
user_efftab_size = 0;
effects_chain = NULL;
save_output_eff = NULL;
user_effargs_size = NULL; /* array: size of user_effargs for each chain */
nuser_effects = NULL; /* array: number of effects in each chain */
current_eff_chain = 0;
eff_chain_count = 0;
very_first_effchain = sox_true;
effects_filename = NULL;
play_rate_arg = NULL;
norm_level = NULL;
}
int sox_main(int argc, char *argv[])
{
#if DEBUG
printf("sox_main:\n");
int i = 0;
while (i < argc) {
printf("%s ", argv[i]);
i++;
}
printf("\n");
#endif
sox_main_private(argc, argv);
cleanup_globals();
return 0;
}
I have a working Visual Studio project.
I've created a static library with the files of the original project (except main.cpp), also
I've created a "tester" project (with the static lib linked to it) with only a main.cpp file from the original project.
Both compiles without any relevant error.
And tester runs appropriately.
But! At testing the "tester" I am getting a heap allocation error at a (not the first)
new[] operator invoked in a constructor implemented in the library.
That line working fine in the original project without any error.
The "little" version of the code:
//the staticlib
void test() {
manager* m = new manager;
m->open();
}
//....
class manager {
public:
open() {
PRAWINPUTDEVICELIST lDevList;
UINT lDevCount;
GetRawInputDeviceList(NULL, &lDevCount, sizeof(RAWINPUTDEVICELIST));
lDevList = (PRAWINPUTDEVICELIST) malloc(sizeof(RAWINPUTDEVICELIST)*lDevCount);
GetRawInputDeviceList(lDevList, &lDevCount, sizeof(RAWINPUTDEVICELIST));
if(lDevCount) {
for(UINT i = 0; i < lDevCount; i++) {
HIDP_CAPS mCaps;
PHIDP_BUTTON_CAPS mButtonCaps;
PHIDP_VALUE_CAPS mValueCaps;
UINT size;
GetRawInputDeviceInfo(lDevList[i].hDevice, RIDI_DEVICENAME, NULL, &size);
char* name = new char[size+1];
//just to be sure
memset(name, 0, size+1);
//surely sure
name[size] = '\0';
GetRawInputDeviceInfo(lDevList[i].hDevice, RIDI_DEVICENAME, name, &size);
HANDLE lDev = CreateFile((LPCWSTR)name, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);;
PHIDP_PREPARSED_DATA lPrep;
HidD_GetPreparsedData(lDev, &lPrep);
HidP_GetCaps(lPrep, &mCaps);
if(mCaps.NumberInputButtonCaps) {
//crash is here below
//mCaps.NumberInputButtonCaps ~1
mButtonCaps = new HIDP_BUTTON_CAPS[mCaps.NumberInputButtonCaps];
HidP_GetButtonCaps(HidP_Input, mButtonCaps, &mCaps.NumberInputButtonCaps, lPrep);
}
if(mCaps.NumberInputValueCaps) {
//if the first "crash-line" is commented, then
//the crash is here
mValueCaps = new HIDP_VALUE_CAPS[mCaps.NumberInputValueCaps];
HidP_GetValueCaps(HidP_Input, mValueCaps, &mCaps.NumberInputValueCaps, lPrep);
}
CloseHandle(lDev);
}
}
}
};
//the app
test();
Where I am wrong? Is it a typical novice commission I am not afraid of?
Sorry for my English, and thanks ahead for your time!
The error is that you should be allocating wide chars when you call GetRawInputDeviceInfo. From the manual
RIDI_DEVICENAME 0x20000007
pData points to a string that contains the device name.
For this uiCommand only, the value in pcbSize is the character count
(not the byte count).
In other words you should write
wchar_t* name = new wchar_t[size];
GetRawInputDeviceInfo(lDevList[i].hDevice, RIDI_DEVICENAME, name, &size);
Just from reading the manual, I have no actual experience with this API, but it seems a likely explanation.
Add logic that checks for error return states on every Win32 call you make. Possibly one of them is failing and when you remedy that, the rest will work. Always check for and handle errors when you are using Win32 APIs.