Loading ofImage from URL using Poco

Hi,

In that thread about integrating Poco http://www.openframeworks.cc/forum/view-…-8&start=15 , Theo posted this code which shows how to download an image with Poco and load it into ofImage:

  
  
   //some poco stuff  
   HTTPStreamFactory::registerFactory();  
        
   //specify out url and open stream  
   URI uri("[http://www.coolhunting.com/images/funky2.jpg");](http://www.coolhunting.com/images/funky2.jpg");)        
   std::auto_ptr<std::istream> pStr(URIStreamOpener::defaultOpener().open(uri));  
        
   //create a file to save the stream to  
   ofstream myfile;        
   myfile.open(ofToDataPath("thumb.jpg").c_str());  
        
   //copy stream to file  
   StreamCopier::copyStream(*pStr.get(), myfile);  
   myfile.close();  
        
   //load into an ofImage!  
   img.loadImage(ofToDataPath("thumb.jpg"));  
  

I am looking for a way to do essentially this, but without saving the image as a file to the filesystem. I saw the FreeImage_LoadFromHandle function in the FreeImage documentation, but I’m still unclear on how to use it. Zach mentioned that he had some code he could share. That would be great. My end goal would be to have something like:

  
  
void ofImage::loadImageFromUrl(string url)  
  

Thanks,
Brian

Hey!

Looks like the poco copyToString is the way to go.

  
	string str;		  
		StreamCopier::copyToString(*pStr.get(), str);  
		int bytesToRead = str.size();  
		  
		char buff[bytesToRead];  
		memset(buff, 0, bytesToRead);  
		  
		for(int i = 0; i < bytesToRead; i++){  
			buff[i] = str[i];  
		}  
		  
		printf("numBytes copied is %i   
", sizeof(buff));  

Then once you have it as char * array you can use the freeimage loadFromMemory functions - which I think would be better than loadFromHandle. I think Freeimage can also determine the filetype from memory too with FreeImage_GetFileTypeFromMemory. There is more info in the freeimage docs: http://surfnet.dl.sourceforge.net/sourc-…-ge3100.pdf

The best thing to do would be to make a new class that extends the ofImage class - that way you don’t have to hack your ofImage code but you can still use the ofImage members and methods.

companje - did this to extend the ofxXmlSettings class.
http://forum.openframeworks.cc/t/ofxxmlrecursivelookup/566/1

Hope that helps!
Theo

this is pretty basic, but it’s a class that extends ofImage and loads from RAM. a more thorough example is here:

http://www.koders.com/cpp/fid27675200C3-…-37522.aspx

**note: this code was written against OF 0.04, likely you’ll need to change IMG->bmp to just bmp
**

haven’t thoroughly tested this, but I put it up here because it’s a start (also, it’s extending the base class, something we support as opposed to altering ofImage)

hope that helps!!
zach

  
  
  
#ifndef _OF_MEM_IMAGE_H_  
#define _OF_MEM_IMAGE_H_  
  
#include "ofImage.h"  
  
  
class 	ofMemoryImage : public ofImage {  
  
	public :  
		  
		void loadFromData(unsigned char * datasource, int len);  
		  
};   
  
  
  
#endif  
  
  

  
  
  
#include "ofMemoryImage.h"  
#include "FreeImage.h"  
  
  
  
  
void ofMemoryImage::loadFromData(unsigned char * datasource, int len){  
  
	if(IMG->isValid()) {  
		FreeImage_Unload(IMG->bmp);			  
	}  
	  
	FIMEMORY *hmem = NULL;  
	hmem = FreeImage_OpenMemory(datasource, len);  
	if (hmem == NULL)  
           printf("hmem == null \n");  
             
  
	FREE_IMAGE_FORMAT fif = FIF_JPEG;  
	  
	IMG->bmp = FreeImage_LoadFromMemory(fif, hmem, 0);  
	  
	if (IMG->bmp == NULL){  
		printf("bmp == null.... \n");  
	}  
	  
  
	//if (!ofbOriginBottomLeft()){     /// bottom is now lower left !   
		FreeImage_FlipVertical(IMG->bmp);  
	//}  
	update();  
	  
	  
}	  
  
  
  

Wanted to see if it worked and it does.

This is basically the code I posted above plus zach’s load from memory code.

To use just put the webImageLoader.h and .cpp in your src/ folder.
You can treat it just like an ofImage object but with the extra loadFromUrl function

webImageLoader.h

  
#pragma once  
  
#include "ofMain.h"  
  
#include "Poco/URIStreamOpener.h"  
#include "Poco/StreamCopier.h"  
#include "Poco/Path.h"  
#include "Poco/URI.h"  
#include "Poco/Exception.h"  
#include "Poco/Net/HTTPStreamFactory.h"  
#include <memory>  
#include <iostream>  
  
using Poco::URIStreamOpener;  
using Poco::StreamCopier;  
using Poco::Path;  
using Poco::URI;  
using Poco::Exception;  
using Poco::Net::HTTPStreamFactory;  
  
static bool factoryLoaded = false;  
  
class webImageLoader : public ofImage {   
  
   public :   
     
		void loadFromUrl(string url);	  
       	     
};   

webImageLoader.cpp

  
#include "webImageLoader.h"  
  
void webImageLoader::loadFromUrl(string url){  
  
	//poco is not happy if we register the factory more than once  
	if(!factoryLoaded){  
		HTTPStreamFactory::registerFactory();  
		factoryLoaded = true;  
	}  
  
	//specify out url and open stream  
	URI uri(url);		  
	std::auto_ptr<std::istream> pStr(URIStreamOpener::defaultOpener().open(uri));  
	  
	//copy to our string  
	string str;         
	StreamCopier::copyToString(*pStr.get(), str);   
  
	//figure out how many bytes the image is and allocate  
	int bytesToRead = str.size();   
	char buff[bytesToRead];   
	memset(buff, 0, bytesToRead);   
	  
	//copy the bytes from the string to our buffer  
	for(int i = 0; i < bytesToRead; i++){   
	 buff[i] = str[i];   
	}   
  
	printf("numBytes copied is %i \n", sizeof(buff));  
  
	//if we already have a loaded image clear it  
	if(isValid()){   
	 clear();       
	}   
	  
	//create a freeimage memory handle from the buffer address  
	FIMEMORY *hmem = NULL;   
	hmem = FreeImage_OpenMemory((BYTE *)buff, bytesToRead);   
	if (hmem == NULL){ printf("couldn't create memory handle! \n"); return; }   
		  
	//get the file type!  
	FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem);   
  
	//make the image!!  
	bmp = FreeImage_LoadFromMemory(fif, hmem, 0);  
  
	//free our memory  
	FreeImage_CloseMemory(hmem);  
	  
	if (bmp == NULL){ printf("couldn't create bmp! \n"); return; }   
	  
	//flip it!  
	FreeImage_FlipVertical(bmp);   
	update();   
}	  
  

Hey Guys.

Thanks for the info and the code. This is perfect.

-Brian

hey theo -

thanks for the link. just out of curiosity, what does this line return for you?

  
  
//get the file type!   
FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem);   
  

