Get Cimg image buffer [duplicate] - c++

I'm trying to convert a Cimg image to itk image to use it for registration algorithm. The Cimg is a RGB image and i want to convert it to RGB itk image. Her is my code :
void Cimg_To_ITK (CImg<uchar> img)
{
const unsigned int Dimension = 2;
typedef itk::RGBPixel< unsigned char > RGBPixelType;
typedef itk::Image< RGBPixelType, Dimension > RGBImageType;
typedef itk::ImportImageFilter< RGBPixelType, Dimension > ImportFilterType;
ImportFilterType::Pointer importFilter = ImportFilterType::New();
typedef itk::ImageFileWriter< RGBImageType > WriterType;
WriterType::Pointer writer = WriterType::New();
RGBImageType::SizeType imsize;
imsize[0] = img.width();
imsize[1] = img.height();
ImportFilterType::IndexType start;
start.Fill( 0 );
ImportFilterType::RegionType region;
region.SetIndex( start );
region.SetSize( imsize );
importFilter->SetRegion( region );
const itk::SpacePrecisionType origin[ Dimension ] = { 0.0, 0.0 };
importFilter->SetOrigin( origin );
const itk::SpacePrecisionType spacing[ Dimension ] = { 1.0, 1.0 };
importFilter->SetSpacing( spacing );
const unsigned int numberOfPixels = imsize[0] * imsize[1];
const bool importImageFilterWillOwnTheBuffer = true;
RGBPixelType * localBuffer = new RGBPixelType[ numberOfPixels ];
RGBPixelType * it = localBuffer;
memcpy(*it, img.data(), numberOfPixels);
importFilter->SetImportPointer( localBuffer, numberOfPixels,importImageFilterWillOwnTheBuffer );
writer->SetFileName( "output.png" );
}
I get this error at compilation :
error: cannot convert 'RGBPixelType {aka itk::RGBPixel}' to 'void*' for argument '1' to 'void* memcpy(void*, const void*, size_t)
What is wrong??

*it is a RGBPixelType, it can't be converted to a void pointer and memcpy() can't handle it. memcpy() needs pointers to values, such as img.data() or it. According to the documentation of CImg :
T* data () Return a pointer to the first pixel value.
An example of how to import an image from a buffer of values is provided by ITK here . My guess is that it is your starting point.
The other issue that you will soon face is the size of the image : RBG is 3 bytes per pixel, so it should be
memcpy(it, img.data(), numberOfPixels*3);
Here is an example of how to import a buffer of unsigned char as an ITK RGB Image, starting from your code. Feel free to edit this answer and add the function to handle a CImg !
#include <iostream>
#include <itkImage.h>
using namespace itk;
using namespace std;
#include <itkImportImageFilter.h>
#include <itkImageFileWriter.h>
void Cimg_To_ITK (unsigned char* data)
{
const unsigned int Dimension = 2;
typedef itk::RGBPixel< unsigned char > RGBPixelType;
typedef itk::Image< RGBPixelType, Dimension > RGBImageType;
typedef itk::ImportImageFilter< RGBPixelType, Dimension > ImportFilterType;
ImportFilterType::Pointer importFilter = ImportFilterType::New();
typedef itk::ImageFileWriter< RGBImageType > WriterType;
WriterType::Pointer writer = WriterType::New();
RGBImageType::SizeType imsize;
// imsize[0] = img.width();
// imsize[1] = img.height();
imsize[0] = 100;
imsize[1] = 200;
ImportFilterType::IndexType start;
start.Fill( 0 );
ImportFilterType::RegionType region;
region.SetIndex( start );
region.SetSize( imsize );
importFilter->SetRegion( region );
const itk::SpacePrecisionType origin[ Dimension ] = { 0.0, 0.0 };
importFilter->SetOrigin( origin );
const itk::SpacePrecisionType spacing[ Dimension ] = { 1.0, 1.0 };
importFilter->SetSpacing( spacing );
const unsigned int numberOfPixels = imsize[0] * imsize[1];
const bool importImageFilterWillOwnTheBuffer = true;
RGBPixelType * localBuffer = new RGBPixelType[ numberOfPixels ];
RGBPixelType * it = localBuffer;
memcpy(it, data, numberOfPixels*3);
// no need to delete localBuffer : itk will care since importImageFilterWillOwnTheBuffer=true
importFilter->SetImportPointer( localBuffer, numberOfPixels,importImageFilterWillOwnTheBuffer );
writer->SetFileName( "output.png" );
writer->SetInput(importFilter->GetOutput() );
writer->Update();
}
int main()
{
unsigned char* data=new unsigned char[100*200*3];
for(int i=0;i<200;i++){
for(int j=0;j<100;j++){
data[(i*100+j)*3]=i;
data[(i*100+j)*3+1]=0;
data[(i*100+j)*3+2]=j;
}
}
Cimg_To_ITK (data);
delete[] data;
cout<<"running fine"<<endl;
return 0;
}
The file CMakeLists.txt :
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(ItkTest)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
add_executable(MyTest main.cpp)
target_link_libraries(MyTest ${ITK_LIBRARIES})
After installing ITK and setting the environment variable ITK_DIR, type cmake . and make to build this example.

