You Are Here:

Community: Developer Discussion Boards

#1 Old No image loading/saving on 1.2 phones, why ? - 2005-08-17, 16:38

Join Date: Dec 2003
Posts: 17
vyskocil
Offline
Registered User
I understand that you implemented image file loading and saving (jpg, gif, etc...) using the "new" MultiMedia Framework on symbian phone with version greater or equal to 7.0 (serie 60 2.x) but why don't you used a falback API on older phone to make the graphic API consistent over all serie 60 phone ? Isn't this the goal of a scripting language to hide this ?

I found that older phone have a quite simple ImageConverter API : http://www.cs.tut.fi/~mobo/Symbianv6...ter/index.html
and you could use CMdaImageFileToBitmapUtility object to achive the needed function for loading bitmap file.

I hope very much you will had some time to add this feature for us poor old symbian phone owner (but my ngage is great in a next release...
Reply With Quote

#2 Old Example image converter - 2005-08-17, 21:14

Join Date: Feb 2004
Posts: 11
Location: San Diego
nikhil_vaj
Offline
Registered User
From one poor old symbian phone owner to another (Sorry about the long post):

Source code:
Code:
#include <e32std.h>
#include <e32base.h>

#include <Python.h>
#include <symbian_python_ext_util.h>

#include <MdaImageConverter.h>	// MMdaImageUtilObserver

#define MODULE_NAME sdk12graphics //:ulwp COMP_NAME
#define MODULE_NAME_STRING "sdk12graphics" //:usp COMP_NAME.inspect

// the init function name actually does not matter,
// since on Symbian, lookups are purely by ordinal
#define MODULE_INIT_FUNC initsdk12graphics //:ulwp 'init' + COMP_NAME

class CMdaImageFileToBitmapUtility;
class CFbsBitmap;

// Image converter implementation
class CImageConverter : 
	public CBase, 
	public MMdaImageUtilObserver
{
public:
	static CImageConverter* NewL();
	static CImageConverter* NewLC();
	virtual ~CImageConverter();

public:	// Member functions
	void ConvertImage(TPtrC& imagePath);
	bool IsImageLoaded() const;

protected:	// From MMdaImageUtilObserver
	// Observer functions to inform client code that the current
	// asynchronous step within the manipulation process has completed
	void MiuoConvertComplete(TInt aError);
	void MiuoCreateComplete(TInt aError);
	void MiuoOpenComplete(TInt aError);

private:	// Construction
	void ConstructL();
	CImageConverter();

private:	// Member Functions.
	// Image converstion functions
	void DecodeOpenL(TPtrC& imagePath);
	void DecodeConvertL();

private: // Member data
	bool iImageLoaded;
	CActiveSchedulerWait* iLoop;

	// From Media Server
	CMdaImageFileToBitmapUtility* iFileToBitmap;

	// Bitmap object - saved in the TLS
	CFbsBitmap* iImage;
};

// Two phase construction
CImageConverter* CImageConverter::NewL()
{
	CImageConverter* self = CImageConverter::NewLC();
	CleanupStack::Pop();
	return self;
}

CImageConverter* CImageConverter::NewLC()
{
	CImageConverter* self = new (ELeave) CImageConverter();
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
}

void CImageConverter::ConstructL()
{
	iFileToBitmap = CMdaImageFileToBitmapUtility::NewL(*this);
	iLoop = new (ELeave) CActiveSchedulerWait();
}

CImageConverter::CImageConverter()
 :	iLoop(NULL)
	, iFileToBitmap(NULL)
{
}

CImageConverter::~CImageConverter()
{
	delete iFileToBitmap;
	delete iLoop;
}

// Conversion routine
void CImageConverter::ConvertImage(TPtrC& imagePath)
{
	iImageLoaded = FALSE;
	iFileToBitmap->Cancel();
	DecodeOpenL(imagePath);
	iLoop->Start();
}

// Tries to open the image
void CImageConverter::DecodeOpenL(TPtrC& imagePath)
{
	iFileToBitmap->OpenL(imagePath);
}

// Return from the image open routine (success or failure)
void CImageConverter::MiuoOpenComplete(TInt aError)
{
	if (aError == KErrNone)
	{
		TRAPD (err, DecodeConvertL());
	}
	else
	{
		iLoop->AsyncStop();
	}
}

// Tries to convert the image
void CImageConverter::DecodeConvertL()
{
	TFrameInfo frmInfo;
	iFileToBitmap->FrameInfo(0, frmInfo);
	iImage = new (ELeave) CFbsBitmap();
	// Save the bitmap pointer on Thread Local Storage
	Dll::SetTls(static_cast<TAny*>(iImage));
	iImage->Create(frmInfo.iOverallSizeInPixels, EColor4K);
	iFileToBitmap->ConvertL(*iImage, 0);
}

// Return from image conversion routine
void CImageConverter::MiuoConvertComplete(TInt aError)
{
	if (aError == KErrNone)
	{
		iImageLoaded = TRUE;
	}
	iLoop->AsyncStop();
}

// Called in case of creating an image
void CImageConverter::MiuoCreateComplete(TInt /*aError*/) {}

bool CImageConverter::IsImageLoaded() const
{
	return iImageLoaded;
}

// Converts a GIF/JPEG image into CFbsBitmap object and returns
// a PyCObject with a pointer to CFbsBitmap
static PyObject* sdk12graphics_ConvertImage(PyObject* /*self*/, PyObject* args)
{
	TInt error;
	char* b;
	int l;

	if (!PyArg_ParseTuple(args, "u#", &b, &l))
	{
		Py_INCREF(Py_None);
		return Py_None;
	}
	TPtrC imagePath((TUint16*)b, l);

	CImageConverter* converter = CImageConverter::NewL();
	CleanupStack::PushL(converter);

	Py_BEGIN_ALLOW_THREADS;
	TRAP(error, converter->ConvertImage(imagePath));
	Py_END_ALLOW_THREADS;

	if (error)
	{
		Py_INCREF(Py_None);
		return Py_None;
	}

	if(!converter->IsImageLoaded())
	{
		Py_INCREF(Py_None);
		return Py_None;
	}

	// copies the object;
	// returns NULL if cannot build the value
	PyObject* arg = PyCObject_FromVoidPtr((void *)static_cast<CFbsBitmap*>(Dll::Tls()), NULL);

	CleanupStack::PopAndDestroy(converter);

	if (!arg)
	{
		// should set an exception
		Py_INCREF(Py_None);
		return Py_None;
	}

	return arg;
}

//(ui $py_module.method_table_def
static const PyMethodDef sdk12graphics_methods[] =
{
	{"convertimage", (PyCFunction)sdk12graphics_ConvertImage, METH_VARARGS, "Returns a CObject with a CFbsBitmap*"},
	{NULL, NULL} /* sentinel */
};
#define METHOD_TABLE const_cast<PyMethodDef*>(&sdk12graphics_methods[0])
//) end method table

// Init function
DL_EXPORT(void) MODULE_INIT_FUNC()
{
	PyObject* module = Py_InitModule(MODULE_NAME_STRING, METHOD_TABLE);
	if (!module)
	{
		return;
	}
	// Add extra initialization here
}

// DLL function
GLDEF_C TInt E32Dll(TDllReason)
{
	return KErrNone;
}
MMP File:
Code:
TARGETTYPE	dll
TARGET		sdk12graphics.pyd
TARGETPATH \system\libs

UID		0x1000008d 0x1f87d786

TARGETPATH	\system\libs\

SYSTEMINCLUDE	\epoc32\include
SYSTEMINCLUDE	\epoc32\include\libc
SYSTEMINCLUDE	\epoc32\..\python-port-s60\symbian_python\symbian
SYSTEMINCLUDE	\epoc32\..\python-port-s60\symbian_python\include
SYSTEMINCLUDE	\epoc32\..\python-port-s60\symbian_python\python

LIBRARY euser.lib
LIBRARY python222.lib
LIBRARY MediaClientImage.lib 
LIBRARY fbscli.lib
LIBRARY estlib.lib

USERINCLUDE .
SOURCEPATH .

SOURCE sdk12graphics.cpp
Example usage (Imageviewer example):
Code:
import sdk12graphics
from appuifw import *
from graphics import *
import e32

c=Canvas()
app.body=c
screenbm=Image.new((176,208))
drc=Draw(screenbm)
draw_realscreen=Draw(c)
if e32.in_emulator():
    imagedir=u'z:\\system\\data'
else:
    imagedir=u'e:\\images'
files=map(unicode,os.listdir(imagedir))

index=selection_list(files)
print index

import key_codes
lock=e32.Ao_lock()

def fullupdate():
    drc.clear(bgcolor)
    update()
    
def nextpic():
    global index
    index=(index+1)%len(files)
    lock.signal()
def prevpic():
    global index
    index=(index-1)%len(files)
    lock.signal()

def zoomin():
    global zoomstepindex,zoom
    if zoomstepindex < (len(zoomsteps)-1):
        zoomstepindex+=1
    zoom=zoomsteps[zoomstepindex]
    fullupdate()

def zoomout():
    global zoomstepindex
    if zoomstepindex > 0:
        zoomstepindex-=1
    zoom=zoomsteps[zoomstepindex]
    drc.clear(bgcolor)
    fullupdate()

app.screen='full'
draw_realscreen.clear(0)
center=[0,0]
zoom=1
zoomstepindex=0
screensize=(176,208)
screenrect=(0,0,screensize[0],screensize[1])
step=30



def isvalidcenter(c):
    iw,ih=(bm.size[0],bm.size[1])
    srcsize=(int(screensize[0]/zoom),int(screensize[1]/zoom))
    vw,vh=(srcsize[0]/2,srcsize[1]/2)    
    return (c[0]+vw<iw and c[0]-vw>=0 and
            c[1]+vh<ih and c[1]-vh>=0)
def move(delta):
    global center
    c=center
    for k in range(1,4):
        t=[c[0]+int(delta[0]*k*20/zoom),
           c[1]+int(delta[1]*k*20/zoom)]
        center=t
        update()

bgcolor=0

c.bind(key_codes.EKey3,nextpic)
c.bind(key_codes.EKey1,prevpic)
c.bind(key_codes.EKey5,zoomin)
c.bind(key_codes.EKey0,zoomout)
c.bind(key_codes.EKeyLeftArrow,lambda:move((-1,0)))
c.bind(key_codes.EKeyRightArrow,lambda:move((1,0)))
c.bind(key_codes.EKeyUpArrow,lambda:move((0,-1)))
c.bind(key_codes.EKeyDownArrow,lambda:move((0,1)))

def resizetest():
    bm.resize((100,100))
    fullupdate()

c.bind(key_codes.EKey8,resizetest)

def rect_intersection(r1,r2):
    return (max(r1[0],r2[0]),max(r1[1],r2[1]),
            min(r1[2],r2[2]),min(r1[3],r2[3]))
    
def update():
    global zoom
    zoom=zoomsteps[zoomstepindex]
    # We convert the screen rect into image coordinates, compute its
    # intersection with the image rect and transform it back to screen
    # coordinates.
    imgrect=(0,0,bm.size[0],bm.size[1])    
    ss=(int(screensize[0]/zoom),int(screensize[1]/zoom))
    screenrect_imgcoords=(center[0]-ss[0]/2,center[1]-ss[1]/2,
                          center[0]+ss[0]/2,center[1]+ss[1]/2)
    sourcerect=rect_intersection(screenrect_imgcoords,imgrect)
    targetrect=(int((sourcerect[0]-center[0])*zoom+screensize[0]/2),
                int((sourcerect[1]-center[1])*zoom+screensize[1]/2),
                int((sourcerect[2]-center[0])*zoom+screensize[0]/2),
                int((sourcerect[3]-center[1])*zoom+screensize[1]/2))
    drc.clear(bgcolor)
    drc.blit(bm,source=sourcerect,target=targetrect,scale=1)
    drc.text((0,10),files[index],(0,255,0))
    draw_realscreen.blit(screenbm)

running=1
def quit():
    global running,lock
    running=0
    lock.signal()
    
app.exit_key_handler=quit
drc.clear(bgcolor)

selected_file=imagedir+"\\"+files[index]

im=None
bitmap = None
bm = None
while running:
    selected_file=imagedir+"\\"+files[index]
    if bitmap is not None:
        del bitmap
    bitmap = sdk12graphics.convertimage(selected_file)
    if bitmap is not None:
        bm = Image.from_cfbsbitmap(bitmap) 
        zoomsteps=[1.*screensize[0]/bm.size[0],.25,.5,1]
        zoomstepindex=0
        center=[bm.size[0]/2,bm.size[1]/2]    
        fullupdate()
        lock.wait()
bm=None
screenbm=None
Hope this helps. Please let me know if there is any problem.

Best Regards,
Nikhil
Reply With Quote

#3 Old Re: Example image converter - 2005-08-18, 09:15

Join Date: Sep 2003
Posts: 209
Location: Finland
otsov
Offline
Regular Contributor
I did not tried it yet, but seems proper, very nice!

Some minor corrections (quick peek of code):

o Add "L"-prefix to "CImageConverter::ConvertImage()"
o "TRUE" = "ETrue"
o Surround with TRAP-harness:
Code:
CImageConverter* converter = CImageConverter::NewL();
CleanupStack::PushL(converter);
o Error code handling:
Code:
	Py_BEGIN_ALLOW_THREADS;
	TRAP(error, converter->ConvertImage(imagePath));
	Py_END_ALLOW_THREADS;

	if (error)
	{
		Py_INCREF(Py_None);
		return Py_None;
	}
Instead of returning "Py_None" consider using "SPyErr_SetFromSymbianOSErr" (see API reference, Appendix C)
o UID line is not needed in the ".mmp" file (target is DLL)
o The TLS-usage could be converted to just returning the pointer from "CImageConverter::ConvertImage()"?
o I have a faint recollection for a reason to "python222.lib" to appear before "euser.lib" in ".mmp"-files (I might be wrong here)
Reply With Quote

#4 Old Great ! - 2005-08-18, 14:35

Join Date: Dec 2003
Posts: 17
vyskocil
Offline
Registered User
Nikhil thank you very much sharing your code !
I just made a good old Makefile to compile it on linux (I don't like the sdk build tools with MMP files, I prefer old good Makefile...).
It is working great for now !
It would be nice to merge a similar code in a next Py60 release :-)
Reply With Quote

#5 Old Re: No image loading/saving on 1.2 phones, why ? - 2006-05-01, 21:07

Join Date: Feb 2005
Posts: 1,353
Location: Belgium (Europe)
cyke64's Avatar
cyke64
Offline
Super Contributor
hello ,

For my first extension in C++ for pys60 , I took your code , updated a little , make a little package and publish it on my google pages !

You can find it at http://cyke64.googlepages.com/ with the imageviewer1st exemple !

http://cyke64.googlepages.com/image1st.SIS
http://cyke64.googlepages.com/imageviewer1st.py

PS : I try it on pys60 1.3.1 and 2nd Ed and it works too.
Try it on 1st and report any error to me !


pys60 1.4.5,1.9.7,pygame,PyS60 CE on E90 , N810 with Python 2.5.2 and ... last PyS60 1.9.7 with touch ui on 5800 !

pys60 extension modules on http://cyke64.googlepages.com/
Reply With Quote
Reply « Previous Thread | Next Thread »
Display Modes
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules

You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Forum Jump

Rate This

 
Bookmark this page: DeliciousDiggFacebookGoogleYahooStumbleUponRedditDiigoTechnocratiTwitter  Share this page Share this page Print this Page Print this page Invite a friend Invite a friend
京ICP备05048969号    Email Newsletters Press Terms & Conditions Privacy Policy Sitemap Contact Us © 2009 Nokia