i’m getting a -1, which i guess means that it’s unable to determine the file type. and if i hardcode FIF_JPEG into FreeImage_LoadFromMemory, my app crashes.

all the best,

jeremy

Hey guys, I updated webImageLoader.cpp for OF 057 and possibly beyond (which nicely already has Poco inside of it). Let me know if you have any problems

  
  
#include "webImageLoader.h"  
  
void webImageLoader::loadFromUrl(string url){  
  
   //poco is not happy if we register the factory more than once  
   if(!factoryLoaded){  
      HTTPStreamFactory::registerFactory();  
      factoryLoaded = true;  
   }  
  
   //specify out url and open stream  
   URI uri(url);        
   std::auto_ptr<std::istream> pStr(URIStreamOpener::defaultOpener().open(uri));  
     
   //copy to our string  
   string str;         
   StreamCopier::copyToString(*pStr.get(), str);  
  
   //figure out how many bytes the image is and allocate  
   int bytesToRead = str.size();  
   char buff[bytesToRead];  
   memset(buff, 0, bytesToRead);  
     
   //copy the bytes from the string to our buffer  
   for(int i = 0; i < bytesToRead; i++){  
    buff[i] = str[i];  
   }  
  
   printf("numBytes copied is %i \n", sizeof(buff));  
  
   //if we already have a loaded image clear it  
  // if(isValid()){  
    clear();       
  // }  
     
   //create a freeimage memory handle from the buffer address  
   FIMEMORY *hmem = NULL;  
   hmem = FreeImage_OpenMemory((BYTE *)buff, bytesToRead);  
   if (hmem == NULL){ printf("couldn't create memory handle! \n"); return; }  
        
   //get the file type!  
   FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem);  
  
   //make the image!!  
	putBmpIntoPixels(FreeImage_LoadFromMemory(fif, hmem, 0), myPixels);  
 //  bmp = FreeImage_LoadFromMemory(fif, hmem, 0);  
  
   //free our memory  
   FreeImage_CloseMemory(hmem);  
     
   if (getBmpFromPixels(myPixels) == NULL){ printf("couldn't create bmp! \n"); return; }  
     
   //flip it!  
   FreeImage_FlipVertical(getBmpFromPixels(myPixels));  
     
	if (myPixels.bAllocated == true && bUseTexture == true){  
		tex.allocate(myPixels.width, myPixels.height, myPixels.glDataType);  
	}	  
	  
	swapRgb(myPixels);  
     
   update();  
}      
  

