1

I receive images on the PC from two cameras. The stream is not continuous but takes place at event detection. Therefore, I have to receive around 8-10 image pairs after a particular time. Since I have to process the images, I want to first keep all the images in a large buffer and later process them in a batch. It is also acceptable to keep images in two large buffers (one for each camera). How do I keep these pair of images in one (or two) large buffer(s)? I am implementing this program in C.

user846400
  • 1,061
  • 1
  • 17
  • 25
  • 2
    If you are implementing the program in C, why did you tag your question C++? – Robᵩ May 01 '12 at 14:25
  • 1
    Not enough information. Which OS? Which image library are you using. Memory constraints? – Neil May 01 '12 at 14:29
  • I am working on UBUNTU. I am using only C functions to receive images via UDP and saving them (fwrite, i have still not integrated any image processing). BTW, I have enough memory to hold the images until they are processed/saved. – user846400 May 01 '12 at 14:31

2 Answers2

2

Assumeing the following API to get the image:

int ImageGet(
  char * pBuffer, 
  size_t * pSize); /* returns 0 on success or any other value if no image is available or on error */

you could do the following:

#include <stdlib.h>
#include <string.h>

...

#define IMAGESIZE_MAX (1024*1024) 

char * pBuffer = NULL;
char * pBufferCurrent = pBuffer;
int iResult = 0;
size_t size = IMAGESIZE_MAX;
size_t sizeTotal = 0;

do 
{
  char * pBufferCurrent = realloc (
    pBuffer, 
    sizeTotal + sizeof(size) + size);

  if (!pBufferCurrent)
  {
    break;
  }

  pBuffer = pBufferCurrent;

  pBufferCurrent += sizeTotal;

  if ((iResult = ImageGet (
    pBufferCurrent + sizeof(size), 
    &size))
  {
    break; 
  }

  memcpy (
    pBufferCurrent,
    &size, 
    sizeof(size));

  sizeTotal += (sizeof(size) + size);
} while (1);

...

This stores your data sequentially:

[     size 1     ][  image data 1  ][     size 2     ][  image data 2  ]...
<-sizeof(size_t)-><-    size 1    -><-sizeof(size_t)-><-    size 2    ->

in the buffer pointed to by pBuffer.


To retrieve a reference to the data describing image N from the buffer pBuffer you could use the following method:

const char * BufferImageGetByIndex(
    const char * pBuffer,
    unsigned indexImage)
{
  for (unsigned indexImageCnt = 0;
    indexImageCnt < indexImage;
    ++ indexImageCnt)
  {
    pBuffer += sizeof(size_t) + *((size_t *) pBuffer);
  }

  return pBuffer;
}

Then to actually get an image you could do like so:

...
/* Get a reference to the data decribing **fourth** image in the buffer filled by the example above. */
const char * pBufferImage4 = *BufferImageGetByIndex(pBuffer, 3);

/* Get the size ... */
size_t sizeImage4 = *((size_t *) pBufferImage4);
/* ... and a reference to the image data. */
const char * pImage4 = pBufferImage4 + sizeof(size_t);
...
alk
  • 69,737
  • 10
  • 105
  • 255
  • One minor nitpick: Instead of defining IMAGESIZE_MAX to be a multiplication that needs to be evaluated at each check against the max, just make it the answer (1084576). Yeah it will be compiled as a simple 10-bit left shift, but there's no need to waste instructions willy-nilly. – pg1989 May 01 '12 at 15:59
  • I thought I might leave this as an exercise to the OP ... ;-) - no, to be honest I simply couldn't remember the result and I was too lazy start a calculator and even more to lazy too use my brain ... and I felt 1024 bytes might be unrealistic small for an image buffer these days @pg1989 – alk May 01 '12 at 16:04
  • No worries, I know the feeling all too well. – pg1989 May 01 '12 at 16:06
  • Btw: `IMAGESIZE_MAX` is only used **once**! :-) @pg1989 – alk May 01 '12 at 16:12
  • Thanks for such a detailed answer. What I understand from your code is that if char *pBuffer is the pointer to a single image and size_t *pSize is its size, then every image will be stored sequentially separated by a length of 16 bytes (length of size_t). So When I read the images back from memory, I should point the pointer *pBuffer to the first image and increment it by *pBuffer+sizeof(size)+pBuffer. Please correct me if I am wrong. Thanks for your help. – user846400 May 01 '12 at 17:37
  • To get the zeroth image read in `size_t size` from `*pBuffer`, increment `pBuffer` by `sizeof(size_t)` and then read `size` bytes of raw image data from `*pBuffer`; to get the next image increment `pBuffer` by the previously read `size` and start over (see my edited answer). Btw: `sizeof(size_t)` is expected to be 8 bytes on a recent version of Linux. @user846400 – alk May 01 '12 at 18:27
  • 1
    Any compiler worth it's salt will see no difference between (1024*1024) and (1048576). It will recognize that (1024*1024) is invariant and optimize it accordingly. It will not waste instructions calculating it **ever**. (By the way, 1084576 != (1024*1024) ) – Robert Crovella Aug 02 '13 at 02:18
0

Assuming your images are all of a standard size and format, you can simply malloc() a buffer which will hold all the images at event detection time. If you're looking to do any analytics on the images, I would recommend switching to C++ and using the OpenCV libraries. They are pretty much without parallel in open-source image libs.

pg1989
  • 1,010
  • 6
  • 13
  • i use a single buffer (unsigned char* buffer) to receive a single image via UDP. The question is how do I use a buffer that can store multiple images? – user846400 May 01 '12 at 14:34
  • Make it a bigger single buffer? I'm really confused as to what you're actually asking. Are you wondering what the best way to store the data in the buffer is? – pg1989 May 01 '12 at 15:54