After applying an ITK filter pipeline, how do I write back the result to a buffer to be used (outside ITK)?
The Insight Software Guide has an example Book 1: Chapter 4.1.7: "Importing Image Data from a Buffer", and the same example is also found in the WikiExamples.
It shows how one can wrap a ITK pointer around a C++ array to use it further by using the ImportImageFilter object.
However, this example then uses a Writer object to write the filtered result to a file.
How do I write the filtered result into another C++ array instead? Or how do I overwrite the array I've used as input?
In essence, I've an application which contains an image in a buffer (localBuffer) which I can wrap following the example code:
[...]
const bool filterOwnsBuffer= false;
importFilter->SetImportPointer( localBuffer, size[0]*size[1], filterOwnsBuffer );
I can then use it it in any itk pipeline and 'update' it at a certain stage:
[...]
FilterType::Pointer filter = FilterType::New();
filter->SetInput( importFilter->GetOutput() );
filter->Update();
How do I now ensure that localbuffer has the filtered values? Or, alternatively, how do I set a different resultbuffer to the output values? Do I have to use the image iterator and 'loop' over my buffer manually? Or can I use the filter->GetOutput() more directly?
A little code example or a link to an according example would be very much appreciated.
(Simply the "Exporting Image Data to a Buffer" equivalent to the given import example.)
ImageType::Pointer output = filter->GetOutput();
ImageType::PixelContainer * outputContainer = output->GetPixelContainer();
ImageType::PixelContainer::Element * resultBuffer = outputContainer->GetBufferPointer();
See the Image documentation and ImportImageContainer documentation.
Here is the remedy for me:
memcpy( buffer, filter->GetOutput()->GetBufferPointer(),
size[0]*size[1]*sizeof(InputPixelType));
This works because by the time the filter is destroyed the buffer was already parsed to "buffer", which is the pointer to your data.
Related
I have generated a GeoTiff dataset in-memory using GDALTranslate() with a /vsimem/ filepath. I need access to the buffer for the actual GeoTiff file to put it in a stream for an external API. My understanding is that this should be possible with VSIGetMemFileBuffer(), however I can't seem to get this to return anything other than nullptr.
My code is essentially as follows:
//^^ GDALDataset* srcDataset created somewhere up here ^^
//psOptions struct has "-b 4" and "-of GTiff" settings.
const char* filep = "/vsimem/foo.tif";
GDALDataset* gtiffData = GDALTranslate(filep, srcDataset, psOptions, nullptr);
vsi_l_offset size = 0;
GByte* buf = VSIGetMemFileBuffer(filep, &size, true); //<-- returns nullptr
gtiffData seems to be a real dataset on inspection, it has all the appropriate properties (number of bands, raster size, etc). When I provide a real filesystem location to GDALTranslate() rather than the /vsimem/ path and load it up in QGIS it renders correctly too.
Looking a the source for VSIGetMemFileBuffer(), this should really only be returning nullptr if the file can't be found. This suggests i'm using it incorrectly. Does anyone know what the correct usage is?
Bonus points: Is there a better way to do this (stream the file out)?
Thanks!
I don't know anything about the C++ API. But in Python, the snippet below is what I sometimes use to get the contents of an in-mem file. In my case mainly VRT's but it shouldn't be any different for other formats.
But as said, I don't know if the VSI-api translate 1-on-1 to C++.
from osgeo import gdal
filep = "/vsimem/foo.tif"
# get the file size
stat = gdal.VSIStatL(filep, gdal.VSI_STAT_SIZE_FLAG)
# open file
vsifile = gdal.VSIFOpenL(filep, 'r')
# read entire contents
vsimem_content = gdal.VSIFReadL(1, stat.size, vsifile)
In the case of a VRT the content would be text, shown with something like print(vsimem_content.decode()). For a tiff it would of course be binary data.
I came back to this after putting in a workaround, and upon swapping things back over it seems to work fine. #mmomtchev suggested looking at the CPL_DEBUG output, which showed nothing unusual (and was silent during the actual VSIGetMemFileBuffer call).
In particular, for other reasons I had to put a GDALWarp call in between calling GDALTranslate and accessing the buffer, and it seems that this is what makes the difference. My guess is that GDALWarp is calling VSIFOpenL internally - although I can't find this in the source - and this does some kind of initialisation for VSIGetMemFileBuffer. Something to try for anyone else who encounters this.
I want to transfer image data on websocket by using boost library.
How should I resolve below error?
At first, I confirmed to be able to transfer and receive text data by referring following URL.
https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/quick_start.html
And next, although I tried to transfer image, I got following error message.
websocket_client.cpp:563:38: error: no matching function for call to 'buffer(cv::Mat&)'
ws.write(boost::asio::buffer(img));
What I did are below.
read image file as 'img' by using opencv.
Change the code for transfer data
// Send the message
// ws.write(boost::asio::buffer(std::string(text)));
ws.write(boost::asio::buffer(img));
cv::Mat is not a buffer type or adaptable as such. If you have POD data, then you can "cast" it like the commenter says:
// don't do this:
buffer(&img, sizeof(img));
However, that's not safe:
static_assert(std::is_standard_layout_v<cv::Mat>);
static_assert(std::is_trivial_v<cv::Mat>);
The type is actually not bitwise copyable. But since there's a matrix, there is likely a contiguous region of data that is:
ws.write(net::buffer(img.data, img.total() * img.elemSize()));
This uses total() and elemSize(), links to the documentation.
Now, this will be enough if the receiving end already knows the dimensions. If not, send them first, e.g.:
uint32_t dimensions[] { htonl(image_witdh), htonl(image_height) };
std::vector<net::const_buffer> buffers {
net::buffer(dimensions),
net::buffer(img.data, img.total() * img.elemSize())
};
ws.write(buffers);
I am given image data and color table I am trying to export it as a single frame GIF using giflib. I looked into the API, but can't get it to work. The program crashes even at the first function:
GifFileType image_out;
int errorCode = 0;
char* fileName = "SomeName.gif";
image_out = *EGifOpenFileName(fileName,true, &errorCode);
It is my understanding that I first need to open a file by specifying it's name and then update it with fileHandle. Then Fill in the screen description, the extension block the image data and add the 3B ending to the file. Then use EGifSpew to export the whole gif. The problem is that I can't even use EGifOpenFileName(); The program crashes at that line.
Can someone help me the API of giflib? This problem is getting really frustrating.
Thanks.
EDIT:
For the purposes of simple encoding I do not want to specify a color table and I just want to encode a single frame GIF.
The prototype is:
GifFileType *EGifOpenFileName(char *GifFileName, bool GifTestExistance, int *ErrorCode)
You should write as
GifFileType* image_out = EGifOpenFileName(fileName,true, &errorCode);
Note GifFileType is not POD type so you should NOT copy like that.
I am writing a c++ library that fetches and returns either image data or video data from a cloud server using libcurl. I've started writing some test code but still stuck at designing API because I'm not sure about what's best way to handle these media files. Storing it in a char/string variable as binary data seems to work, but I wonder if that would take up too much RAM memory if the files are too big. I'm new to this, so please suggest a solution.
You can use something like zlib to compress it in memory, and then uncompress it only when it needs to be used; however, most modern computers have quite a lot of memory, so you can handle quite a lot of images before you need to start compressing. With videos, which are effectively a LOT of images, it becomes a bit more important -- you tend to decompress as you go, and possibly even stream-from-disk as you go.
The usual way to handle this, from an API point of view, is to have something like an Image object and a Video object (classes). These objects would have functions to "get" the uncompressed image/frame. The "get" function would check to see if the data is currently compressed; if it is, it would decompress it before returning it; if it's not compressed, it can return it immediately. The way the data is actually stored (compressed/uncompressed/on disk/in memory) and the details of how to work with it are thus hidden behind the "get" function. Most importantly, this model lets you change your mind later, adding additional types of compression, adding disk-streaming support, etc., without changing how the code that calls the get() function is written.
The other challenge is how you return an Image or Video object from a function. You can do it like this:
Image getImageFromURL( const std::string &url );
But this has the interesting problem that the image is "copied" during the return process (sometimes; depends how the compiler optimizes things). This way is more memory efficient:
void getImageFromURL( const std::string &url, Image &result );
This way, you pass in the image object into which you want your image loaded. No copies are made. You can also change the 'void' return value into some kind of error/status code, if you aren't using exceptions.
If you're worried about what to do, code for both returning the data in an array and for writing the data in a file ... and pass the responsability to choose to the caller. Make your function something like
/* one of dst and outfile should be NULL */
/* if dst is not NULL, dstlen specifies the size of the array */
/* if outfile is not NULL, data is written to that file */
/* the return value indicates success (0) or reason for failure */
int getdata(unsigned char *dst, size_t dstlen,
const char *outfile,
const char *resource);
I have some wxImages and I would like to store them into a BLOB (Binary Large OBject) field in a MySQL database.
There are no methods in wxImage nor wxBitmap for obtaining the binary data as an array of unsigned char so I can load into the database.
My current workaround is to write the image to a temporary file, then load the BLOB field directly from the file.
Is there a more efficient method to load and store a wxImage object into a MySQL BLOB field?
I am using MySql C++ connector 1.05, MS Visual Studio 2008, wxWidgets and C++.
wxWidgets doesn't provide any API to the data from wxBitmap (because it's platform-dependent) but wxImage uses a well-defined (and very simple) format which you can access using its GetData() method as mentioned above. Just notice that you may need to use GetAlpha() as well if your images have alpha channel.
However this is not how I'd do it because the data will be huge if you do it like this. While compressing it, as also suggested above, is possible, why bother doing it manually when wxImage already supports writing image in any of the standard image formats. Just create a wxMemoryOutputStream and pass it to SaveFile(). Then simply access the stream buffer directly using GetOutputStreamBuffer()->GetBufferStart() and related functions.
Unless I'm missing something, couldn't you use WxImage::GetData (http://docs.wxwidgets.org/2.8/wx_wximage.html#wximagegetdata) to get the data and then ::GetHeight and ::GetWidth to know the length of the data that pointer points to? The unsigned char * that is returned by WxImage::GetData looks like it should point to the RGB data that makes up the image.