py::Object next ( py::Object self ) { const py::Object line = readline(self); if (line.handle() == py::none.handle()) { return (py::Object()); } return (line); }
void CallTipsList::extractTipsFromObject(Py::Object& obj, Py::List& list, QMap<QString, CallTip>& tips) const { try { for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { Py::String attrname(*it); Py::Object attr = obj.getAttr(attrname.as_string()); CallTip tip; QString str = QString::fromLatin1(attrname.as_string().c_str()); tip.name = str; if (attr.isCallable()) { union PyType_Object basetype = {&PyBaseObject_Type}; if (PyObject_IsSubclass(attr.ptr(), basetype.o) == 1) { tip.type = CallTip::Class; } else { PyErr_Clear(); // PyObject_IsSubclass might set an exception tip.type = CallTip::Method; } } else if (PyModule_Check(attr.ptr())) { tip.type = CallTip::Module; } else { tip.type = CallTip::Member; } if (str == QLatin1String("__doc__") && attr.isString()) { Py::Object help = attr; if (help.isString()) { Py::String doc(help); QString longdoc = QString::fromUtf8(doc.as_string().c_str()); int pos = longdoc.indexOf(QLatin1Char('\n')); pos = qMin(pos, 70); if (pos < 0) pos = qMin(longdoc.length(), 70); tip.description = stripWhiteSpace(longdoc); tip.parameter = longdoc.left(pos); } } else if (attr.hasAttr("__doc__")) { Py::Object help = attr.getAttr("__doc__"); if (help.isString()) { Py::String doc(help); QString longdoc = QString::fromUtf8(doc.as_string().c_str()); int pos = longdoc.indexOf(QLatin1Char('\n')); pos = qMin(pos, 70); if (pos < 0) pos = qMin(longdoc.length(), 70); tip.description = stripWhiteSpace(longdoc); tip.parameter = longdoc.left(pos); } } tips[str] = tip; } } catch (Py::Exception& e) { // Just clear the Python exception e.clear(); } }
QMap<QString, CallTip> CallTipsList::extractTips(const QString& context) const { Base::PyGILStateLocker lock; QMap<QString, CallTip> tips; if (context.isEmpty()) return tips; try { Py::Module module("__main__"); Py::Dict dict = module.getDict(); #if 0 QStringList items = context.split(QLatin1Char('.')); QString modname = items.front(); items.pop_front(); if (!dict.hasKey(std::string(modname.toLatin1()))) return tips; // unknown object // get the Python object we need Py::Object obj = dict.getItem(std::string(modname.toLatin1())); while (!items.isEmpty()) { QByteArray name = items.front().toLatin1(); std::string attr = name.constData(); items.pop_front(); if (obj.hasAttr(attr)) obj = obj.getAttr(attr); else return tips; } #else // Don't use hasattr & getattr because if a property is bound to a method this will be executed twice. PyObject* code = Py_CompileString(static_cast<const char*>(context.toLatin1()), "<CallTipsList>", Py_eval_input); if (!code) { PyErr_Clear(); return tips; } PyObject* eval = 0; if (PyCode_Check(code)) { eval = PyEval_EvalCode(reinterpret_cast<PyCodeObject*>(code), dict.ptr(), dict.ptr()); } Py_DECREF(code); if (!eval) { PyErr_Clear(); return tips; } Py::Object obj(eval, true); #endif // Checks whether the type is a subclass of PyObjectBase because to get the doc string // of a member we must get it by its type instead of its instance otherwise we get the // wrong string, namely that of the type of the member. // Note: 3rd party libraries may use their own type object classes so that we cannot // reliably use Py::Type. To be on the safe side we should use Py::Object to assign // the used type object to. //Py::Object type = obj.type(); Py::Object type(PyObject_Type(obj.ptr()), true); Py::Object inst = obj; // the object instance union PyType_Object typeobj = {&Base::PyObjectBase::Type}; union PyType_Object typedoc = {&App::DocumentObjectPy::Type}; union PyType_Object basetype = {&PyBaseObject_Type}; if (PyObject_IsSubclass(type.ptr(), typedoc.o) == 1) { // From the template Python object we don't query its type object because there we keep // a list of additional methods that we won't see otherwise. But to get the correct doc // strings we query the type's dict in the class itself. // To see if we have a template Python object we check for the existence of supportedProperties if (!type.hasAttr("supportedProperties")) { obj = type; } } else if (PyObject_IsSubclass(type.ptr(), typeobj.o) == 1) { obj = type; } else if (PyInstance_Check(obj.ptr())) { // instances of old style classes PyInstanceObject* inst = reinterpret_cast<PyInstanceObject*>(obj.ptr()); PyObject* classobj = reinterpret_cast<PyObject*>(inst->in_class); obj = Py::Object(classobj); } else if (PyObject_IsInstance(obj.ptr(), basetype.o) == 1) { // New style class which can be a module, type, list, tuple, int, float, ... // Make sure it's not a type objec union PyType_Object typetype = {&PyType_Type}; if (PyObject_IsInstance(obj.ptr(), typetype.o) != 1) { // this should be now a user-defined Python class // http://stackoverflow.com/questions/12233103/in-python-at-runtime-determine-if-an-object-is-a-class-old-and-new-type-instan if (Py_TYPE(obj.ptr())->tp_flags & Py_TPFLAGS_HEAPTYPE) { obj = type; } } } // If we have an instance of PyObjectBase then determine whether it's valid or not if (PyObject_IsInstance(inst.ptr(), typeobj.o) == 1) { Base::PyObjectBase* baseobj = static_cast<Base::PyObjectBase*>(inst.ptr()); const_cast<CallTipsList*>(this)->validObject = baseobj->isValid(); } else { // PyObject_IsInstance might set an exception PyErr_Clear(); } Py::List list(obj.dir()); // If we derive from PropertyContainerPy we can search for the properties in the // C++ twin class. union PyType_Object proptypeobj = {&App::PropertyContainerPy::Type}; if (PyObject_IsSubclass(type.ptr(), proptypeobj.o) == 1) { // These are the attributes of the instance itself which are NOT accessible by // its type object extractTipsFromProperties(inst, tips); } // If we derive from App::DocumentPy we have direct access to the objects by their internal // names. So, we add these names to the list, too. union PyType_Object appdoctypeobj = {&App::DocumentPy::Type}; if (PyObject_IsSubclass(type.ptr(), appdoctypeobj.o) == 1) { App::DocumentPy* docpy = (App::DocumentPy*)(inst.ptr()); App::Document* document = docpy->getDocumentPtr(); // Make sure that the C++ object is alive if (document) { std::vector<App::DocumentObject*> objects = document->getObjects(); Py::List list; for (std::vector<App::DocumentObject*>::iterator it = objects.begin(); it != objects.end(); ++it) list.append(Py::String((*it)->getNameInDocument())); extractTipsFromObject(inst, list, tips); } } // If we derive from Gui::DocumentPy we have direct access to the objects by their internal // names. So, we add these names to the list, too. union PyType_Object guidoctypeobj = {&Gui::DocumentPy::Type}; if (PyObject_IsSubclass(type.ptr(), guidoctypeobj.o) == 1) { Gui::DocumentPy* docpy = (Gui::DocumentPy*)(inst.ptr()); if (docpy->getDocumentPtr()) { App::Document* document = docpy->getDocumentPtr()->getDocument(); // Make sure that the C++ object is alive if (document) { std::vector<App::DocumentObject*> objects = document->getObjects(); Py::List list; for (std::vector<App::DocumentObject*>::iterator it = objects.begin(); it != objects.end(); ++it) list.append(Py::String((*it)->getNameInDocument())); extractTipsFromObject(inst, list, tips); } } } // These are the attributes from the type object extractTipsFromObject(obj, list, tips); } catch (Py::Exception& e) { // Just clear the Python exception e.clear(); } return tips; }
Py::Object RendererAgg::draw_lines(const Py::Tuple& args) { theRasterizer->reset_clipping(); _VERBOSE("RendererAgg::draw_lines"); args.verify_length(3); Py::Object gc = args[0]; Py::SeqBase<Py::Object> x = args[1]; //todo: use numerix for efficiency Py::SeqBase<Py::Object> y = args[2]; //todo: use numerix for efficiency set_clip_rectangle(gc); size_t Nx = x.length(); size_t Ny = y.length(); if (Nx!=Ny) throw Py::ValueError("x and y must be equal length sequences"); if (Nx<2) throw Py::ValueError("x and y must have length >= 2"); agg::vcgen_stroke::line_cap_e cap = get_linecap(gc); agg::vcgen_stroke::line_join_e join = get_joinstyle(gc); double lw = points_to_pixels ( gc.getAttr("_linewidth") ) ; //std::cout << "agg lw " << lw << std::endl; agg::rgba color = get_color(gc); // process the dashes Py::Tuple dashes = get_dashes(gc); bool useDashes = dashes[0].ptr() != Py_None; double offset = 0; Py::SeqBase<Py::Object> dashSeq; if ( dashes[0].ptr() != Py_None ) { // use dashes //TODO: use offset offset = points_to_pixels_snapto(dashes[0]); dashSeq = dashes[1]; }; agg::path_storage path; int isaa = antialiased(gc); double heightd = double(height); if (Nx==2) { // this is a little hack - len(2) lines are probably grid and // ticks so I'm going to snap to pixel //printf("snapto %d\n", Nx); double x0 = Py::Float(x[0]); double y0 = Py::Float(y[0]); double x1 = Py::Float(x[1]); double y1 = Py::Float(y[1]); if (x0==x1) { x0 = (int)x0 + 0.5; x1 = (int)x1 + 0.5; } if (y0==y1) { y0 = (int)y0 + 0.5; y1 = (int)y1 + 0.5; } y0 = heightd-y0; y1 = heightd-y1; path.move_to(x0, y0); path.line_to(x1, y1); } else { double thisX = Py::Float( x[0] ); double thisY = Py::Float( y[0] ); thisY = heightd - thisY; //flipy path.move_to(thisX, thisY); for (size_t i=1; i<Nx; ++i) { thisX = Py::Float( x[i] ); thisY = Py::Float( y[i] ); thisY = heightd - thisY; //flipy //if ((i<10) || i>=19990) //std::cout << i << " " << Nx << " " << thisX << " " << thisY << std::endl; path.line_to(thisX, thisY); } } //std::cout << width << " " << height << std::endl; if (! useDashes ) { agg::conv_stroke<agg::path_storage> stroke(path); stroke.line_cap(cap); stroke.line_join(join); stroke.width(lw); //freeze was here std::cout << "\t adding path!" << std::endl; theRasterizer->add_path(stroke); } else { // set the dashes //TODO: scale for DPI size_t N = dashSeq.length(); if (N%2 != 0 ) throw Py::ValueError("dashes must be an even length sequence"); typedef agg::conv_dash<agg::path_storage> dash_t; dash_t dash(path); double on, off; for (size_t i=0; i<N/2; i+=1) { on = points_to_pixels_snapto(dashSeq[2*i]); off = points_to_pixels_snapto(dashSeq[2*i+1]); dash.add_dash(on, off); } agg::conv_stroke<dash_t> stroke(dash); stroke.line_cap(cap); stroke.line_join(join); stroke.width(lw); theRasterizer->add_path(stroke); } if ( isaa ) { rendererAA->color(color); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); } else { rendererBin->color(color); agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin); } return Py::Object(); }
Py::Object _image_module::fromarray(const Py::Tuple& args) { _VERBOSE("_image_module::fromarray"); args.verify_length(2); Py::Object x = args[0]; int isoutput = Py::Int(args[1]); PyArrayObject *A = (PyArrayObject *) PyArray_ContiguousFromObject(x.ptr(), PyArray_DOUBLE, 2, 3); if (A==NULL) throw Py::ValueError("Array must be rank 2 or 3 of doubles"); Image* imo = new Image; imo->rowsIn = A->dimensions[0]; imo->colsIn = A->dimensions[1]; size_t NUMBYTES(imo->colsIn * imo->rowsIn * imo->BPP); agg::int8u *buffer = new agg::int8u[NUMBYTES]; if (buffer==NULL) //todo: also handle allocation throw throw Py::MemoryError("_image_module::fromarray could not allocate memory"); imo->bufferIn = buffer; imo->rbufIn = new agg::rendering_buffer; imo->rbufIn->attach(buffer, imo->colsIn, imo->rowsIn, imo->colsIn*imo->BPP); if (A->nd == 2) { //assume luminance for now; agg::int8u gray; int start = 0; for (size_t rownum=0; rownum<imo->rowsIn; rownum++) for (size_t colnum=0; colnum<imo->colsIn; colnum++) { double val = *(double *)(A->data + rownum*A->strides[0] + colnum*A->strides[1]); gray = int(255 * val); *(buffer+start++) = gray; // red *(buffer+start++) = gray; // green *(buffer+start++) = gray; // blue *(buffer+start++) = 255; // alpha } } else if (A->nd == 3) { // assume RGB if (A->dimensions[2] != 3 && A->dimensions[2] != 4 ) { Py_XDECREF(A); throw Py::ValueError(Printf("3rd dimension must be length 3 (RGB) or 4 (RGBA); found %d", A->dimensions[2]).str()); } int rgba = A->dimensions[2]==4; int start = 0; double r,g,b,alpha; int offset =0; for (size_t rownum=0; rownum<imo->rowsIn; rownum++) for (size_t colnum=0; colnum<imo->colsIn; colnum++) { offset = rownum*A->strides[0] + colnum*A->strides[1]; r = *(double *)(A->data + offset); g = *(double *)(A->data + offset + A->strides[2] ); b = *(double *)(A->data + offset + 2*A->strides[2] ); if (rgba) alpha = *(double *)(A->data + offset + 3*A->strides[2] ); else alpha = 1.0; *(buffer+start++) = int(255*r); // red *(buffer+start++) = int(255*g); // green *(buffer+start++) = int(255*b); // blue *(buffer+start++) = int(255*alpha); // alpha } } else { // error Py_XDECREF(A); throw Py::ValueError("Illegal array rank; must be rank; must 2 or 3"); } Py_XDECREF(A); if (isoutput) { // make the output buffer point to the input buffer imo->rowsOut = imo->rowsIn; imo->colsOut = imo->colsIn; imo->bufferOut = new agg::int8u[NUMBYTES]; if (buffer == imo->bufferOut) //todo: also handle allocation throw throw Py::MemoryError("_image_module::fromarray could not allocate memory"); imo->rbufOut = new agg::rendering_buffer; imo->rbufOut->attach(imo->bufferOut, imo->colsOut, imo->rowsOut, imo->colsOut * imo->BPP); for (size_t i=0; i<NUMBYTES; i++) *(imo->bufferOut +i) = *(imo->bufferIn +i); } return Py::asObject( imo ); }
PythonObject::PythonObject(const Py::Object& object) : Qross::Object() , d(new Private(object)) { #ifdef QROSS_PYTHON_FUNCTION_DEBUG qrossdebug( QString("PythonObject::PythonObject() constructor") ); #endif Py::List x( object.dir() ); for(Py::Sequence::iterator i= x.begin(); i != x.end(); ++i) { std::string s = (*i).str(); if(s == "__init__") continue; //if(! m_pyobject.hasAttr( (*i).str() )) continue; Py::Object o = d->m_pyobject.getAttr(s); #ifdef QROSS_PYTHON_FUNCTION_DEBUG QString t; if(o.isCallable()) t += "isCallable "; if(o.isDict()) t += "isDict "; if(o.isList()) t += "isList "; if(o.isMapping()) t += "isMapping "; if(o.isNumeric()) t += "isNumeric "; if(o.isSequence()) t += "isSequence "; if(o.isTrue()) t += "isTrue "; if(o.isInstance()) t += "isInstance "; qrossdebug( QString("PythonObject::PythonObject() method '%1' (%2)").arg( (*i).str().as_string().c_str() ).arg(t) ); #endif if(o.isCallable()) d->m_calls.append( (*i).str().as_string().c_str() ); } }
TaskWatcherPython::TaskWatcherPython(const Py::Object& o) : TaskWatcher(0), watcher(o) { QString title; if (watcher.hasAttr(std::string("title"))) { Py::String name(watcher.getAttr(std::string("title"))); std::string s = (std::string)name; title = QString::fromUtf8(s.c_str()); } QPixmap icon; if (watcher.hasAttr(std::string("icon"))) { Py::String name(watcher.getAttr(std::string("icon"))); std::string s = (std::string)name; icon = BitmapFactory().pixmap(s.c_str()); } Gui::TaskView::TaskBox *tb = 0; if (watcher.hasAttr(std::string("commands"))) { if (!tb) tb = new Gui::TaskView::TaskBox(icon, title, true, 0); Py::List cmds(watcher.getAttr(std::string("commands"))); CommandManager &mgr = Gui::Application::Instance->commandManager(); for (Py::List::iterator it = cmds.begin(); it != cmds.end(); ++it) { Py::String name(*it); std::string s = (std::string)name; Command *c = mgr.getCommandByName(s.c_str()); if (c) c->addTo(tb); } } if (watcher.hasAttr(std::string("widgets"))) { if (!tb && !title.isEmpty()) tb = new Gui::TaskView::TaskBox(icon, title, true, 0); Py::List list(watcher.getAttr(std::string("widgets"))); Py::Module mainmod(PyImport_AddModule((char*)"sip")); Py::Callable func = mainmod.getDict().getItem("unwrapinstance"); for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { Py::Tuple arguments(1); arguments[0] = *it; //PyQt pointer Py::Object result = func.apply(arguments); void* ptr = PyLong_AsVoidPtr(result.ptr()); QObject* object = reinterpret_cast<QObject*>(ptr); if (object) { QWidget* w = qobject_cast<QWidget*>(object); if (w) { if (tb) tb->groupLayout()->addWidget(w); else Content.push_back(w); } } } } if (tb) Content.push_back(tb); if (watcher.hasAttr(std::string("filter"))) { Py::String name(watcher.getAttr(std::string("filter"))); std::string s = (std::string)name; this->setFilter(s.c_str()); } }
QMap<QString, CallTip> CallTipsList::extractTips(const QString& context) const { Base::PyGILStateLocker lock; QMap<QString, CallTip> tips; if (context.isEmpty()) return tips; try { QStringList items = context.split(QLatin1Char('.')); Py::Module module("__main__"); Py::Dict dict = module.getDict(); QString modname = items.front(); items.pop_front(); if (!dict.hasKey(std::string(modname.toAscii()))) return tips; // unknown object // get the Python object we need Py::Object obj = dict.getItem(std::string(modname.toAscii())); while (!items.isEmpty()) { QByteArray name = items.front().toAscii(); std::string attr = name.constData(); items.pop_front(); if (obj.hasAttr(attr)) obj = obj.getAttr(attr); else return tips; } // Checks whether the type is a subclass of PyObjectBase because to get the doc string // of a member we must get it by its type instead of its instance otherwise we get the // wrong string, namely that of the type of the member. // Note: 3rd party libraries may use their own type object classes so that we cannot // reliably use Py::Type. To be on the safe side we should use Py::Object to assign // the used type object to. //Py::Object type = obj.type(); Py::Object type(PyObject_Type(obj.ptr()), true); Py::Object inst = obj; // the object instance union PyType_Object typeobj = {&Base::PyObjectBase::Type}; union PyType_Object typedoc = {&App::DocumentObjectPy::Type}; if (PyObject_IsSubclass(type.ptr(), typedoc.o) == 1) { // From the template Python object we don't query its type object because there we keep // a list of additional methods that we won't see otherwise. But to get the correct doc // strings we query the type's dict in the class itself. // To see if we have a template Python object we check for the existence of supportedProperties if (!type.hasAttr("supportedProperties")) { obj = type; } } else if (PyObject_IsSubclass(type.ptr(), typeobj.o) == 1) { obj = type; } // If we have an instance of PyObjectBase then determine whether it's valid or not if (PyObject_IsInstance(inst.ptr(), typeobj.o) == 1) { Base::PyObjectBase* baseobj = static_cast<Base::PyObjectBase*>(inst.ptr()); const_cast<CallTipsList*>(this)->validObject = baseobj->isValid(); } else { // PyObject_IsInstance might set an exception PyErr_Clear(); } Py::List list(PyObject_Dir(obj.ptr()), true); // If we derive from PropertyContainerPy we can search for the properties in the // C++ twin class. union PyType_Object proptypeobj = {&App::PropertyContainerPy::Type}; if (PyObject_IsSubclass(type.ptr(), proptypeobj.o) == 1) { // These are the attributes of the instance itself which are NOT accessible by // its type object extractTipsFromProperties(inst, tips); } // If we derive from App::DocumentPy we have direct access to the objects by their internal // names. So, we add these names to the list, too. union PyType_Object appdoctypeobj = {&App::DocumentPy::Type}; if (PyObject_IsSubclass(type.ptr(), appdoctypeobj.o) == 1) { App::DocumentPy* docpy = (App::DocumentPy*)(inst.ptr()); App::Document* document = docpy->getDocumentPtr(); // Make sure that the C++ object is alive if (document) { std::vector<App::DocumentObject*> objects = document->getObjects(); Py::List list; for (std::vector<App::DocumentObject*>::iterator it = objects.begin(); it != objects.end(); ++it) list.append(Py::String((*it)->getNameInDocument())); extractTipsFromObject(inst, list, tips); } } // If we derive from Gui::DocumentPy we have direct access to the objects by their internal // names. So, we add these names to the list, too. union PyType_Object guidoctypeobj = {&Gui::DocumentPy::Type}; if (PyObject_IsSubclass(type.ptr(), guidoctypeobj.o) == 1) { Gui::DocumentPy* docpy = (Gui::DocumentPy*)(inst.ptr()); if (docpy->getDocumentPtr()) { App::Document* document = docpy->getDocumentPtr()->getDocument(); // Make sure that the C++ object is alive if (document) { std::vector<App::DocumentObject*> objects = document->getObjects(); Py::List list; for (std::vector<App::DocumentObject*>::iterator it = objects.begin(); it != objects.end(); ++it) list.append(Py::String((*it)->getNameInDocument())); extractTipsFromObject(inst, list, tips); } } } // These are the attributes from the type object extractTipsFromObject(obj, list, tips); } catch (Py::Exception& e) { // Just clear the Python exception e.clear(); } return tips; }
Py::Object RendererAgg::draw_text(const Py::Tuple& args) { _VERBOSE("RendererAgg::draw_text"); theRasterizer->reset_clipping(); args.verify_length(4); FT2Font *font = static_cast<FT2Font*>(args[0].ptr()); int x = Py::Int( args[1] ); int y = Py::Int( args[2] ); Py::Object gc = args[3]; Py::Object o ( gc.getAttr( "_cliprect" ) ); bool useClip = o.ptr()!=Py_None; double l = 0; double b = 0; double r = width; double t = height; if (useClip) { Py::SeqBase<Py::Object> rect( o ); l = Py::Float(rect[0]) ; b = Py::Float(rect[1]) ; double w = Py::Float(rect[2]) ; double h = Py::Float(rect[3]) ; r = l+w; t = b+h; //std::cout << b << " " << h << " " << " " << t << std::endl; } agg::rgba color = get_color(gc); pixfmt::color_type p; p.r = int(255*color.r); p.b = int(255*color.b); p.g = int(255*color.g); p.a = int(255*color.a); //y = y-font->image.height; unsigned thisx, thisy; for (size_t i=0; i<font->image.width; ++i) { for (size_t j=0; j<font->image.height; ++j) { thisx = i+x+font->image.offsetx; thisy = j+y+font->image.offsety; if (thisx<l || thisx>=r) continue; if (thisy<height-t || thisy>=height-b) continue; pixFmt->blend_pixel (thisx, thisy, p, font->image.buffer[i + j*font->image.width]); } } /* bbox the text for debug purposes agg::path_storage path; path.move_to(x, y); path.line_to(x, y+font->image.height); path.line_to(x+font->image.width, y+font->image.height); path.line_to(x+font->image.width, y); path.close_polygon(); agg::rgba edgecolor(1,0,0,1); //now fill the edge agg::conv_stroke<agg::path_storage> stroke(path); stroke.width(1.0); rendererAA->color(edgecolor); //self->theRasterizer->gamma(agg::gamma_power(gamma)); theRasterizer->add_path(stroke); agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA); */ return Py::Object(); }
// this code is heavily adapted from the paint license, which is in // the file paint.license (BSD compatible) included in this // distribution. TODO, add license file to MANIFEST.in and CVS Py::Object RendererAgg::write_png(const Py::Tuple& args) { //small memory leak in this function - JDH 2004-06-08 _VERBOSE("RendererAgg::write_png"); args.verify_length(1); FILE *fp; Py::Object o = Py::Object(args[0]); bool fpclose = true; if (o.isString()) { std::string fileName = Py::String(o); const char *file_name = fileName.c_str(); fp = fopen(file_name, "wb"); } else { if ((fp = PyFile_AsFile(o.ptr())) == NULL) throw Py::TypeError("Could not convert object to file pointer"); fpclose = false; } png_structp png_ptr; png_infop info_ptr; struct png_color_8_struct sig_bit; png_uint_32 row; png_bytep row_pointers[height]; for (row = 0; row < height; ++row) { row_pointers[row] = pixBuffer + row * width * 4; } if (fp == NULL) throw Py::RuntimeError("could not open file"); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { if (fpclose) fclose(fp); throw Py::RuntimeError("could not create write struct"); } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { if (fpclose) fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); throw Py::RuntimeError("could not create info struct"); } if (setjmp(png_ptr->jmpbuf)) { if (fpclose) fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); throw Py::RuntimeError("error building image"); } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // this a a color image! sig_bit.gray = 0; sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; /* if the image has an alpha channel then */ sig_bit.alpha = 8; png_set_sBIT(png_ptr, info_ptr, &sig_bit); png_write_info(png_ptr, info_ptr); png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); /* Changed calls to png_destroy_write_struct to follow http://www.libpng.org/pub/png/libpng-manual.txt. This ensures the info_ptr memory is released. */ png_destroy_write_struct(&png_ptr, &info_ptr); if (fpclose) fclose(fp); return Py::Object(); }
Py::Object Transformation::numerix_x_y(const Py::Tuple & args) { _VERBOSE("Transformation::numerix_x_y"); args.verify_length(2); Py::Object xo = args[0]; Py::Object yo = args[1]; PyArrayObject *x = (PyArrayObject *) PyArray_ContiguousFromObject(xo.ptr(), PyArray_DOUBLE, 1, 1); if (x==NULL) throw Py::TypeError("Transformation::numerix_x_y expected numerix array"); PyArrayObject *y = (PyArrayObject *) PyArray_ContiguousFromObject(yo.ptr(), PyArray_DOUBLE, 1, 1); if (y==NULL) throw Py::TypeError("Transformation::numerix_x_y expected numerix array"); size_t Nx = x->dimensions[0]; size_t Ny = y->dimensions[0]; if (Nx!=Ny) throw Py::ValueError("x and y must be equal length sequences"); // evaluate the lazy objects if (!_frozen) eval_scalars(); int dimensions[1]; dimensions[0] = Nx; PyArrayObject *retx = (PyArrayObject *)PyArray_FromDims(1,dimensions,PyArray_DOUBLE); if (retx==NULL) { Py_XDECREF(x); Py_XDECREF(y); throw Py::RuntimeError("Could not create return x array"); } PyArrayObject *rety = (PyArrayObject *)PyArray_FromDims(1,dimensions,PyArray_DOUBLE); if (rety==NULL) { Py_XDECREF(x); Py_XDECREF(y); throw Py::RuntimeError("Could not create return x array"); } for (size_t i=0; i< Nx; ++i) { double thisx = *(double *)(x->data + i*x->strides[0]); double thisy = *(double *)(y->data + i*y->strides[0]); //std::cout << "calling operator " << thisx << " " << thisy << " " << std::endl; this->operator()(thisx, thisy); *(double *)(retx->data + i*retx->strides[0]) = xy.first; *(double *)(rety->data + i*rety->strides[0]) = xy.second; } Py_XDECREF(x); Py_XDECREF(y); Py::Tuple ret(2); ret[0] = Py::Object((PyObject*)retx); ret[1] = Py::Object((PyObject*)rety); Py_XDECREF(retx); Py_XDECREF(rety); return ret; }
Py::Object Bbox::update_numerix(const Py::Tuple &args) { //update the box from the numerix arrays x and y _VERBOSE("Bbox::update_numerix"); args.verify_length(3); Py::Object xo = args[0]; Py::Object yo = args[1]; PyArrayObject *x = (PyArrayObject *) PyArray_ContiguousFromObject(xo.ptr(), PyArray_DOUBLE, 1, 1); if (x==NULL) throw Py::TypeError("Bbox::update_numerix expected numerix array"); PyArrayObject *y = (PyArrayObject *) PyArray_ContiguousFromObject(yo.ptr(), PyArray_DOUBLE, 1, 1); if (y==NULL) throw Py::TypeError("Bbox::update_numerix expected numerix array"); size_t Nx = x->dimensions[0]; size_t Ny = y->dimensions[0]; if (Nx!=Ny) throw Py::ValueError("x and y must be equal length sequences"); //don't use current bounds when updating box if ignore==1 if (Nx==0) return Py::Object(); double minx = _ll->xval(); double maxx = _ur->xval(); double miny = _ll->yval(); double maxy = _ur->yval(); double thisx, thisy; int ignore = Py::Int(args[2]); if (ignore) { int xok=0; int yok=0; // loop through values until we find some nans... for (size_t i=0; i< Nx; ++i) { thisx = *(double *)(x->data + i*x->strides[0]); thisy = *(double *)(y->data + i*y->strides[0]); if (!xok) { if (!MPL_isnan64(thisx)) { minx=thisx; maxx=thisx; xok=1; } } if (!yok) { if (!MPL_isnan64(thisy)) { miny=thisy; maxy=thisy; yok=1; } } if (xok && yok) break; } } for (size_t i=0; i< Nx; ++i) { thisx = *(double *)(x->data + i*x->strides[0]); thisy = *(double *)(y->data + i*y->strides[0]); _posx.update(thisx); _posy.update(thisy); if (thisx<minx) minx=thisx; if (thisx>maxx) maxx=thisx; if (thisy<miny) miny=thisy; if (thisy>maxy) maxy=thisy; } Py_XDECREF(x); Py_XDECREF(y); _ll->x_api()->set_api(minx); _ll->y_api()->set_api(miny); _ur->x_api()->set_api(maxx); _ur->y_api()->set_api(maxy); return Py::Object(); }
PythonInterpreter::PythonInterpreter(Kross::InterpreterInfo* info) : Kross::Interpreter(info) , d(new PythonInterpreterPrivate()) { // Initialize the python interpreter. initialize(); // Set name of the program. Py_SetProgramName(const_cast<char*>("Kross")); /* // Set arguments. //char* comm[0]; const char* comm = const_cast<char*>("kross"); // name. PySys_SetArgv(1, comm); */ // In the python sys.path are all module-directories are // listed in. QString path; // First import the sys-module to remember it's sys.path // list in our path QString. Py::Module sysmod( PyImport_ImportModule( (char*)"sys" ), true ); Py::Dict sysmoddict = sysmod.getDict(); Py::Object syspath = sysmoddict.getItem("path"); if(syspath.isList()) { Py::List syspathlist = syspath; for(Py::List::iterator it = syspathlist.begin(); it != syspathlist.end(); ++it) { if( ! (*it).isString() ) continue; QString s = PythonType<QString>::toVariant(*it); path.append( s + PYPATHDELIMITER ); } } else path = Py_GetPath(); #if 0 // Determinate additional module-paths we like to add. // First add the global Kross modules-path. QStringList krossdirs = KGlobal::dirs()->findDirs("data", "kross/python"); for(QStringList::Iterator krossit = krossdirs.begin(); krossit != krossdirs.end(); ++krossit) path.append(*krossit + PYPATHDELIMITER); // Then add the application modules-path. QStringList appdirs = KGlobal::dirs()->findDirs("appdata", "kross/python"); for(QStringList::Iterator appit = appdirs.begin(); appit != appdirs.end(); ++appit) path.append(*appit + PYPATHDELIMITER); #endif // Set the extended sys.path. PySys_SetPath( (char*) path.toLatin1().data() ); #ifdef KROSS_PYTHON_INTERPRETER_DEBUG krossdebug(QString("Python ProgramName: %1").arg(Py_GetProgramName())); krossdebug(QString("Python ProgramFullPath: %1").arg(Py_GetProgramFullPath())); krossdebug(QString("Python Version: %1").arg(Py_GetVersion())); krossdebug(QString("Python Platform: %1").arg(Py_GetPlatform())); krossdebug(QString("Python Prefix: %1").arg(Py_GetPrefix())); krossdebug(QString("Python ExecPrefix: %1").arg(Py_GetExecPrefix())); //krossdebug(QString("Python Path: %1").arg(Py_GetPath())); //krossdebug(QString("Python System Path: %1").arg(path)); #endif // Initialize the main module. d->mainmodule = new PythonModule(this); // The main dictonary. Py::Dict moduledict = d->mainmodule->getDict(); //TODO moduledict["KrossPythonVersion"] = Py::Int(KROSS_PYTHON_VERSION); // Prepare the interpreter. QString s = //"# -*- coding: iso-8859-1 -*-\n" //"import locale\n" //"locale.setlocale(locale.LC_ALL, '')\n" //"# -*- coding: latin-1 -*\n" //"# -*- coding: utf-8 -*-\n" //"import locale\n" //"locale.setlocale(locale.LC_ALL, '')\n" //"from __future__ import absolute_import\n" "import sys\n" //"import os, os.path\n" //"sys.setdefaultencoding('latin-1')\n" // Dirty hack to get sys.argv defined. Needed for e.g. TKinter. "sys.argv = ['']\n" // On the try to read something from stdin always return an empty // string. That way such reads don't block our script. // Deactivated since sys.stdin has the encoding attribute needed // by e.g. LiquidWeather and those attr is missing in StringIO // and cause it's buildin we can't just add it but would need to // implement our own class. Grrrr, what a stupid design :-/ //"try:\n" //" import cStringIO\n" //" sys.stdin = cStringIO.StringIO()\n" //"except:\n" //" pass\n" // Class to redirect something. We use this class e.g. to redirect // <stdout> and <stderr> to a c++ event. //"class Redirect:\n" //" def __init__(self, target):\n" //" self.target = target\n" //" def write(self, s):\n" //" self.target.call(s)\n" // Wrap builtin __import__ method. All import requests are // first redirected to our PythonModule.import method and // if the call returns None, then we call the original // python import mechanism. "import __builtin__\n" "import __main__\n" "import traceback\n" "sys.modules['_oldmain'] = sys.modules['__main__']\n" "_main_builtin_import_ = __main__.__builtin__.__import__\n" "class _Importer:\n" " def __init__(self, script):\n" " self.script = script\n" " self.realImporter = __main__.__builtin__.__import__\n" " __main__.__builtin__.__import__ = self._import\n" " def _import(self, name, globals=None, locals=None, fromlist=[], level = -1):\n" //" try:\n" //" print \"1===========> _Importer name=%s fromlist=%s\" % (name,fromlist)\n" #if PY_MAJOR_VERSION >= 3 || (PY_MAJOR_VERSION >= 2 && PY_MINOR_VERSION >= 5) " mod = __main__._import(self.script, name, globals, locals, fromlist, level)\n" #else " mod = __main__._import(self.script, name, globals, locals, fromlist)\n" #endif " if mod == None:\n" " if name == 'qt':\n" " raise ImportError('Import of the PyQt3 module is not allowed. Please use PyQt4 instead.')\n" " if name == 'dcop':\n" " raise ImportError('Import of the KDE3 DCOP module is not allowed. Please use PyQt4 DBUS instead.')\n" #if PY_MAJOR_VERSION >= 3 || (PY_MAJOR_VERSION >= 2 && PY_MINOR_VERSION >= 5) " mod = self.realImporter(name, globals, locals, fromlist, level)\n" #else " mod = self.realImporter(name, globals, locals, fromlist)\n" #endif " if mod != None:\n" //" print \"3===========> _Importer name=%s fromlist=%s\" % (name,fromlist)\n" " if globals != None and (not fromlist or len(fromlist)==0 or '*' in fromlist):\n" " globals[name] = mod\n" " return mod\n" //" except ImportError:\n" //" except:\n" //" print \"9===========> _Importer Trying ImportError with name=%s fromlist=%s insysmodules=%s\" % (name,fromlist,name in sys.modules)\n" //" print \" \".join( traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) )\n" //" return None\n" /* " print \"_Importer name=%s fromlist=%s\" % (name,fromlist)\n" " if fromlist == None:\n" " mod = __main__._import(self.script, name, globals, locals, fromlist)\n" " if mod != None:\n" " print \"2===========> _Importer name=%s fromlist=%s\" % (name,fromlist)\n" " globals[name] = mod\n" " return mod\n" //" if name in sys.modules:\n" // hack to preserve module paths, needed e.g. for "import os.path" //" print \"3===========> _Importer name=%s fromlist=%s\" % (name,fromlist)\n" //" return sys.modules[name]\n" " print \"3===========> _Importer Trying realImporter with name=%s fromlist=%s insysmodules=%s\" % (name,fromlist,name in sys.modules)\n" " try:\n" " mod = self.realImporter(name, globals, locals, fromlist)\n" " print \"4===========> _Importer Trying realImporter with name=%s fromlist=%s insysmodules=%s module=%s\" % (name,fromlist,name in sys.modules,mod)\n" //" mod.__init__(name)\n" //" globals[name] = mod\n" //" sys.modules[name] = mod\n" " print \"5===========> _Importer Trying realImporter with name=%s fromlist=%s insysmodules=%s module=%s\" % (name,fromlist,name in sys.modules,mod)\n" " return mod\n" " except ImportError:\n" " print \"6===========> _Importer Trying ImportError with name=%s fromlist=%s insysmodules=%s\" % (name,fromlist,name in sys.modules)\n" " n = name.split('.')\n" " if len(n) >= 2:\n" " print \"7===========> _Importer Trying ImportError with name=%s fromlist=%s insysmodules=%s\" % (name,fromlist,name in sys.modules)\n" " m = self._import(\".\".join(n[:-1]),globals,locals,[n[-1],])\n" " print \"8===========> _Importer Trying ImportError with name=%s fromlist=%s insysmodules=%s\" % (name,fromlist,name in sys.modules)\n" " return self.realImporter(name, globals, locals, fromlist)\n" " print \"9===========> _Importer Trying ImportError with name=%s fromlist=%s insysmodules=%s\" % (name,fromlist,name in sys.modules)\n" " raise\n" */ ; PyObject* pyrun = PyRun_String(s.toLatin1().data(), Py_file_input, moduledict.ptr(), moduledict.ptr()); if(! pyrun) { Py::Object errobj = Py::value(Py::Exception()); // get last error setError( QString("Failed to prepare the __main__ module: %1").arg(errobj.as_string().c_str()) ); } Py_XDECREF(pyrun); // free the reference. }
Py::Object _image_module::pcolor2(const Py::Tuple& args) { _VERBOSE("_image_module::pcolor2"); if (args.length() != 7) throw Py::TypeError("Incorrect number of arguments (6 expected)"); Py::Object xp = args[0]; Py::Object yp = args[1]; Py::Object dp = args[2]; int rows = Py::Int(args[3]); int cols = Py::Int(args[4]); Py::Tuple bounds = args[5]; Py::Object bgp = args[6]; if (bounds.length() !=4) throw Py::TypeError("Incorrect number of bounds (4 expected)"); double x_left = Py::Float(bounds[0]); double x_right = Py::Float(bounds[1]); double y_bot = Py::Float(bounds[2]); double y_top = Py::Float(bounds[3]); // Check we have something to output to if (rows == 0 || cols ==0) throw Py::ValueError("rows or cols is zero; there are no pixels"); // Get numpy arrays PyArrayObject *x = (PyArrayObject *) PyArray_ContiguousFromObject(xp.ptr(), PyArray_DOUBLE, 1, 1); if (x == NULL) throw Py::ValueError("x is of incorrect type (wanted 1D double)"); PyArrayObject *y = (PyArrayObject *) PyArray_ContiguousFromObject(yp.ptr(), PyArray_DOUBLE, 1, 1); if (y == NULL) { Py_XDECREF(x); throw Py::ValueError("y is of incorrect type (wanted 1D double)"); } PyArrayObject *d = (PyArrayObject *) PyArray_ContiguousFromObject(dp.ptr(), PyArray_UBYTE, 3, 3); if (d == NULL) { Py_XDECREF(x); Py_XDECREF(y); throw Py::ValueError("data is of incorrect type (wanted 3D uint8)"); } if (d->dimensions[2] != 4) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); throw Py::ValueError("data must be in RGBA format"); } // Check dimensions match int nx = x->dimensions[0]; int ny = y->dimensions[0]; if (nx != d->dimensions[1]+1 || ny != d->dimensions[0]+1) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); throw Py::ValueError("data and axis bin boundary dimensions are incompatible"); } PyArrayObject *bg = (PyArrayObject *) PyArray_ContiguousFromObject(bgp.ptr(), PyArray_UBYTE, 1, 1); if (bg == NULL) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); throw Py::ValueError("bg is of incorrect type (wanted 1D uint8)"); } if (bg->dimensions[0] != 4) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); Py_XDECREF(bg); throw Py::ValueError("bg must be in RGBA format"); } // Allocate memory for pointer arrays int * irows = reinterpret_cast<int*>(PyMem_Malloc(sizeof(int)*rows)); if (irows == NULL) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); Py_XDECREF(bg); throw Py::MemoryError("Cannot allocate memory for lookup table"); } int * jcols = reinterpret_cast<int*>(PyMem_Malloc(sizeof(int*)*cols)); if (jcols == NULL) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); Py_XDECREF(bg); PyMem_Free(irows); throw Py::MemoryError("Cannot allocate memory for lookup table"); } // Create output Image* imo = new Image; imo->rowsIn = rows; imo->rowsOut = rows; imo->colsIn = cols; imo->colsOut = cols; size_t NUMBYTES(rows * cols * 4); agg::int8u *buffer = new agg::int8u[NUMBYTES]; if (buffer == NULL) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); Py_XDECREF(bg); PyMem_Free(irows); PyMem_Free(jcols); throw Py::MemoryError("Could not allocate memory for image"); } // Calculate the pointer arrays to map input x to output x int i, j; double *x0 = reinterpret_cast<double*>(x->data); double *y0 = reinterpret_cast<double*>(y->data); double sx = cols/(x_right - x_left); double sy = rows/(y_top - y_bot); _bin_indices(jcols, cols, x0, nx, sx, x_left); _bin_indices(irows, rows, y0, ny, sy, y_bot); // Copy data to output buffer agg::int8u * position = buffer; unsigned char *start = reinterpret_cast<unsigned char*>(d->data); unsigned char *bgptr = reinterpret_cast<unsigned char*>(bg->data); int s0 = d->strides[0]; int s1 = d->strides[1]; for (i=0; i<rows; i++) { for (j=0; j<cols; j++) { if (irows[i] == -1 || jcols[j] == -1) { memcpy(position, bgptr, 4*sizeof(agg::int8u)); } else { memcpy(position, (start + s0*irows[i] + s1*jcols[j]), 4*sizeof(agg::int8u)); } position += 4; } } // Attach output buffer to output buffer imo->rbufOut = new agg::rendering_buffer; imo->bufferOut = buffer; imo->rbufOut->attach(imo->bufferOut, imo->colsOut, imo->rowsOut, imo->colsOut * imo->BPP); Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); Py_XDECREF(bg); PyMem_Free(irows); PyMem_Free(jcols); return Py::asObject(imo); }
Py::Object _image_module::pcolor(const Py::Tuple& args) { _VERBOSE("_image_module::pcolor"); if (args.length() != 6) throw Py::TypeError("Incorrect number of arguments (6 expected)"); Py::Object xp = args[0]; Py::Object yp = args[1]; Py::Object dp = args[2]; unsigned int rows = Py::Int(args[3]); unsigned int cols = Py::Int(args[4]); Py::Tuple bounds = args[5]; if (bounds.length() !=4) throw Py::TypeError("Incorrect number of bounds (4 expected)"); float x_min = Py::Float(bounds[0]); float x_max = Py::Float(bounds[1]); float y_min = Py::Float(bounds[2]); float y_max = Py::Float(bounds[3]); float width = x_max - x_min; float height = y_max - y_min; float dx = width / ((float) cols); float dy = height / ((float) rows); // Check we have something to output to if (rows == 0 || cols ==0) throw Py::ValueError("Cannot scale to zero size"); // Get numpy arrays PyArrayObject *x = (PyArrayObject *) PyArray_ContiguousFromObject(xp.ptr(), PyArray_FLOAT, 1, 1); if (x == NULL) throw Py::ValueError("x is of incorrect type (wanted 1D float)"); PyArrayObject *y = (PyArrayObject *) PyArray_ContiguousFromObject(yp.ptr(), PyArray_FLOAT, 1, 1); if (y == NULL) { Py_XDECREF(x); throw Py::ValueError("y is of incorrect type (wanted 1D float)"); } PyArrayObject *d = (PyArrayObject *) PyArray_ContiguousFromObject(dp.ptr(), PyArray_UBYTE, 3, 3); if (d == NULL) { Py_XDECREF(x); Py_XDECREF(y); throw Py::ValueError("data is of incorrect type (wanted 3D UInt8)"); } if (d->dimensions[2] != 4) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); throw Py::ValueError("data must be in RGBA format"); } // Check dimensions match int nx = x->dimensions[0]; int ny = y->dimensions[0]; if (nx != d->dimensions[1] || ny != d->dimensions[0]) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); throw Py::ValueError("data and axis dimensions do not match"); } // Allocate memory for pointer arrays unsigned int * rowstarts = reinterpret_cast<unsigned int*>(PyMem_Malloc(sizeof(unsigned int)*rows)); if (rowstarts == NULL) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); throw Py::MemoryError("Cannot allocate memory for lookup table"); } unsigned int * colstarts = reinterpret_cast<unsigned int*>(PyMem_Malloc(sizeof(unsigned int*)*cols)); if (colstarts == NULL) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); PyMem_Free(rowstarts); throw Py::MemoryError("Cannot allocate memory for lookup table"); } // Create output Image* imo = new Image; imo->rowsIn = rows; imo->colsIn = cols; imo->rowsOut = rows; imo->colsOut = cols; size_t NUMBYTES(rows * cols * 4); agg::int8u *buffer = new agg::int8u[NUMBYTES]; if (buffer == NULL) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); PyMem_Free(rowstarts); PyMem_Free(colstarts); throw Py::MemoryError("Could not allocate memory for image"); } // Calculate the pointer arrays to map input x to output x unsigned int i, j, j_last; unsigned int * colstart = colstarts; unsigned int * rowstart = rowstarts; float *xs1 = reinterpret_cast<float*>(x->data); float *ys1 = reinterpret_cast<float*>(y->data); float *xs2 = xs1+1; float *ys2 = ys1+1; float *xl = xs1 + nx - 1; float *yl = ys1 + ny - 1; float xo = x_min + dx/2.0; float yo = y_min + dy/2.0; float xm = 0.5*(*xs1 + *xs2); float ym = 0.5*(*ys1 + *ys2); // x/cols j = 0; j_last = j; for (i=0;i<cols;i++,xo+=dx,colstart++) { while(xs2 != xl && xo > xm) { xs1 = xs2; xs2 = xs1+1; xm = 0.5*(*xs1 + *xs2); j++; } *colstart = j - j_last; j_last = j; } // y/rows j = 0; j_last = j; for (i=0;i<rows;i++,yo+=dy,rowstart++) { while(ys2 != yl && yo > ym) { ys1 = ys2; ys2 = ys1+1; ym = 0.5*(*ys1 + *ys2); j++; } *rowstart = j - j_last; j_last = j; } // Copy data to output buffer unsigned char *start; unsigned char *inposition; size_t inrowsize(nx*4); size_t rowsize(cols*4); rowstart = rowstarts; agg::int8u * position = buffer; agg::int8u * oldposition = NULL; start = reinterpret_cast<unsigned char*>(d->data); for(i=0;i<rows;i++,rowstart++) { if (i > 0 && *rowstart == 0) { memcpy(position, oldposition, rowsize*sizeof(agg::int8u)); oldposition = position; position += rowsize; } else { oldposition = position; start += *rowstart * inrowsize; inposition = start; for(j=0,colstart=colstarts;j<cols;j++,position+=4,colstart++) { inposition += *colstart * 4; memcpy(position, inposition, 4*sizeof(agg::int8u)); } } } // Attatch output buffer to output buffer imo->rbufOut = new agg::rendering_buffer; imo->bufferOut = buffer; imo->rbufOut->attach(imo->bufferOut, imo->colsOut, imo->rowsOut, imo->colsOut * imo->BPP); Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(d); PyMem_Free(rowstarts); PyMem_Free(colstarts); return Py::asObject(imo); }
Py::Object _image_module::frombyte(const Py::Tuple& args) { _VERBOSE("_image_module::frombyte"); args.verify_length(2); Py::Object x = args[0]; int isoutput = Py::Int(args[1]); PyArrayObject *A = (PyArrayObject *) PyArray_ContiguousFromObject(x.ptr(), PyArray_UBYTE, 3, 3); if (A == NULL) throw Py::ValueError("Array must have 3 dimensions"); if (A->dimensions[2]<3 || A->dimensions[2]>4) throw Py::ValueError("Array dimension 3 must have size 3 or 4"); Image* imo = new Image; imo->rowsIn = A->dimensions[0]; imo->colsIn = A->dimensions[1]; agg::int8u *arrbuf; agg::int8u *buffer; arrbuf = reinterpret_cast<agg::int8u *>(A->data); size_t NUMBYTES(imo->colsIn * imo->rowsIn * imo->BPP); buffer = new agg::int8u[NUMBYTES]; if (buffer==NULL) //todo: also handle allocation throw throw Py::MemoryError("_image_module::frombyte could not allocate memory"); const size_t N = imo->rowsIn * imo->colsIn * imo->BPP; size_t i = 0; if (A->dimensions[2] == 4) { memmove(buffer, arrbuf, N); } else { while (i < N) { memmove(buffer, arrbuf, 3); buffer += 3; arrbuf += 3; *buffer++ = 255; i += 4; } buffer -= N; arrbuf -= imo->rowsIn * imo->colsIn; } Py_XDECREF(A); if (isoutput) { // make the output buffer point to the input buffer imo->rowsOut = imo->rowsIn; imo->colsOut = imo->colsIn; imo->rbufOut = new agg::rendering_buffer; imo->bufferOut = buffer; imo->rbufOut->attach(imo->bufferOut, imo->colsOut, imo->rowsOut, imo->colsOut * imo->BPP); } else { imo->bufferIn = buffer; imo->rbufIn = new agg::rendering_buffer; imo->rbufIn->attach(buffer, imo->colsIn, imo->rowsIn, imo->colsIn*imo->BPP); } return Py::asObject( imo ); }
Py::Object Transformation::nonlinear_only_numerix(const Py::Tuple & args, const Py::Dict &kwargs) { _VERBOSE("Transformation::nonlinear_only_numerix"); args.verify_length(2); int returnMask = false; if (kwargs.hasKey("returnMask")) { returnMask = Py::Int(kwargs["returnMask"]); } Py::Object xo = args[0]; Py::Object yo = args[1]; PyArrayObject *x = (PyArrayObject *) PyArray_ContiguousFromObject(xo.ptr(), PyArray_DOUBLE, 1, 1); if (x==NULL) throw Py::TypeError("Transformation::nonlinear_only_numerix expected numerix array"); PyArrayObject *y = (PyArrayObject *) PyArray_ContiguousFromObject(yo.ptr(), PyArray_DOUBLE, 1, 1); if (y==NULL) throw Py::TypeError("Transformation::nonlinear_only_numerix expected numerix array"); size_t Nx = x->dimensions[0]; size_t Ny = y->dimensions[0]; if (Nx!=Ny) throw Py::ValueError("x and y must be equal length sequences"); int dimensions[1]; dimensions[0] = Nx; PyArrayObject *retx = (PyArrayObject *)PyArray_FromDims(1,dimensions,PyArray_DOUBLE); if (retx==NULL) { Py_XDECREF(x); Py_XDECREF(y); throw Py::RuntimeError("Could not create return x array"); } PyArrayObject *rety = (PyArrayObject *)PyArray_FromDims(1,dimensions,PyArray_DOUBLE); if (rety==NULL) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(retx); throw Py::RuntimeError("Could not create return x array"); } PyArrayObject *retmask = NULL; if (returnMask) { retmask = (PyArrayObject *)PyArray_FromDims(1,dimensions,PyArray_UBYTE); if (retmask==NULL) { Py_XDECREF(x); Py_XDECREF(y); Py_XDECREF(retx); Py_XDECREF(rety); throw Py::RuntimeError("Could not create return mask array"); } } for (size_t i=0; i< Nx; ++i) { double thisx = *(double *)(x->data + i*x->strides[0]); double thisy = *(double *)(y->data + i*y->strides[0]); try { this->nonlinear_only_api(&thisx, &thisy); } catch(...) { if (returnMask) { *(unsigned char *)(retmask->data + i*retmask->strides[0]) = 0; *(double *)(retx->data + i*retx->strides[0]) = 0.0; *(double *)(rety->data + i*rety->strides[0]) = 0.0; continue; } else { throw Py::ValueError("Domain error on this->nonlinear_only_api(&thisx, &thisy) in Transformation::nonlinear_only_numerix"); } } *(double *)(retx->data + i*retx->strides[0]) = thisx; *(double *)(rety->data + i*rety->strides[0]) = thisy; if (returnMask) { *(unsigned char *)(retmask->data + i*retmask->strides[0]) = 1; } } Py_XDECREF(x); Py_XDECREF(y); if (returnMask) { Py::Tuple ret(3); ret[0] = Py::Object((PyObject*)retx); ret[1] = Py::Object((PyObject*)rety); ret[2] = Py::Object((PyObject*)retmask); Py_XDECREF(retx); Py_XDECREF(rety); Py_XDECREF(retmask); return ret; } else { Py::Tuple ret(2); ret[0] = Py::Object((PyObject*)retx); ret[1] = Py::Object((PyObject*)rety); Py_XDECREF(retx); Py_XDECREF(rety); return ret; } }