Related

Not able to create multilayered tiff image using FreeImage

Been trying for 2 days now without any luck. My goal is to take 2 arrays of data that we normally create 2 exr files from, and create a multilayered/multipage TIFF file (FreeImage only support multipage for tif, gif and ico, and we need this to work well in python too).
static unsigned DLL_CALLCONV
myReadProc(void *buffer, unsigned size, unsigned count, freeimage::fi_handle handle) {
return (unsigned)fread(buffer, size, count, (FILE *)handle);
}
static unsigned DLL_CALLCONV
myWriteProc(void *buffer, unsigned size, unsigned count, freeimage::fi_handle handle) {
return (unsigned)fwrite(buffer, size, count, (FILE *)handle);
}
static int DLL_CALLCONV
mySeekProc(freeimage::fi_handle handle, long offset, int origin) {
return fseek((FILE *)handle, offset, origin);
}
static long DLL_CALLCONV
myTellProc(freeimage::fi_handle handle) {
return ftell((FILE *)handle);
}
void MyClass::TestMultilayeredFile(math::float4 *data1, math::float4 *data2, Hash128 &hash, const int width, const int height)
{
freeimage::FreeImageIO io;
io.read_proc = myReadProc;
io.write_proc = myWriteProc;
io.seek_proc = mySeekProc;
io.tell_proc = myTellProc;
core::string cachePathAsset = GetAbsoluteHashFilePath(GetRelativeHashFilePath(hash, "_combined.tiff"));
const int pixelCount = width * height;
enum Layers
{
kData1 = 0,
kData2 = 1,
kLayerCount = 2
};
FILE *file = fopen(cachePathAsset.c_str(), "w+b");
if (file != NULL) {
freeimage::FIMULTIBITMAP *out = freeimage::FreeImage_OpenMultiBitmapFromHandle(freeimage::FREE_IMAGE_FORMAT::FIF_TIFF, &io, (freeimage::fi_handle)file, 0x0800);
if (out)
{
const math::float4* kLayers[2] = { data1, data2 };
for (int layer = 0; layer < kLayerCount; ++layer)
{
freeimage::FIBITMAP* bitmap = freeimage::FreeImage_AllocateT(freeimage::FIT_RGBAF, width, height);
const int pitch = freeimage::FreeImage_GetPitch(bitmap);
void* bytes = (freeimage::BYTE*)freeimage::FreeImage_GetBits(bitmap);
const int bytesPerPixel = freeimage::FreeImage_GetBPP(bitmap) / 8;
DebugAssert(pitch == width * bytesPerPixel);
DebugAssert(bytes);
DebugAssert(bytesPerPixel == 16);
memcpy(bytes, kLayers[layer], pixelCount * bytesPerPixel);
freeimage::FreeImage_AppendPage(out, bitmap);
freeimage::FreeImage_Unload(bitmap);
}
// Save the multi-page file to the stream
BOOL bSuccess = freeimage::FreeImage_SaveMultiBitmapToHandle(freeimage::FREE_IMAGE_FORMAT::FIF_TIFF, out, &io, (freeimage::fi_handle)file, 0x0800);
freeimage::FreeImage_CloseMultiBitmap(out, 0);
}
}
}
The tiff file is created, but only contains 1kb. Also, bSuccess returns false. The code to generate the individual images have worked in the past, but haven't done mulipage before.

ITK: CannyEdgeDetectionFilter issues

