8000 added Nicholas frombyte patch · matplotlib/matplotlib@0801df8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0801df8

Browse files
committed
added Nicholas frombyte patch
svn path=/trunk/matplotlib/; revision=1393
1 parent aeafeb0 commit 0801df8

File tree

5 files changed

+116
-73
lines changed

5 files changed

+116
-73
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
New entries should be added at the top
22

3+
2005-06-01 Added Nicholas' frombyte image patch - JDH
4+
35
2005-05-31 Added vertical TeX support for agg - JDH
46

57
2005-05-31 Applied Eric's cntr patch - JDH

lib/matplotlib/axes.py

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,7 +1682,6 @@ def set_frame_on(self, b):
16821682
"""
16831683
self._frameon = b
16841684

1685-
16861685
def imshow(self, X,
16871686
cmap = None,
16881687
norm = None,
@@ -1708,29 +1707,20 @@ def imshow(self, X,
17081707
colormapping etc. See below for details
17091708
17101709
1711-
Display the image in X to current axes. X may be a float array or a
1712-
PIL image. If X is a float array, X can have the following shapes
1713-
1714-
MxN : luminance (grayscale)
1715-
1716-
MxNx3 : RGB
1710+
Display the image in X to current axes. X may be a float array, a
1711+
UInt8 array or a PIL image. If X is an array, X can have the following
1712+
shapes:
17171713
1718-
MxNx4 : RGBA
1719-
1720-
A matplotlib.image.AxesImage instance is returned
1714+
MxN : luminance (grayscale, float array only)
17211715
1716+
MxNx3 : RGB (float or UInt8 array)
17221717
1723-
Alternative form:
1718+
MxNx4 : RGBA (float or UInt8 array)
17241719
1725-
IMSHOW(BUFFER, aspect=None, interpolation=None, vmax=None,
1726-
origin=None, extent=None, shape=SHAPE)
1720+
The value for each component of MxNx3 and MxNx4 float arrays should be
1721+
in the range 0.0 to 1.0; MxN float arrays may be normalised.
17271722
1728-
Display a buffer of shape shape stored in 4 byte per pixel, RGBA
1729-
form. BUFFER can be any read-only or writable buffer (eg: string
1730-
or array.array); writable buffers will be altered when shown.
1731-
SHAPE is required and should be a tupple of length 2:
1732-
(width, height). Allowed keyword arguments cmap, norm, alpha, vmin
1733-
and vmax are ignored.
1723+
A matplotlib.image.AxesImage instance is returned
17341724
17351725
The following kwargs are allowed:
17361726
@@ -1752,8 +1742,8 @@ def imshow(self, X,
17521742
filterrad parameters
17531743
17541744
* norm is a matplotlib.colors.normalize instance; default is
1755-
normalization(). This scales luminance -> 0-1 (Ignored when X is
1756-
PIL image).
1745+
normalization(). This scales luminance -> 0-1 (only used for an
1746+
MxN float array).
17571747
17581748
* vmin and vmax are used to scale a luminance image to 0-1. If
17591749
either is None, the min and max of the luminance values will be
@@ -1798,7 +1788,6 @@ def imshow(self, X,
17981788
if norm is None and shape is None:
17991789
im.set_clim(vmin, vmax)
18001790

1801-
#im.set_data(X, shape)
18021791
im.set_data(X)
18031792
im.set_alpha(alpha)
18041793

lib/matplotlib/image.py

Lines changed: 24 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from colors import normalize, colorConverter
1111
import cm
1212
import numerix
13-
from numerix import arange
13+
from numerix import arange, asarray, UInt8
1414
import _image
1515

1616

@@ -91,17 +91,13 @@ def __init__(self, ax,
9191

9292

9393
self._imcache = None
94-
self._isbuffer = False
9594

9695
def get_size(self):
9796
'Get the numrows, numcols of the input image'
9897
if self._A is None:
9998
raise RuntimeError('You must first set the image array')
10099

101-
if self._isbuffer:
102-
return self._shape
103-
else:
104-
return self._A.shape[:2]
100+
return self._A.shape[:2]
105101

106102
def set_alpha(self, alpha):
107103
"""
@@ -124,12 +120,12 @@ def changed(self):
124120
def make_image(self, flipy):
125121
if self._A is not None:
126122
if self._imcache is None:
127-
if self._isbuffer:
128-
im = _image.frombuffer(self._A, self._shape[0], self._shape[1], 0)
123+
if self._A.typecode() == UInt8:
124+
im = _image.frombyte(self._A, 0)
129125
else:
130126
x = self.to_rgba(self._A, self._alpha)
131127
im = _image.fromarray(x, 0)
132-
self._imcache = im
128+
self._imcache = im
133129
else:
134130
im = self._imcache
135131
else:
@@ -138,11 +134,8 @@ def make_image(self, flipy):
138134

