map.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * The Python Imaging Library.
  3. *
  4. * standard memory mapping interface for the Imaging library
  5. *
  6. * history:
  7. * 1998-03-05 fl added Win32 read mapping
  8. * 1999-02-06 fl added "I;16" support
  9. * 2003-04-21 fl added PyImaging_MapBuffer primitive
  10. *
  11. * Copyright (c) 1998-2003 by Secret Labs AB.
  12. * Copyright (c) 2003 by Fredrik Lundh.
  13. *
  14. * See the README file for information on usage and redistribution.
  15. */
  16. /*
  17. * FIXME: should move the memory mapping primitives into libImaging!
  18. */
  19. #include "Python.h"
  20. #include "Imaging.h"
  21. #include "py3.h"
  22. /* compatibility wrappers (defined in _imaging.c) */
  23. extern int PyImaging_CheckBuffer(PyObject* buffer);
  24. extern int PyImaging_GetBuffer(PyObject* buffer, Py_buffer *view);
  25. /* -------------------------------------------------------------------- */
  26. /* Standard mapper */
  27. typedef struct {
  28. PyObject_HEAD
  29. char* base;
  30. int size;
  31. int offset;
  32. #ifdef _WIN32
  33. HANDLE hFile;
  34. HANDLE hMap;
  35. #endif
  36. } ImagingMapperObject;
  37. static PyTypeObject ImagingMapperType;
  38. ImagingMapperObject*
  39. PyImaging_MapperNew(const char* filename, int readonly)
  40. {
  41. ImagingMapperObject *mapper;
  42. if (PyType_Ready(&ImagingMapperType) < 0)
  43. return NULL;
  44. mapper = PyObject_New(ImagingMapperObject, &ImagingMapperType);
  45. if (mapper == NULL)
  46. return NULL;
  47. mapper->base = NULL;
  48. mapper->size = mapper->offset = 0;
  49. #ifdef _WIN32
  50. mapper->hFile = (HANDLE)-1;
  51. mapper->hMap = (HANDLE)-1;
  52. /* FIXME: currently supports readonly mappings only */
  53. mapper->hFile = CreateFile(
  54. filename,
  55. GENERIC_READ,
  56. FILE_SHARE_READ,
  57. NULL, OPEN_EXISTING,
  58. FILE_ATTRIBUTE_NORMAL,
  59. NULL);
  60. if (mapper->hFile == (HANDLE)-1) {
  61. PyErr_SetString(PyExc_IOError, "cannot open file");
  62. Py_DECREF(mapper);
  63. return NULL;
  64. }
  65. mapper->hMap = CreateFileMapping(
  66. mapper->hFile, NULL,
  67. PAGE_READONLY,
  68. 0, 0, NULL);
  69. if (mapper->hMap == (HANDLE)-1) {
  70. CloseHandle(mapper->hFile);
  71. PyErr_SetString(PyExc_IOError, "cannot map file");
  72. Py_DECREF(mapper);
  73. return NULL;
  74. }
  75. mapper->base = (char*) MapViewOfFile(
  76. mapper->hMap,
  77. FILE_MAP_READ,
  78. 0, 0, 0);
  79. mapper->size = GetFileSize(mapper->hFile, 0);
  80. #endif
  81. return mapper;
  82. }
  83. static void
  84. mapping_dealloc(ImagingMapperObject* mapper)
  85. {
  86. #ifdef _WIN32
  87. if (mapper->base != 0)
  88. UnmapViewOfFile(mapper->base);
  89. if (mapper->hMap != (HANDLE)-1)
  90. CloseHandle(mapper->hMap);
  91. if (mapper->hFile != (HANDLE)-1)
  92. CloseHandle(mapper->hFile);
  93. mapper->base = 0;
  94. mapper->hMap = mapper->hFile = (HANDLE)-1;
  95. #endif
  96. PyObject_Del(mapper);
  97. }
  98. /* -------------------------------------------------------------------- */
  99. /* standard file operations */
  100. static PyObject*
  101. mapping_read(ImagingMapperObject* mapper, PyObject* args)
  102. {
  103. PyObject* buf;
  104. int size = -1;
  105. if (!PyArg_ParseTuple(args, "|i", &size))
  106. return NULL;
  107. /* check size */
  108. if (size < 0 || mapper->offset + size > mapper->size)
  109. size = mapper->size - mapper->offset;
  110. if (size < 0)
  111. size = 0;
  112. buf = PyBytes_FromStringAndSize(NULL, size);
  113. if (!buf)
  114. return NULL;
  115. if (size > 0) {
  116. memcpy(PyBytes_AsString(buf), mapper->base + mapper->offset, size);
  117. mapper->offset += size;
  118. }
  119. return buf;
  120. }
  121. static PyObject*
  122. mapping_seek(ImagingMapperObject* mapper, PyObject* args)
  123. {
  124. int offset;
  125. int whence = 0;
  126. if (!PyArg_ParseTuple(args, "i|i", &offset, &whence))
  127. return NULL;
  128. switch (whence) {
  129. case 0: /* SEEK_SET */
  130. mapper->offset = offset;
  131. break;
  132. case 1: /* SEEK_CUR */
  133. mapper->offset += offset;
  134. break;
  135. case 2: /* SEEK_END */
  136. mapper->offset = mapper->size + offset;
  137. break;
  138. default:
  139. /* FIXME: raise ValueError? */
  140. break;
  141. }
  142. Py_INCREF(Py_None);
  143. return Py_None;
  144. }
  145. /* -------------------------------------------------------------------- */
  146. /* map entire image */
  147. extern PyObject*PyImagingNew(Imaging im);
  148. static void
  149. ImagingDestroyMap(Imaging im)
  150. {
  151. return; /* nothing to do! */
  152. }
  153. static PyObject*
  154. mapping_readimage(ImagingMapperObject* mapper, PyObject* args)
  155. {
  156. int y, size;
  157. Imaging im;
  158. char* mode;
  159. int xsize;
  160. int ysize;
  161. int stride;
  162. int orientation;
  163. if (!PyArg_ParseTuple(args, "s(ii)ii", &mode, &xsize, &ysize,
  164. &stride, &orientation))
  165. return NULL;
  166. if (stride <= 0) {
  167. /* FIXME: maybe we should call ImagingNewPrologue instead */
  168. if (!strcmp(mode, "L") || !strcmp(mode, "P"))
  169. stride = xsize;
  170. else if (!strcmp(mode, "I;16") || !strcmp(mode, "I;16B"))
  171. stride = xsize * 2;
  172. else
  173. stride = xsize * 4;
  174. }
  175. size = ysize * stride;
  176. if (mapper->offset + size > mapper->size) {
  177. PyErr_SetString(PyExc_IOError, "image file truncated");
  178. return NULL;
  179. }
  180. im = ImagingNewPrologue(mode, xsize, ysize);
  181. if (!im)
  182. return NULL;
  183. /* setup file pointers */
  184. if (orientation > 0)
  185. for (y = 0; y < ysize; y++)
  186. im->image[y] = mapper->base + mapper->offset + y * stride;
  187. else
  188. for (y = 0; y < ysize; y++)
  189. im->image[ysize-y-1] = mapper->base + mapper->offset + y * stride;
  190. im->destroy = ImagingDestroyMap;
  191. mapper->offset += size;
  192. return PyImagingNew(im);
  193. }
  194. static struct PyMethodDef methods[] = {
  195. /* standard file interface */
  196. {"read", (PyCFunction)mapping_read, 1},
  197. {"seek", (PyCFunction)mapping_seek, 1},
  198. /* extensions */
  199. {"readimage", (PyCFunction)mapping_readimage, 1},
  200. {NULL, NULL} /* sentinel */
  201. };
  202. static PyTypeObject ImagingMapperType = {
  203. PyVarObject_HEAD_INIT(NULL, 0)
  204. "ImagingMapper", /*tp_name*/
  205. sizeof(ImagingMapperObject), /*tp_size*/
  206. 0, /*tp_itemsize*/
  207. /* methods */
  208. (destructor)mapping_dealloc, /*tp_dealloc*/
  209. 0, /*tp_print*/
  210. 0, /*tp_getattr*/
  211. 0, /*tp_setattr*/
  212. 0, /*tp_compare*/
  213. 0, /*tp_repr*/
  214. 0, /*tp_as_number */
  215. 0, /*tp_as_sequence */
  216. 0, /*tp_as_mapping */
  217. 0, /*tp_hash*/
  218. 0, /*tp_call*/
  219. 0, /*tp_str*/
  220. 0, /*tp_getattro*/
  221. 0, /*tp_setattro*/
  222. 0, /*tp_as_buffer*/
  223. Py_TPFLAGS_DEFAULT, /*tp_flags*/
  224. 0, /*tp_doc*/
  225. 0, /*tp_traverse*/
  226. 0, /*tp_clear*/
  227. 0, /*tp_richcompare*/
  228. 0, /*tp_weaklistoffset*/
  229. 0, /*tp_iter*/
  230. 0, /*tp_iternext*/
  231. methods, /*tp_methods*/
  232. 0, /*tp_members*/
  233. 0, /*tp_getset*/
  234. };
  235. PyObject*
  236. PyImaging_Mapper(PyObject* self, PyObject* args)
  237. {
  238. char* filename;
  239. if (!PyArg_ParseTuple(args, "s", &filename))
  240. return NULL;
  241. return (PyObject*) PyImaging_MapperNew(filename, 1);
  242. }
  243. /* -------------------------------------------------------------------- */
  244. /* Buffer mapper */
  245. typedef struct ImagingBufferInstance {
  246. struct ImagingMemoryInstance im;
  247. PyObject* target;
  248. Py_buffer view;
  249. } ImagingBufferInstance;
  250. static void
  251. mapping_destroy_buffer(Imaging im)
  252. {
  253. ImagingBufferInstance* buffer = (ImagingBufferInstance*) im;
  254. PyBuffer_Release(&buffer->view);
  255. Py_XDECREF(buffer->target);
  256. }
  257. PyObject*
  258. PyImaging_MapBuffer(PyObject* self, PyObject* args)
  259. {
  260. Py_ssize_t y, size;
  261. Imaging im;
  262. PyObject* target;
  263. Py_buffer view;
  264. char* mode;
  265. char* codec;
  266. PyObject* bbox;
  267. Py_ssize_t offset;
  268. int xsize, ysize;
  269. int stride;
  270. int ystep;
  271. if (!PyArg_ParseTuple(args, "O(ii)sOn(sii)", &target, &xsize, &ysize,
  272. &codec, &bbox, &offset, &mode, &stride, &ystep))
  273. return NULL;
  274. if (!PyImaging_CheckBuffer(target)) {
  275. PyErr_SetString(PyExc_TypeError, "expected string or buffer");
  276. return NULL;
  277. }
  278. if (stride <= 0) {
  279. if (!strcmp(mode, "L") || !strcmp(mode, "P"))
  280. stride = xsize;
  281. else if (!strncmp(mode, "I;16", 4))
  282. stride = xsize * 2;
  283. else
  284. stride = xsize * 4;
  285. }
  286. if (stride > 0 && ysize > PY_SSIZE_T_MAX / stride) {
  287. PyErr_SetString(PyExc_MemoryError, "Integer overflow in ysize");
  288. return NULL;
  289. }
  290. size = (Py_ssize_t) ysize * stride;
  291. if (offset > PY_SSIZE_T_MAX - size) {
  292. PyErr_SetString(PyExc_MemoryError, "Integer overflow in offset");
  293. return NULL;
  294. }
  295. /* check buffer size */
  296. if (PyImaging_GetBuffer(target, &view) < 0)
  297. return NULL;
  298. if (view.len < 0) {
  299. PyErr_SetString(PyExc_ValueError, "buffer has negative size");
  300. return NULL;
  301. }
  302. if (offset + size > view.len) {
  303. PyErr_SetString(PyExc_ValueError, "buffer is not large enough");
  304. return NULL;
  305. }
  306. im = ImagingNewPrologueSubtype(
  307. mode, xsize, ysize, sizeof(ImagingBufferInstance));
  308. if (!im)
  309. return NULL;
  310. /* setup file pointers */
  311. if (ystep > 0)
  312. for (y = 0; y < ysize; y++)
  313. im->image[y] = (char*)view.buf + offset + y * stride;
  314. else
  315. for (y = 0; y < ysize; y++)
  316. im->image[ysize-y-1] = (char*)view.buf + offset + y * stride;
  317. im->destroy = mapping_destroy_buffer;
  318. Py_INCREF(target);
  319. ((ImagingBufferInstance*) im)->target = target;
  320. ((ImagingBufferInstance*) im)->view = view;
  321. return PyImagingNew(im);
  322. }