Rev 2601 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1405 | subik | 1 | #include "objimageexport.h" |
2 | #include "cmdutil.h" |
||
3 | |||
4 | #include <structmember.h> |
||
5 | #include <qfileinfo.h> |
||
6 | #include <vector> |
||
7 | |||
8 | typedef struct |
||
9 | { |
||
10 | PyObject_HEAD |
||
11 | PyObject *name; // string - filename |
||
12 | PyObject *type; // string - image type (PNG, JPEG etc.) |
||
13 | PyObject *allTypes; // list - available types |
||
14 | int dpi; // DPI of the bitmap |
||
15 | int scale; // how is bitmap scaled 100 = 100% |
||
16 | int quality; // quality/compression <1; 100> |
||
17 | } ImageExport; |
||
18 | |||
19 | |||
20 | static void ImageExport_dealloc(ImageExport* self) |
||
21 | { |
||
22 | Py_XDECREF(self->name); |
||
23 | Py_XDECREF(self->type); |
||
24 | Py_XDECREF(self->allTypes); |
||
25 | self->ob_type->tp_free((PyObject *)self); |
||
26 | } |
||
27 | |||
28 | static PyObject * ImageExport_new(PyTypeObject *type, PyObject *args, PyObject *kwds) |
||
29 | { |
||
30 | if(!checkHaveDocument()) |
||
31 | return NULL; |
||
32 | |||
33 | ImageExport *self; |
||
34 | self = (ImageExport *)type->tp_alloc(type, 0); |
||
35 | if (self != NULL) { |
||
2587 | subik | 36 | self->name = PyString_FromString("ImageExport.png"); |
1405 | subik | 37 | self->type = PyString_FromString("PNG"); |
38 | self->allTypes = PyList_New(0); |
||
39 | self->dpi = 72; |
||
40 | self->scale = 100; |
||
41 | self->quality = 100; |
||
42 | } |
||
43 | return (PyObject *) self; |
||
44 | } |
||
45 | |||
46 | static int ImageExport_init(ImageExport *self, PyObject *args, PyObject *kwds) |
||
47 | { |
||
48 | return 0; |
||
49 | } |
||
50 | |||
51 | static PyMemberDef ImageExport_members[] = { |
||
52 | {const_cast<char*>("dpi"), T_INT, offsetof(ImageExport, dpi), 0, imgexp_dpi__doc__}, |
||
53 | {const_cast<char*>("scale"), T_INT, offsetof(ImageExport, scale), 0, imgexp_scale__doc__}, |
||
54 | {const_cast<char*>("quality"), T_INT, offsetof(ImageExport, quality), 0, imgexp_quality__doc__}, |
||
55 | {NULL, 0, 0, 0, NULL} // sentinel |
||
56 | }; |
||
57 | |||
58 | static PyObject *ImageExport_getName(ImageExport *self, void *closure) |
||
59 | { |
||
60 | Py_INCREF(self->name); |
||
61 | return self->name; |
||
62 | } |
||
63 | |||
64 | static int ImageExport_setName(ImageExport *self, PyObject *value, void *closure) |
||
65 | { |
||
66 | if (!PyString_Check(value)) { |
||
67 | PyErr_SetString(PyExc_TypeError, QObject::tr("The filename must be a string.", "python error")); |
||
68 | return -1; |
||
69 | } |
||
2587 | subik | 70 | if (PyString_Size(value) < 1) |
71 | { |
||
72 | PyErr_SetString(PyExc_TypeError, "The filename should not be empty string."); |
||
73 | return -1; |
||
74 | } |
||
1405 | subik | 75 | Py_DECREF(self->name); |
76 | Py_INCREF(value); |
||
77 | self->name = value; |
||
78 | return 0; |
||
79 | } |
||
80 | |||
81 | static PyObject *ImageExport_getType(ImageExport *self, void *closure) |
||
82 | { |
||
83 | Py_INCREF(self->type); |
||
84 | return self->type; |
||
85 | } |
||
86 | |||
87 | static int ImageExport_setType(ImageExport *self, PyObject *value, void *closure) |
||
88 | { |
||
89 | if (value == NULL) { |
||
90 | PyErr_SetString(PyExc_TypeError, QObject::tr("Cannot delete image type settings.", "python error")); |
||
91 | return -1; |
||
92 | } |
||
93 | if (!PyString_Check(value)) { |
||
94 | PyErr_SetString(PyExc_TypeError, QObject::tr("The image type must be a string.", "python error")); |
||
95 | return -1; |
||
96 | } |
||
97 | Py_DECREF(self->type); |
||
98 | Py_INCREF(value); |
||
99 | self->type = value; |
||
100 | return 0; |
||
101 | } |
||
102 | |||
103 | static PyObject *ImageExport_getAllTypes(ImageExport *self, void *closure) |
||
104 | { |
||
105 | PyObject *l; |
||
106 | int pos = 0; |
||
107 | QStringList list = QImage::outputFormatList(); |
||
108 | l = PyList_New(list.count()); |
||
109 | for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) |
||
110 | { |
||
111 | PyList_SetItem(l, pos, PyString_FromString((*it).latin1())); |
||
112 | ++pos; |
||
113 | } |
||
114 | return l; |
||
115 | } |
||
116 | |||
117 | static int ImageExport_setAllTypes(ImageExport *self, PyObject *value, void *closure) |
||
118 | { |
||
119 | PyErr_SetString(PyExc_ValueError, QObject::tr("'allTypes' attribute is READ-ONLY", "python error")); |
||
120 | return -1; |
||
121 | } |
||
122 | |||
123 | static PyGetSetDef ImageExport_getseters [] = { |
||
124 | {const_cast<char*>("name"), (getter)ImageExport_getName, (setter)ImageExport_setName, imgexp_filename__doc__, NULL}, |
||
125 | {const_cast<char*>("type"), (getter)ImageExport_getType, (setter)ImageExport_setType, imgexp_type__doc__, NULL}, |
||
126 | {const_cast<char*>("allTypes"), (getter)ImageExport_getAllTypes, (setter)ImageExport_setAllTypes, imgexp_alltypes__doc__, NULL}, |
||
127 | {NULL, NULL, NULL, NULL, NULL} // sentinel |
||
128 | }; |
||
129 | |||
130 | static PyObject *ImageExport_save(ImageExport *self) |
||
131 | { |
||
132 | if(!checkHaveDocument()) |
||
133 | return NULL; |
||
2584 | subik | 134 | |
2611 | subik | 135 | /* a little magic here - I need to compute the "maxGr" value... |
136 | * We need to know the right size of the page for landscape, |
||
137 | * portrait and user defined sizes. |
||
138 | */ |
||
139 | double pixmapSize; |
||
140 | (Carrier->doc->PageH > Carrier->doc->PageB) |
||
141 | ? pixmapSize = Carrier->doc->PageH |
||
142 | : pixmapSize = Carrier->doc->PageB; |
||
143 | QPixmap pixmap = Carrier->view->PageToPixmap(Carrier->doc->ActPage->PageNr, qRound(pixmapSize * self->scale * (self->dpi / 72.0) / 100.0)); |
||
1405 | subik | 144 | QImage im = pixmap.convertToImage(); |
2584 | subik | 145 | int dpm = qRound(100.0 / 2.54 * self->dpi); |
146 | im.setDotsPerMeterY(dpm); |
||
147 | im.setDotsPerMeterX(dpm); |
||
148 | if (!im.save(PyString_AsString(self->name), PyString_AsString(self->type), self->quality)) |
||
1405 | subik | 149 | { |
150 | PyErr_SetString(ScribusException, QObject::tr("Failed to export image", "python error")); |
||
151 | return NULL; |
||
152 | } |
||
153 | Py_INCREF(Py_True); // return True not None for backward compat |
||
154 | return Py_True; |
||
155 | } |
||
156 | |||
157 | static PyObject *ImageExport_saveAs(ImageExport *self, PyObject *args) |
||
158 | { |
||
159 | char* value; |
||
160 | if(!checkHaveDocument()) |
||
161 | return NULL; |
||
162 | if (!PyArg_ParseTuple(args, "es", "utf-8", &value)) |
||
163 | return NULL; |
||
2611 | subik | 164 | |
165 | /* a little magic here - I need to compute the "maxGr" value... |
||
166 | * We need to know the right size of the page for landscape, |
||
167 | * portrait and user defined sizes. |
||
168 | */ |
||
169 | double pixmapSize; |
||
170 | (Carrier->doc->PageH > Carrier->doc->PageB) |
||
171 | ? pixmapSize = Carrier->doc->PageH |
||
172 | : pixmapSize = Carrier->doc->PageB; |
||
173 | QPixmap pixmap = Carrier->view->PageToPixmap(Carrier->doc->ActPage->PageNr, qRound(pixmapSize * self->scale * (self->dpi / 72.0) / 100.0)); |
||
1405 | subik | 174 | QImage im = pixmap.convertToImage(); |
2601 | subik | 175 | int dpm = qRound(100.0 / 2.54 * self->dpi); |
176 | im.setDotsPerMeterY(dpm); |
||
177 | im.setDotsPerMeterX(dpm); |
||
2584 | subik | 178 | if (!im.save(value, PyString_AsString(self->type), self->quality)) |
1405 | subik | 179 | { |
180 | PyErr_SetString(ScribusException, QObject::tr("Failed to export image", "python error")); |
||
181 | return NULL; |
||
182 | } |
||
183 | Py_INCREF(Py_True); // return True not None for backward compat |
||
184 | return Py_True; |
||
185 | } |
||
186 | |||
187 | static PyMethodDef ImageExport_methods[] = { |
||
188 | {const_cast<char*>("save"), (PyCFunction)ImageExport_save, METH_NOARGS, imgexp_save__doc__}, |
||
189 | {const_cast<char*>("saveAs"), (PyCFunction)ImageExport_saveAs, METH_VARARGS, imgexp_saveas__doc__}, |
||
190 | {NULL, (PyCFunction)(0), 0, NULL} // sentinel |
||
191 | }; |
||
192 | |||
193 | PyTypeObject ImageExport_Type = { |
||
194 | PyObject_HEAD_INIT(NULL) // PyObject_VAR_HEAD |
||
195 | 0, |
||
196 | const_cast<char*>("ImageExport"), // char *tp_name; /* For printing, in format "<module>.<name>" */ |
||
197 | sizeof(ImageExport), // int tp_basicsize, /* For allocation */ |
||
198 | 0, // int tp_itemsize; /* For allocation */ |
||
199 | (destructor) ImageExport_dealloc, // destructor tp_dealloc; |
||
200 | 0, // printfunc tp_print; |
||
201 | 0, // getattrfunc tp_getattr; |
||
202 | 0, // setattrfunc tp_setattr; |
||
203 | 0, // cmpfunc tp_compare; |
||
204 | 0, // reprfunc tp_repr; |
||
205 | 0, // PyNumberMethods *tp_as_number; |
||
206 | 0, // PySequenceMethods *tp_as_sequence; |
||
207 | 0, // PyMappingMethods *tp_as_mapping; |
||
208 | 0, // hashfunc tp_hash; |
||
209 | 0, // ternaryfunc tp_call; |
||
210 | 0, // reprfunc tp_str; |
||
211 | 0, // getattrofunc tp_getattro; |
||
212 | 0, // setattrofunc tp_setattro; |
||
213 | 0, // PyBufferProcs *tp_as_buffer; |
||
214 | Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, // long tp_flags; |
||
215 | imgexp__doc__, // char *tp_doc; /* Documentation string */ |
||
216 | 0, // traverseproc tp_traverse; |
||
217 | 0, // inquiry tp_clear; |
||
218 | 0, // richcmpfunc tp_richcompare; |
||
219 | 0, // long tp_weaklistoffset; |
||
220 | 0, // getiterfunc tp_iter; |
||
221 | 0, // iternextfunc tp_iternext; |
||
222 | ImageExport_methods, // struct PyMethodDef *tp_methods; |
||
223 | ImageExport_members, // struct PyMemberDef *tp_members; |
||
224 | ImageExport_getseters, // struct PyGetSetDef *tp_getset; |
||
225 | 0, // struct _typeobject *tp_base; |
||
226 | 0, // PyObject *tp_dict; |
||
227 | 0, // descrgetfunc tp_descr_get; |
||
228 | 0, // descrsetfunc tp_descr_set; |
||
229 | 0, // long tp_dictoffset; |
||
230 | (initproc)ImageExport_init, // initproc tp_init; |
||
231 | 0, // allocfunc tp_alloc; |
||
232 | ImageExport_new, // newfunc tp_new; |
||
233 | 0, // freefunc tp_free; /* Low-level free-memory routine */ |
||
234 | 0, // inquiry tp_is_gc; /* For PyObject_IS_GC */ |
||
235 | 0, // PyObject *tp_bases; |
||
236 | 0, // PyObject *tp_mro; /* method resolution order */ |
||
237 | 0, // PyObject *tp_cache; |
||
238 | 0, // PyObject *tp_subclasses; |
||
239 | 0, // PyObject *tp_weaklist; |
||
240 | 0, // destructor tp_del; |
||
241 | |||
242 | #ifdef COUNT_ALLOCS |
||
243 | /* these must be last and never explicitly initialized */ |
||
244 | // int tp_allocs; |
||
245 | // int tp_frees; |
||
246 | // int tp_maxalloc; |
||
247 | // struct _typeobject *tp_next; |
||
248 | #endif |
||
249 | }; |