Hey All, thanks for this code, I combined it with some other useful forum posts and made:

http://forum.openframeworks.cc/t/flickrscraperslideshow/1257/0

A flickr Scraper slideshow.

Thanks again,

JGL

Hey, just and idea maybe It will be nice have native load image class from internet, adding this class inside core of OF or as an addon.

hugs to all

Mar

Hey,

I was trying to use the webImageLoader class and ran across this error? I’m new to oF but I suspect this is a remnant of a constant that used to exist that doesn’t anymore.

  
error: 'BYTE' was not declared in this scope  

Any help is much appreciated, thanks!

edit: nevermind, just changed it to unsigned char * and we’ll see how that works, but now I’m getting a SIGABRT program error but that’s probably just me.

  
error: 'BYTE' was not declared in this scope  

I presume you need to include FreeImage.h :slight_smile:

[quote author=“jedmund”]Hey,

I was trying to use the webImageLoader class and ran across this error? I’m new to oF but I suspect this is a remnant of a constant that used to exist that doesn’t anymore.

  
error: 'BYTE' was not declared in this scope  

Any help is much appreciated, thanks!

edit: nevermind, just changed it to unsigned char * and we’ll see how that works, but now I’m getting a SIGABRT program error but that’s probably just me.[/quote]

hey !
Did you solve this error?
Im on the same situation

I was trying to use the webImageLoader class and ran across this error? I’m new to oF but I suspect this is a remnant of a constant that used to exist that doesn’t anymore.

Code:
error: ‘BYTE’ was not declared in this scope

Any help is much appreciated, thanks!

edit: nevermind, just changed it to unsigned char * and we’ll see how that works, but now I’m getting a SIGABRT program error but that’s probably just me.

just same problem for me.

just changed to ‘Byte’ and it works, but now I’m getting a EXEC_BAD_ACCESS at

  
if (myPixels.bAllocated == true && bUseTexture == true){  
      tex.allocate(myPixels.width, myPixels.height, myPixels.glDataType);  
   }    

using xcode 3.2.3 on MAC OS X

Reviving a super old thread, but wanted to leave a note for the next person: the following just works in the latest oF.

ofImage.loadImage("http://some.com/url.png")