| Reply | « Previous Thread | Next Thread » |
|
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... |
|
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;
}
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 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
Best Regards, Nikhil |
| nikhil_vaj |
| View Public Profile |
| Find all posts by nikhil_vaj |
|
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); Code:
Py_BEGIN_ALLOW_THREADS;
TRAP(error, converter->ConvertImage(imagePath));
Py_END_ALLOW_THREADS;
if (error)
{
Py_INCREF(Py_None);
return Py_None;
}
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) |
|
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 :-) |
|
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 | « Previous Thread | Next Thread » |
| Thread Tools | Search this Thread |
|---|---|
| Rate This Thread | |