I'm trying to use the CannyEdgeDetectionImageFilter but the GetPixel() method doesn't seem to be properly referencing the filtered image. I've tried a lot of different tactics to attempt to resolve the issue, but the only thing that seems to work is writing and reading the image to/from the disk (which is not ideal). My code is below:
typedef itk::Image<unsigned char, 2> ImageType;
typedef itk::Image<float, 2> floatImageType;
...
floatImageType::Pointer to_float(ImageType::Pointer image){
typedef itk::CastImageFilter <ImageType, floatImageType> CastFilterType;
CastFilterType::Pointer castToFloat = CastFilterType::New();
castToFloat->SetInput( image );
castToFloat->Update();
return castToFloat->GetOutput();
}
...
ImageType::Pointer check(ImageType::Pointer image){
typedef itk::ImageDuplicator <ImageType> ImageDuplicatorType;
typedef itk::RescaleIntensityImageFilter
<floatImageType, ImageType> RescaleFilter;
typedef itk::CannyEdgeDetectionImageFilter
<floatImageType, floatImageType> CannyFilter;
RescaleFilter::Pointer Rescale = RescaleFilter::New();
CannyFilter::Pointer Canny = CannyFilter::New();
ImageDuplicatorType::Pointer Duplicator = ImageDuplicatorType::New();
ImageType::Pointer cannyImage;
Canny->SetVariance( 20 );
Canny->SetUpperThreshold( 2 );
Canny->SetLowerThreshold( 20 );
Rescale->SetOutputMinimum( 0 );
Rescale->SetOutputMaximum( 255 );
Duplicator->SetInputImage(image);
Duplicator->Update();
ImageType::Pointer img_copy = Duplicator->GetOutput();
floatImageType::Pointer floatImage = to_float(img_copy);
Canny->SetInput(floatImage);
Rescale->SetInput( Canny->GetOutput() );
Rescale->Update();
cannyImage = Rescale->GetOutput();
/* Insert odd work-around here */
const ImageType::SizeType img_size = cannyImage->GetLargestPossibleRegion().GetSize();
itk::Index<2> loc = {{img_size[0]/2, 0}};
int top_edge = 0;
bool contin = true;
for (int i = 0; ((i < img_size[1]) && contin); i++){
loc[1] = i;
if (cannyImage->GetPixel(loc) != 0){
top_edge = i;
contin = false;
}
}
...
}
When a pixel value of cannyImage later on, the value should be either 0, or (if an edge) 255. However, it produces values that appear to belong to a gray-scale image.
However, if I include the following code in he section above, it works as one should expect:
std::string fname = "/tmp/canny_" + to_string(getpid()) + ".tmp";
writeImage(cannyImage, fname);
cannyImage = readImage(fname);
(Methods writeImage(ImageType::Pointer image, std::string filename) and ImageType::Pointer readImage(std::string filename) were defined earlier the program.)
Anyone know what's going wrong with my program? Why does pushing it through the disk IO cause it to work?

How to resize an image from an rgb buffer using c++

I have an (char*)RGB buffer that has the data of actual image. Let's say that the actual image resolution is 720x576. Now I want to resize it to a resolution , say 120x90.
How can I do this using https://code.google.com/p/jpeg-compressor/ or libjpeg ?
Note: can use any other library, but should work in linux.
Edited: Video decoder decodes a frame in YUV, which I convert it into RGB. All these happen in a buffer.
I need to resize the RGB buffer to make a thumbnail out of it with variable size.
Thanks for the help in advance
I did the following to achieve my goal:
#define TN_WIDTH 240
#define TN_HEIGHT 180
#include "jpegcompressor/jpge.h"
#include "jpegcompressor/jpgd.h"
#include <ippi.h>
bool createThumnailJpeg(const uint8* pSrc, int srcwidth, int srcheight)
{
int req_comps = 3;
jpge::params params;
params.m_quality = 50;
params.m_subsampling = jpge::H2V2;
params.m_two_pass_flag = false;
FILE *fpJPEGTN = fopen("Resource\\jpegcompressor.jpeg","wb");
int dstWidth = TN_WIDTH;
int dstHeight = TN_HEIGHT;
int uiDstBufferSize = dstWidth * dstHeight * 3;
uint8 *pDstRGBBuffer = new uint8[uiDstBufferSize];
uint8 *pJPEGTNBuffer = new uint8[uiDstBufferSize];
int uiSrcBufferSize = srcwidth * srcheight * 3;
IppiSize srcSize = {srcwidth , srcheight};
IppiRect srcROI = {0, 0, srcwidth, srcheight};
IppiSize dstROISize = {dstWidth, dstHeight};
double xfactor = (double) dstWidth / srcwidth;
double yfactor = (double) dstHeight / srcheight;
IppStatus status = ippiResize_8u_C3R(pSrc, srcSize, srcwidth*3, srcROI,
pDstRGBBuffer, dstWidth*3, dstROISize, xfactor, yfactor, 1);
if (!jpge::compress_image_to_jpeg_file_in_memory(pJPEGTNBuffer, uiDstBufferSize, dstWidth, dstHeight, req_comps, pDstRGBBuffer, params))
{
cout << "failed!";
delete[] pDstRGBBuffer;
delete [] pJPEGTNBuffer;
return false;
}
if (fpJPEGTN)
{
fwrite(pJPEGTNBuffer, uiDstBufferSize, 1, fpJPEGTN);
fclose(fpJPEGTN);
}
delete [] pDstRGBBuffer;
delete [] pJPEGTNBuffer;
return true;
}

ITK Importing Image Data from a Buffer