139135
bg = colorConverter.to_rgba(self.axes.get_frame().get_facecolor(), 0)
140136
im.set_bg( *bg)
141-
if self._isbuffer:
142-
im.is_greyscale = False
143-
else:
144-
im.is_grayscale = (self.cmap.name == "gray" and
145-
len(self._A.shape) == 2)
137+
im.is_grayscale = (self.cmap.name == "gray" and
138+
len(self._A.shape) == 2)
146139

147140
im.set_aspect(self._aspectd[self._aspect])
148141
im.set_interpolation(self._interpd[self._interpolation])
@@ -224,19 +217,16 @@ def set_data(self, A, shape=None):
224217
225218
ACCEPTS: numeric/numarray/PIL Image A"""
226219
# check if data is PIL Image without importing Image
227-
if shape is None:
228-
if hasattr(A,'getpixel'): X = pil_to_array(A)
229-
else: X = A # assume array
220+
if hasattr(A,'getpixel'): X = pil_to_array(A)
221+
else: X = asarray(A) # assume array
222+
223+
if (X.typecode() != UInt8
224+
or len(X.shape) != 3
225+
or X.shape[2] > 4
226+
or X.shape[2] < 3):
230227
cm.ScalarMappable.set_array(self, X)
231-
self._isbuffer = False
232228
else:
233-
if not isinstance(shape, tuple):
234-
raise ValueError
235-
if not len(shape) == 2:
236-
raise ValueError
237-
self._shape = shape
238-
self._A = A
239-
self._isbuffer = True
229+
self._A = X
240230

241231
self._imcache =None
242232

@@ -338,6 +328,7 @@ def get_filterrad(self):
338328
'return the filterrad setting'
339329
return self._filterrad
340330

331+
341332
class FigureImage(Artist, cm.ScalarMappable):
342333
def __init__(self, fig,
343334
cmap = None,
@@ -410,24 +401,15 @@ def imread(fname):
410401

411402

412403
def pil_to_array( pilImage ):
413-
if pilImage.mode == 'P': # convert from paletted
414-
im = pilImage.convert('RGBX')
415-
else:
416-
im = pilImage
417-
418-
# There's a whole lotta conversion and copying going on
419-
# here -- could it be optimized?
420-
421-
if im.mode in ('RGBA','RGBX'): n_channels = 4
422-
elif im.mode == 'RGB': n_channels = 3
423-
elif im.mode == 'L': n_channels = 1
424-
else: raise RuntimeError('Unknown image mode')
404+
if pilImage.mode in ('RGBA', 'RGBX'):
405+
im = pilImage # no need to convert images in rgba format
406+
else: # try to convert to an rgba image
407+
try:
408+
im = pilImage.convert('RGBA')
409+
except ValueError:
410+
raise RuntimeError('Unknown image mode')
425411

426412
x_str = im.tostring('raw',im.mode,0,-1)
427413
x = numerix.fromstring(x_str,numerix.UInt8)
428-
if n_channels == 1:
429-
x.shape = im.size[1], im.size[0]
430-
else:
431-
x.shape = im.size[1], im.size[0], n_channels
432-
x=x.astype(numerix.Float32)/255.0
414+
x.shape = im.size[1], im.size[0], 4
433415
return x

src/_image.cpp

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <cmath>
44
#include <cstdio>
55
#include <png.h>
6+
#include <string>
67
#include "Python.h"
78

89
#ifdef NUMARRAY
@@ -1078,7 +1079,80 @@ _image_module::fromarray2(const Py::Tuple& args) {
10781079
return Py::asObject( imo );
10791080
}
10801081

1082+
char _image_module_frombyte__doc__[] =
1083+
"frombyte(A, isoutput)\n"
1084+
"\n"
1085+
"Load the image from a byte array.\n"
1086+
"By default this function fills the input buffer, which can subsequently\n"
1087+
"be resampled using resize. If isoutput=1, fill the output buffer.\n"
1088+
"This is used to support raw pixel images w/o resampling."
1089+
;
1090+
Py::Object
1091+
_image_module::frombyte(const Py::Tuple& args) {
1092+
_VERBOSE("_image_module::frombyte");
1093+
1094+
args.verify_length(2);
1095+
1096+
Py::Object x = args[0];
1097+
int isoutput = Py::Int(args[1]);
1098+
1099+
PyArrayObject *A = (PyArrayObject *) PyArray_ContiguousFromObject(x.ptr(), PyArray_UBYTE, 3, 3);
10811100

1101+
if (A->dimensions[2]<3 || A->dimensions[2]>4)
1102+
throw Py::ValueError("Array dimension 3 must have size 3 or 4");
1103+
1104+
Image* imo = new Image;
1105+
1106+
imo->rowsIn = A->dimensions[0];
1107+
imo->colsIn = A->dimensions[1];
1108+
1109+
agg::int8u *arrbuf;
1110+
agg::int8u *buffer;
1111+
1112+
arrbuf = reinterpret_cast<agg::int8u *>(A->data);
1113+
1114+
size_t NUMBYTES(imo->colsIn * imo->rowsIn * imo->BPP);
1115+
buffer = new agg::int8u[NUMBYTES];
1116+
1117+
if (buffer==NULL) //todo: also handle allocation throw
1118+
throw Py::MemoryError("_image_module::frombyte could not allocate memory");
1119+
1120+
const size_t N = imo->rowsIn * imo->colsIn * imo->BPP;
1121+
size_t i = 0;
1122+
if (A->dimensions[2] == 4) {
1123+
std::memmove(buffer, arrbuf, N);
1124+
} else {
1125+
while (i < N) {
1126+
std::memmove(buffer, arrbuf, 3);
1127+
buffer += 3;
1128+
arrbuf += 3;
1129+
*buffer++ = 255;
1130+
i += 4;
1131+
}
1132+
buffer -= N;
1133+
arrbuf -= imo->rowsIn * imo->colsIn;
1134+
}
1135+
Py_XDECREF(A);
1136+
1137+
if (isoutput) {
1138+
// make the output buffer point to the input buffer
1139+
1140+
imo->rowsOut = imo->rowsIn;
1141+
imo->colsOut = imo->colsIn;
1142+
1143+
imo->rbufOut = new agg::rendering_buffer;
1144+
imo->bufferOut = buffer;
1145+
imo->rbufOut->attach(imo->bufferOut, imo->colsOut, imo->rowsOut, imo->colsOut * imo->BPP);
1146+
1147+
}
1148+
else {
1149+
imo->bufferIn = buffer;
1150+
imo->rbufIn = new agg::rendering_buffer;
1151+
imo->rbufIn->attach(buffer, imo->colsIn, imo->rowsIn, imo->colsIn*imo->BPP);
1152+
}
1153+
1154+
return Py::asObject( imo );
1155+
}
10821156

10831157
char _image_module_frombuffer__doc__[] =
10841158
"frombuffer(buffer, width, height, isoutput)\n"
@@ -1121,15 +1195,7 @@ _image_module::frombuffer(const Py::Tuple& args) {
11211195
agg::int8u* buffer = new agg::int8u[NUMBYTES];
11221196
if (buffer==NULL) //todo: also handle allocation throw
11231197
throw Py::MemoryError("_image_module::frombuffer could not allocate memory");
1124-
for (size_t inum=0; inum<NUMBYTES; inum++)
1125-
*buffer++ = *rawbuf++;
1126-
rawbuf -= NUMBYTES;
1127-
buffer -= NUMBYTES;
1128-
1129-
//for (size_t inum=0; inum<NUMBYTES; inum++)
1130-
// std::cout << int(*buffer++);
1131-
//buffer -= NUMBYTES;
1132-
1198+
std::memmove(buffer, rawbuf, NUMBYTES);
11331199

11341200
if (isoutput) {
11351201
// make the output buffer point to the input buffer

src/_image.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ class _image_module : public Py::ExtensionModule<_image_module>
115115
"fromarray");
116116
add_varargs_method("fromarray2", &_image_module::fromarray2,
117117
"fromarray2");
118+
add_varargs_method("frombyte", &_image_module::frombyte,
119+
"frombyte");
118120
add_varargs_method("frombuffer", &_image_module::frombuffer,
119121
"frombuffer");
120122
add_varargs_method("readpng", &_image_module::readpng,
@@ -127,13 +129,15 @@ class _image_module : public Py::ExtensionModule<_image_module>
127129
~_image_module() {}
128130

129131
private:
132+
Py::Object frombyte (const Py::Tuple &args);
130133
Py::Object frombuffer (const Py::Tuple &args);
131134
Py::Object fromarray (const Py::Tuple &args);
132135
Py::Object fromarray2 (const Py::Tuple &args);
133136
Py::Object readpng (const Py::Tuple &args);
134137
Py::Object from_images (const Py::Tuple &args);
135138
static char _image_module_fromarray__doc__[];
136139
static char _image_module_fromarray2__doc__[];
140+
static char _image_module_frombyte__doc__[];
137141
static char _image_module_frombuffer__doc__[];
138142

139143
};

0 commit comments

Comments
 (0)
0