The two functions in openCV cvLoadImage and cvSaveImage accept file path's as arguments.
For example, when saving a image it's cvSaveImage("/tmp/output.jpg", dstIpl) and it writes on the disk.
Is there any way to feed this a buffer already in memory? So instead of a disk write, the output image will be in memory.
I would also like to know this for both cvSaveImage and cvLoadImage (read and write to memory buffers). Thanks!
My goal is to store the Encoded (jpeg) version of the file in Memory. Same goes to cvLoadImage, I want to load a jpeg that's in memory in to the IplImage format.
This worked for me
// decode jpg (or other image from a pointer)
// imageBuf contains the jpg image
cv::Mat imgbuf = cv::Mat(480, 640, CV_8U, imageBuf);
cv::Mat imgMat = cv::imdecode(imgbuf, CV_LOAD_IMAGE_COLOR);
// imgMat is the decoded image
// encode image into jpg
cv::vector<uchar> buf;
cv::imencode(".jpg", imgMat, buf, std::vector<int>() );
// encoded image is now in buf (a vector)
imageBuf = (unsigned char *) realloc(imageBuf, buf.size());
memcpy(imageBuf, &buf[0], buf.size());
// size of imageBuf is buf.size();
I was asked about a C version instead of C++:
#include <opencv/cv.h>
#include <opencv/highgui.h>
int
main(int argc, char **argv)
{
char *cvwin = "camimg";
cvNamedWindow(cvwin, CV_WINDOW_AUTOSIZE);
// setup code, initialization, etc ...
[ ... ]
while (1) {
// getImage was my routine for getting a jpeg from a camera
char *img = getImage(fp);
CvMat mat;
// substitute 640/480 with your image width, height
cvInitMatHeader(&mat, 640, 480, CV_8UC3, img, 0);
IplImage *cvImg = cvDecodeImage(&mat, CV_LOAD_IMAGE_COLOR);
cvShowImage(cvwin, cvImg);
cvReleaseImage(&cvImg);
if (27 == cvWaitKey(1)) // exit when user hits 'ESC' key
break;
}
cvDestroyWindow(cvwin);
}
There are a couple of undocumented functions in the SVN version of the libary:
CV_IMPL CvMat* cvEncodeImage( const char* ext,
const CvArr* arr, const int* _params )
CV_IMPL IplImage* cvDecodeImage( const CvMat* _buf, int iscolor )
Latest check in message states that they are for native encoding/decoding for bmp, png, ppm and tiff (encoding only).
Alternatively you could use a standard image encoding library (e.g. libjpeg) and manipulate the data in the IplImage to match the input structure of the encoding library.
I'm assuming you're working in linux. From libjpeg.doc:
The rough outline of a JPEG
compression operation is:
Allocate
and initialize a JPEG compression
object
Specify the destination for
the compressed data (eg, a file)
Set
parameters for compression, including
image size & colorspace
jpeg_start_compress(...);
while
(scan lines remain to be written)
jpeg_write_scanlines(...);
jpeg_finish_compress(...);
Release
the JPEG compression object
The real trick for doing what you want to do is providing a custom "data destination (or source) manager" which is defined in jpeglib.h:
struct jpeg_destination_mgr {
JOCTET * next_output_byte; /* => next byte to write in buffer */
size_t free_in_buffer; /* # of byte spaces remaining in buffer */
JMETHOD(void, init_destination, (j_compress_ptr cinfo));
JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
JMETHOD(void, term_destination, (j_compress_ptr cinfo));
};
Basically set that up so your source and/or destination are the memory buffers you want, and you should be good to go.
As an aside, this post could be a lot better but the libjpeg62 documentation is, quite frankly, superb. Just apt-get libjpeg62-dev and read libjpeg.doc and look at example.c. If you run into problems and can't get something to work, just post again and I'm sure someone will be able to help.
All you need to load files from the memory buffer is a different src manager (libjpeg). I have tested the following code in Ubuntu 8.10.
/******************************** First define mem buffer function bodies **************/
<pre>
/*
* memsrc.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains decompression data source routines for the case of
* reading JPEG data from a memory buffer that is preloaded with the entire
* JPEG file. This would not seem especially useful at first sight, but
* a number of people have asked for it.
* This is really just a stripped-down version of jdatasrc.c. Comparison
* of this code with jdatasrc.c may be helpful in seeing how to make
* custom source managers for other purposes.
*/
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
//include "jinclude.h"
include "jpeglib.h"
include "jerror.h"
/* Expanded data source object for memory input */
typedef struct {
struct jpeg_source_mgr pub; /* public fields */
JOCTET eoi_buffer[2]; /* a place to put a dummy EOI */
} my_source_mgr;
typedef my_source_mgr * my_src_ptr;
/*
* Initialize source --- called by jpeg_read_header
* before any data is actually read.
*/
METHODDEF(void)
init_source (j_decompress_ptr cinfo)
{
/* No work, since jpeg_memory_src set up the buffer pointer and count.
* Indeed, if we want to read multiple JPEG images from one buffer,
* this *must* not do anything to the pointer.
*/
}
/*
* Fill the input buffer --- called whenever buffer is emptied.
*
* In this application, this routine should never be called; if it is called,
* the decompressor has overrun the end of the input buffer, implying we
* supplied an incomplete or corrupt JPEG datastream. A simple error exit
* might be the most appropriate response.
*
* But what we choose to do in this code is to supply dummy EOI markers
* in order to force the decompressor to finish processing and supply
* some sort of output image, no matter how corrupted.
*/
METHODDEF(boolean)
fill_input_buffer (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
WARNMS(cinfo, JWRN_JPEG_EOF);
/* Create a fake EOI marker */
src->eoi_buffer[0] = (JOCTET) 0xFF;
src->eoi_buffer[1] = (JOCTET) JPEG_EOI;
src->pub.next_input_byte = src->eoi_buffer;
src->pub.bytes_in_buffer = 2;
return TRUE;
}
/*
* Skip data --- used to skip over a potentially large amount of
* uninteresting data (such as an APPn marker).
*
* If we overrun the end of the buffer, we let fill_input_buffer deal with
* it. An extremely large skip could cause some time-wasting here, but
* it really isn't supposed to happen ... and the decompressor will never
* skip more than 64K anyway.
*/
METHODDEF(void)
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
if (num_bytes > 0) {
while (num_bytes > (long) src->pub.bytes_in_buffer) {
num_bytes -= (long) src->pub.bytes_in_buffer;
(void) fill_input_buffer(cinfo);
/* note we assume that fill_input_buffer will never return FALSE,
* so suspension need not be handled.
*/
}
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
/*
* An additional method that can be provided by data source modules is the
* resync_to_restart method for error recovery in the presence of RST markers.
* For the moment, this source module just uses the default resync method
* provided by the JPEG library. That method assumes that no backtracking
* is possible.
*/
/*
* Terminate source --- called by jpeg_finish_decompress
* after all data has been read. Often a no-op.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
METHODDEF(void)
term_source (j_decompress_ptr cinfo)
{
/* no work necessary here */
}
/*
* Prepare for input from a memory buffer.
*/
GLOBAL(void)
jpeg_memory_src (j_decompress_ptr cinfo, const JOCTET * buffer, size_t bufsize)
{
my_src_ptr src;
/* The source object is made permanent so that a series of JPEG images
* can be read from a single buffer by calling jpeg_memory_src
* only before the first one.
* This makes it unsafe to use this manager and a different source
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_source_mgr));
}
src = (my_src_ptr) cinfo->src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->pub.term_source = term_source;
src->pub.next_input_byte = buffer;
src->pub.bytes_in_buffer = bufsize;
}
Then the usage is pretty simple. You may need to replace SIZEOF() with sizeof(). Find a standard decompression example. Just replace "jpeg_stdio_src" with "jpeg_memory_src". Hope that helps!
Here's an example in Delphi. It converts a 24bit bitmap for use with OpenCV
function BmpToPIplImageEx(Bmp: TBitmap): pIplImage;
Var
i: Integer;
offset: LongInt;
dataByte: PByteArray;
Begin
Assert(Bmp.PixelFormat = pf24bit, 'PixelFormat must be 24bit');
Result := cvCreateImageHeader(cvSize(Bmp.Width, Bmp.Height), IPL_DEPTH_8U, 3);
cvCreateData(Result);
for i := 0 to Bmp.height - 1 do
Begin
offset := longint(Result.imageData) + Result.WidthStep * i;
dataByte := PByteArray(offset);
CopyMemory(dataByte, Bmp.Scanline[i], Result.WidthStep);
End;
End;
This is an indirect answer...
In the past, I've directly used libpng and libjpeg directly to do this. They have a low-level enough API that you can use memory buffers instead of file buffers for reading and writing.
Related
I'm using FFmpe's swr_convert to convert AV_SAMPLE_FMT_FLTP audio. I've been successful converting to a different sample format (e.g. AV_SAMPLE_FMT_FLT and AV_SAMPLE_FMT_S16), but I'm running into trouble when I'm trying to keep the AV_SAMPLE_FMT_FLTP sample format but change the sample rate.
When converting AV_SAMPLE_FMT_FLTP to AV_SAMPLE_FMT_FLTP, swr_convert attempts to write to an empty buffer.
I'm using swr_convert to convert from 22050 Hz AV_SAMPLE_FMT_FLTP to 16000 Hz AV_SAMPLE_FMT_FLTP.
I initialized SwrContext like so:
if (swr_alloc_set_opts2(
&resample_context,
&pAVContext->ch_layout, AV_SAMPLE_FMT_FLTP, 16000,
&pAVContext->ch_layout, AV_SAMPLE_FMT_FLTP, 22050, 0, NULL) < 0)
return ERR_SWR_INIT_FAIL;
if(swr_init(resample_context) < 0)
return ERR_SWR_INIT_FAIL;
and when I call it like this, the program tries to write to a null buffer and crashes.
samples_decoded = swr_convert(ctx->pSwrContext,
&pDecodedAudio, numOutSamples,
(const uint8_t**)&pDecodedFrame->data, pDecodedFrame->nb_samples);
So far I've traced the problem to swr_convert_internal
if(s->int_sample_fmt == s->out_sample_fmt && s->out.planar
&& !(s->out_sample_fmt==AV_SAMPLE_FMT_S32P && (s->dither.output_sample_bits&31))){
//Sample format is planar and input format is same as output format
if(preout==in){
out_count= FFMIN(out_count, in_count);
av_assert0(s->in.planar);
copy(out, in, out_count);
return out_count;
}
else if(preout==postin) preout= midbuf= postin= out;
else if(preout==midbuf) preout= midbuf= out;
else preout= out;
}
That if bit of code assigns out to preout, but out's data is unitialized. Later on FFmpeg tries to write to the uninitialized block.
I've tested this in 5.1 and in the snapshot build, and it crashes both of them.
So, am I doing something wrong, or is this a bug?
I was doing something wrong. Packet audio is a contiguous block of memory and can be referenced by one pointer, but planar audio has a different pointer to each channel. To fix this, I got two pointers to my pDecodedAudio block.
uint8_t* convertedData [2] = {
pDecodedAudio ,
pDecodedAudio + (numOutSamples * ctx->output_sample_size)
};
samples_decoded = swr_convert(ctx->pSwrContext,
convertedData, numOutSamples,
pDecodedFrame->data, pDecodedFrame->nb_samples);
See the comments in AVFrame.
/*
* For planar audio, each channel has a separate data pointer, and
* linesize[0] contains the size of each channel buffer.
* For packed audio, there is just one data pointer, and linesize[0]
* contains the total size of the buffer for all channels.
*
* Note: Both data and extended_data should always be set in a valid frame,
* but for planar audio with more channels that can fit in data,
* extended_data must be used in order to access all channels.
*/
uint8_t **extended_data;
In my C program I would like to use libexif along with libjpeg to set exif tags on an existing jpeg file present at a given path inputFilePath, and save the resulting jpeg to output path outputFilePath.
The input jpeg file is large (40000 X 40000 pixels) so loading the whole image in memory isn't preferable and shouldn't be needed.
I don't care about other existing Exif tags in the Jpeg, they may be removed.
I have read and tried the example provided with libexif which uses a fixed JPEG, but just can't figure out how to do the same for any JPEG.
Btw, I did get the following code which sets exif tags by loading the jpeg in-memory to work. It uses the libjpeg implementation provided in exif utility that comes along with libexif.
ExifEntry *entry;
ExifData *exif = exif_data_new();
if (!exif) {
//Out of memory
}
/* Set the image options */
exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED);
exif_data_set_byte_order(exif, FILE_BYTE_ORDER);
/* Create the mandatory EXIF fields with default data */
exif_data_fix(exif);
/* All these tags are created with default values by exif_data_fix() */
/* Change the data to the correct values for this image. */
entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION);
exif_set_long(entry->data, FILE_BYTE_ORDER, w);
entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION);
exif_set_long(entry->data, FILE_BYTE_ORDER, h);
entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_COLOR_SPACE);
exif_set_short(entry->data, FILE_BYTE_ORDER, 1);
/* Create a EXIF_TAG_USER_COMMENT tag. This one must be handled
* differently because that tag isn't automatically created and
* allocated by exif_data_fix(), nor can it be created using
* exif_entry_initialize() so it must be explicitly allocated here.
*/
entry = create_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT,
sizeof(ASCII_COMMENT) + sizeof(FILE_COMMENT) - 2);
/* Write the special header needed for a comment tag */
memcpy(entry->data, ASCII_COMMENT, sizeof(ASCII_COMMENT) - 1);
/* Write the actual comment text, without the trailing NUL character */
memcpy(entry->data + 8, FILE_COMMENT, sizeof(FILE_COMMENT) - 1);
/* create_tag() happens to set the format and components correctly for
* EXIF_TAG_USER_COMMENT, so there is nothing more to do. */
JPEGData *jdata;
unsigned char *d = NULL;
unsigned int ds;
ExifLog *log = NULL;
/* Parse the JPEG file. */
jdata = jpeg_data_new();
jpeg_data_log(jdata, log);
jpeg_data_load_file(jdata, inputFilePath);
/* Make sure the EXIF data is not too big. */
exif_data_save_data(exif, &d, &ds);
if (ds) {
free(d);
if (ds > 0xffff)
//Too much EXIF data
};
jpeg_data_set_exif_data(jdata, exif);
/* Save the modified image. */
jpeg_data_save_file(jdata, outputFilePath);
jpeg_data_unref(jdata);
If you aren't re-compressing or editing the image, then you won't need libjpeg. It can be done with fopen and fputc.
There's a good description of the JPEG file structure and metadata from exiv2. Most jpeg files will start with 0xFFD8 (start of image), then an APP0 block for JFIF data (0xFF E0 <length> <data>). If there is an EXIF header, it's in the APP1 block (0xFF E1 <length> <data>).
The blocks in a JPEG file are formatted as
Marker (0xFF xx) where xx is En for APPn blocks
Content
2 bytes - length of content in bytes including these 2 bytes
data
So, an outline of your program would be
Copy the file until the APP1 block
Write your APP1 block instead
Copy the rest of the file
The EXIF header contents can be created with exif_data_save_data() in libexif.
My project let me use C++ Windows RPC to upload image from client to server. I do not use WIN RPC before, So I tried some examples include send basic "Hello world" Message to server, but the huge issue is the function can't send unsigned char* include '\0'. I appreciate someone can give me some suggestion to solve this problem.
I use opencv 3.2 to read image to Mat, and I can get Mat data and use memcpy to copy the Mat.data then create a new image in local client. But when I send Mat.data to server, the first of characters in the Mat.data is '\0'. All the Mat.data don't send to server.
My MIDL core code(I have defined uuid and version) is
void Output(
[in, out, size_is(1048576), string] unsigned char szString[]
);
void Output1(
[in, string] unsigned char* szString1
);
My Client core code(It has include all require header) is
Mat I = imread("U:\\normal.jpg", IMREAD_ANYDEPTH);
if (I.empty())
{
std::cout << "!!! Failed imread(): image not found" << std::endl;
// don't let the execution continue, else imshow() will crash.
}
if (!I.data) {
std::cout << "can't open or find image" << std::endl;
//return -1;
}
Mat out;
I.convertTo(I, CV_32F);
I = (I.reshape(0, 1)); // to make it continuous
char tr[512*512*4];
memcpy_s(tr, 512 * 512 * 4, I.data, 512*512 * 4);
//snprintf(tr, 512*512*4,"%s", I.data);
out = Mat(512,512, CV_32F, &tr[0]);
namedWindow("Display window", CV_WINDOW_AUTOSIZE);// Create a window for display.
imshow("Display window", out);
waitKey(5000);
.....
RpcTryExcept
{
std::clog << "Calling Open" << std::endl;
output((unsigned char* )tr);
//output1((unsigned char* )tr);
}
Server side is pretty same with client, I use break point in server to debug, but server side can't get the unsigned char array. I think it's because my function in MIDL just can send the char array, which is end by a null terminated('\0') string? I tried set the array length or the size of the char pointer but still can't transmit '\0' unsigned char to server.
From the MSDN explanation, when you sending array to stub you need to specify length_is also in your midl code.
The [ size_is] attribute indicates the upper bound of the array while the [ length_is] attribute indicates the number of array elements to transmit. In addition to the array, the remote procedure prototype must include any variables representing length or size that determine the transmitted array elements (they can be separate parameters or bundled with the string in a structure). These attributes can be used with wide-character or single-byte character arrays just as they would be with arrays of other types.
And
As an [in] parameter, achInOut must point to valid storage on the client side. The developer allocates memory associated with the array on the client side before making the remote procedure call.
The stubs use the [size_is] parameter strsize to allocate memory on the server and then use the [length_is] parameter pcbSize to transmit the array elements into this memory. The developer must make sure the client code sets the [length_is] variable before calling the remote procedure.
Their example of character array sending:
#define STRSIZE 500 //maximum string length
void Analyze(
[in, out, length_is(*pcbSize), size_is(STRSIZE)] char achInOut[],
[in, out] long *pcbSize);
/* client */
char achInOut[STRSIZE];
long cbSize;
...
gets_s(achInOut, STRSIZE); // get patient input
cbSize = strlen(achInOut) + 1; // transmit '\0' too
Analyze(achInOut, &cbSize);
/* server */
Analyze(char * str, long * pcbSize)
{
...
*pcbSize = strlen(str) + 1; // transmit '\0' too
return;
}
I think, this msdn link will help you.
Do you have to use OpenCV to read image data? Since this post has not been closed, you can try this alternative way to open image file(it works for text file as well) in binary mode, then read/save data into a float array, send it to server. I wrote a simple demo. It works and avoid the null-terminator problem for string.
Sender:
//Open file
char filename[] = "demo1.jpg";
FILE *fp = fopen(filename,"rb");
//Get File size
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fseek(fp, 0, SEEK_SET);
//Read file to buffer
float *img = new float[size];
fread(img, 1, size, fp);
RpcTryExcept
{
//Call your function pre-defined in IDL here to send float arry
}
Receiver:
FILE *fp = fopen((char *)fileName, "wb");
int recvByte = fwrite(img, 1, size, fp);
I am trying to get sound from simple tapping keyboard. Looks like a little drum machine.
If DirectSound is not a proper way to do this, please suggest something else.
In my code I don't know what's wrong. Here it is without error checking and with translations:
//Declaring the IDirectSound object
IDirectSound* device;
DirectSoundCreate(NULL, &device, NULL);
device->SetCooperativeLevel(hWnd, DSSCL_NORMAL );
/* Declaring secondary buffers */
IDirectSoundBuffer* kickbuf;
IDirectSoundBuffer* snarebuf;
/* Declaring .wav files pointers
And to structures for reading the information int the begining of the .wav file */
FILE* fkick;
FILE* fsnare;
sWaveHeader kickHdr;
sWaveHeader snareHdr;
The structure sWaveHeader is declared this way:
typedef struct sWaveHeader
{
char RiffSig[4]; // 'RIFF'
unsigned long WaveformChunkSize; // 8
char WaveSig[4]; // 'WAVE'
char FormatSig[4]; // 'fmt '
unsigned long FormatChunkSize; // 16
unsigned short FormatTag; // WAVE_FORMAT_PCM
unsigned short Channels; // Channels
unsigned long SampleRate;
unsigned long BytesPerSec;
unsigned short BlockAlign;
unsigned short BitsPerSample;
char DataSig[4]; // 'data'
unsigned long DataSize;
} sWaveHeader;
The .wav file opening
#define KICK "D:/muzic/kick.wav"
#define SNARE "D:/muzic/snare.wav"
fkick = fopen(KICK, "rb")
fsnare = fopen(SNARE, "rb")
Here I make a function that does the common work for snarebuf* and **kickbuf
int read_wav_to_WaveHeader (sWaveHeader* , FILE* , IDirectSoundBuffer* ); // The declaring
But I wil not write this function, just show the way it works with kickbuf, for instance.
fseek(fkick, 0, SEEK_SET); // Zero the position in file
fread(&kickHdr, 1, sizeof(sWaveHeader), fkick); // reading the sWaveHeader structure from file
Here goes a checking for fitting if sWaveHeader structure:
if(memcmp(pwvHdr.RiffSig, "RIFF", 4) ||
memcmp(pwvHdr.WaveSig, "WAVE", 4) ||
memcmp(pwvHdr.FormatSig, "fmt ", 4) ||
memcmp(pwvHdr.DataSig, "data", 4))
return 1;
Declaring the format and descriptor for a buffer and filling them:
DSBUFFERDESC bufDesc;
WAVEFORMATEX wvFormat;
ZeroMemory(&wvFormat, sizeof(WAVEFORMATEX));
wvFormat.wFormatTag = WAVE_FORMAT_PCM;
wvFormat.nChannels = kickHdr.Channels;
wvFormat.nSamplesPerSec = kickHdr.SampleRate;
wvFormat.wBitsPerSample = kickHdr.BitsPerSample;
wvFormat.nBlockAlign = wvFormat.wBitsPerSample / 8 * wvFormat.nChannels;
ZeroMemory(&bufDesc, sizeof(DSBUFFERDESC));
bufDesc.dwSize = sizeof(DSBUFFERDESC);
bufDesc.dwFlags = DSBCAPS_CTRLVOLUME |
DSBCAPS_CTRLPAN |
DSBCAPS_CTRLFREQUENCY;
bufDesc.dwBufferBytes = kickHdr.DataSize;
bufDesc.lpwfxFormat = &wvFormat;
Well, the creating of a buffer:
device->CreateSoundBuffer(&bufDesc, &kickbuf, NULL); // Any mistakes by this point?
Now locking the buffer and loading some data to it.
This data starts after sizeof(sWaveHeader) bytes in a WAVE file, am I wrong?
LPVOID Ptr1; // pointer on a pointer on a First block of data
LPVOID Ptr2; // pointer on a pointer on a Second block of data
DWORD Size1, Size2; // their sizes
Now calling the Lock() method:
kickbuf->Lock((DWORD)LockPos, (DWORD)Size,
&Ptr1, &Size1,
&Ptr2, &Size2, 0);
Loading data (is it ok?):
fseek(fkick, sizeof(sWaveHeader), SEEK_SET);
fread(Ptr1, 1, Size1, fkick);
if(Ptr2 != NULL)
fread(Ptr2, 1, Size2, fkick);
Unlocking the buffer:
kickbuf->Unlock(Ptr1, Size1, Ptr2, Size2);
Setting the volume:
kickbuf->SetVolume(-2500);
Then I make a wile(1) looping:
1. ask for a key pressing
2. if it is pressed:
kickbuf->SetCurrentPosition(0)
kickbuf->Play(0,0,0);
But there's no sound playing, please say, what is not proper in my code or maybe in the whole concept. Thank you.
When you initialize the WAVEFORMATEX, your are forgetting to set the nAvgBytesPerSec member. Add this line after the initialization of wvFormat.nBlockAlign:
wvFormat.nAvgBytesPerSec = wvFormat.nSamplesPerSec * wvFormat.nBlockAlign;
Also, I suspect this could be a problem:
kickbuf->SetVolume(-2500);
I suspect that will just attenuate your sample to absolute silence. Try taking that call out so that it plays at full volume.
But more likely, none of you sample code above shows validation of the return values from any of the DirectSound APIs, nor any of the file I/O values. Have you validated the HRESULTs returned by all the DSound APIs are returning S_OK? Have you tried printing or using OutputDebugString to print the values you computed for the members of WAVEFORMATEX?
Have you debugging the fread calls to validate that you are getting valid data into your buffers?
Hope this helps.
I have a task to edit exif tags and add to them application specific values.
if the exif tags exist libexif is more than happy to edit them .
but if the exif tags don't exist, i will have to create them and append them to file.
libexif uses the C fopen so i don't think there is going to be an easy way without some IO manipulation.
I am thinking to read the raw image data put them in memory , fopen(newfile, 'w')
add the exif data
and then append the image data.
only if someone knows an easier way , ( i am restricted with libexif, libexiv2 might create a liscence conflict) .
for the common good i am going to answer my own question, exif application has a modified libjpeg that enable the manipulation of the jpeg raw data.
it has functions like
jpeg_data_load_data (JPEGData *data, const unsigned char *d,unsigned int size);
and
jpeg_data_set_exif_data(myJPEGImage,exif); jpeg_data_save_file(myJPEGImage,"gangrene1.jpg");
That can be used, also free available programs like imagemagick have their own libjpeg , libexif implementation to do manipulate exif and jpeg data.
Hopes this helps
I have just gone down the same road as you with choosing between libexif and libexiv2. I went with libexif due to the licensing.
Back to the question at hand,
libexif doesn't support directly loading JPG's in. You'll need another package to read in the JPG and extract the EXIF header (or you could write something yourself).
There is an excellent Github project called exifyay that uses libexif and has two extra libs that handle reading in JPGS. It is a python project but the sources for the libraries are C. You can find exifyay here (note I am not involved in any way with exifyay or libexif)
I have just recently compiled libexif and merged sources from exifyay into a VS2010 project here. There is an example in the folder 'contrib\examples\LibexifExample'. If you don't like downloading random links here is a sample of the code I got working:
/*
* write-exif.c
*
* Placed into the public domain by Daniel Fandrich
*
* Create a new EXIF data block and write it into a JPEG image file.
*
* The JPEG image data used in this example is fixed and is guaranteed not
* to contain an EXIF tag block already, so it is easy to precompute where
* in the file the EXIF data should be. In real life, a library like
* libjpeg (included with the exif command-line tool source code) would
* be used to write to an existing JPEG file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <libexif/exif-data.h>
#include <libjpeg/jpeg-data.h>
#include <JpegEncoderEXIF/JpegEncoderEXIF.h>
/* byte order to use in the EXIF block */
#define FILE_BYTE_ORDER EXIF_BYTE_ORDER_INTEL
/* comment to write into the EXIF block */
#define FILE_COMMENT "libexif demonstration image"
/* special header required for EXIF_TAG_USER_COMMENT */
#define ASCII_COMMENT "ASCII\0\0\0"
static ExifEntry *create_tag(ExifData *exif, ExifIfd ifd, ExifTag tag, size_t len)
{
void *buf;
ExifEntry *entry;
/* Create a memory allocator to manage this ExifEntry */
ExifMem *mem = exif_mem_new_default();
assert(mem != NULL); /* catch an out of memory condition */
/* Create a new ExifEntry using our allocator */
entry = exif_entry_new_mem (mem);
assert(entry != NULL);
/* Allocate memory to use for holding the tag data */
buf = exif_mem_alloc(mem, len);
assert(buf != NULL);
/* Fill in the entry */
entry->data = (unsigned char*)buf;
entry->size = len;
entry->tag = tag;
entry->components = len;
entry->format = EXIF_FORMAT_UNDEFINED;
/* Attach the ExifEntry to an IFD */
exif_content_add_entry (exif->ifd[ifd], entry);
/* The ExifMem and ExifEntry are now owned elsewhere */
exif_mem_unref(mem);
exif_entry_unref(entry);
return entry;
}
int main(int argc, char **argv)
{
ExifEntry *entry;
//Input JPG
char mInputFilename[]="example.jpg";
//Load JPG
JPEGData * mJpegData = jpeg_data_new_from_file(mInputFilename);
//Load Exif data from JPG
ExifData * mExifData = jpeg_data_get_exif_data(mJpegData);
//Set some Exif options
exif_data_set_option(mExifData, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
exif_data_set_data_type(mExifData, EXIF_DATA_TYPE_COMPRESSED);
exif_data_set_byte_order(mExifData, FILE_BYTE_ORDER);
entry = create_tag(mExifData, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT,
sizeof(ASCII_COMMENT) + sizeof(FILE_COMMENT) - 2);
/* Write the special header needed for a comment tag */
memcpy(entry->data, ASCII_COMMENT, sizeof(ASCII_COMMENT)-1);
/* Write the actual comment text, without the trailing NUL character */
memcpy(entry->data+8, FILE_COMMENT, sizeof(FILE_COMMENT)-1);
/* create_tag() happens to set the format and components correctly for
* EXIF_TAG_USER_COMMENT, so there is nothing more to do. */
/* Create a EXIF_TAG_SUBJECT_AREA tag */
entry = create_tag(mExifData, EXIF_IFD_EXIF, EXIF_TAG_SUBJECT_AREA,
4 * exif_format_get_size(EXIF_FORMAT_SHORT));
entry->format = EXIF_FORMAT_SHORT;
entry->components = 4;
//Write back exif data
jpeg_data_set_exif_data(mJpegData,mExifData);
//Save to JPG
jpeg_data_save_file(mJpegData,"test.jpg");
return 0;
}