I have coded a method to create an Itk image from a buffer (in my case it's a Cimg image type). This is the algorithme :
void Cimg_To_ITK (CImg<uchar> img)
{
const unsigned int Dimension = 2;
typedef itk::RGBPixel< unsigned char > RGBPixelType;
typedef itk::Image< RGBPixelType, Dimension > RGBImageType;
typedef itk::ImportImageFilter< RGBPixelType, Dimension > ImportFilterType;
ImportFilterType::Pointer importFilter = ImportFilterType::New();
typedef itk::ImageFileWriter< RGBImageType > WriterType;
WriterType::Pointer writer = WriterType::New();
RGBImageType::SizeType imsize;
imsize[0] = img.width();
imsize[1] = img.height();
ImportFilterType::IndexType start;
start.Fill( 0 );
ImportFilterType::RegionType region;
region.SetIndex( start );
region.SetSize( imsize );
importFilter->SetRegion( region );
const itk::SpacePrecisionType origin[ Dimension ] = { 0.0, 0.0 };
importFilter->SetOrigin( origin );
const itk::SpacePrecisionType spacing[ Dimension ] = { 1.0, 1.0 };
importFilter->SetSpacing( spacing );
const unsigned int numberOfPixels = imsize[0] * imsize[1];
const bool importImageFilterWillOwnTheBuffer = true;
RGBPixelType * localBuffer = new RGBPixelType[ numberOfPixels ];
memcpy(localBuffer->GetDataPointer(), img.data(), numberOfPixels);
importFilter->SetImportPointer( localBuffer, numberOfPixels,importImageFilterWillOwnTheBuffer );
writer->SetInput( importFilter->GetOutput() );
writer->SetFileName( "output.png" );
writer->Update();
}
I dont have what i want as a output :
input :
output :
CImg stores different RGB Pixels as separate componentes
You must prepare an RGBPixel buffer and iterate over the image and save to the buffer:
RGBPixelType *buffer=new RGBPixelType[img.width()*img.height()];
cimg_for(img,x,y)
{
// Now allign three colors
buffer[x+y*img.width()]= RGBPixelType({img(x,y,0,0),img(x,y,0,1),img(x,y,0,2)});
}
importImageFilterWillOwnTheBuffer=true; // To avoid leaks
Might be also good idea to check how the Cimg stores the pixels for image and if it differs from the RGBPixelType. I suspect that the RGBPixelType array has pixels stored in rgbrgbrgbrgb while the other may have them in some rrrrggggbbbb style format. Or, as already hinted, if the input is a gray-scale image with single channel you have to replicate the value for each rgb value (or if both are rgb you have to copy data from all the three channels)...
This is probably because you just copy one byte per pixel. Each RGBPixelType is likely several bytes in size:
memcpy(localBuffer->GetDataPointer(), img.data(), numberOfPixels * sizeof(RGBPixelType));

reading TGA files in OpenGl to create a 3d ouse

I have a TGA file and a library that allready has everything that I need to read TGA and use them.
This class has a method called pixels(), that returns a pointer that is pointed to the memory area where pixel are stored as RGBRGBRGB...
My question is, how can I take the pixel value?
Cause if I make something like this:
img.load("foo.tga");
printf ("%i", img.pixels());
It gives back to me what is proprably the address.
I've found this code on this site:
struct Pixel2d
{
static const int SIZE = 50;
unsigned char& operator()( int nCol, int nRow, int RGB)
{
return pixels[ ( nCol* SIZE + nRow) * 3 + RGB];
}
unsigned char pixels[SIZE * SIZE * 3 ];
};
int main()
{
Pixel2d p2darray;
glReadPixels(50,50, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &p.pixels);
for( int i = 0; i < Pixel2d::SIZE ; ++i )
{
for( int j = 0; j < Pixel2d::SIZE ; ++j )
{
unsigned char rpixel = p2darray(i , j , 0);
unsigned char gpixel = p2darray(i , j , 1);
unsigned char bpixel = p2darray(i , j , 2);
}
}
}
I think that It can work great for me, but how can I tell the program to read from my img?
Tga supports different pixel depths. And we don't know what library you're using. But generally speaking pixels() should return a pointer to a buffer containing pixels. Say for sake of argument it unpacks the pixels into 8-bit per channel subpixels, then each pixel is represented by 3 bytes.
So to access a pixel at a given offset in the buffer:
const u8* pixelBuffer = img.pixels():
u8 red = pixelBuffer[(offset*3)+0];
u8 green = pixelBuffer[(offset*3)+1];
u8 blue = pixelBuffer[(offset*3)+2];
If you know the width of the image buffer then you can get a pixel by its x and y coordinates:
u8 red = pixelBuffer[((x+(y*width))*3)+0];