1#!/usr/bin/env python
2
3from __future__ import print_function
4from __future__ import absolute_import
5import math, os
6import OpenImageIO as oiio
7from OpenImageIO import ImageBuf, ImageSpec, ImageBufAlgo, ROI
8
9
10OIIO_TESTSUITE_ROOT = os.getenv('OIIO_TESTSUITE_ROOT', '')
11OIIO_TESTSUITE_IMAGEDIR = os.getenv('OIIO_TESTSUITE_IMAGEDIR', '')
12
13def make_constimage (xres, yres, chans=3, format=oiio.UINT8, value=(0,0,0),
14                xoffset=0, yoffset=0) :
15    spec = ImageSpec (xres,yres,chans,format)
16    spec.x = xoffset
17    spec.y = yoffset
18    b = ImageBuf (spec)
19    oiio.ImageBufAlgo.fill (b, value)
20    return b
21
22
23def write (image, filename, format=oiio.UNKNOWN) :
24    if not image.has_error :
25        image.write (filename, format)
26    if image.has_error :
27        print ("Error writing", filename, ":", image.geterror())
28
29def dumpimg (image, fmt="{:.3f}", msg="") :
30    spec = image.spec()
31    print (msg, end="")
32    for y in range(spec.y, spec.y+spec.height) :
33        for x in range(spec.x, spec.x+spec.width) :
34            p = image.getpixel (x, y)
35            print ("[", end="")
36            for c in range(spec.nchannels) :
37                print (fmt.format(p[c]), end=" ")
38            print ("] ", end="")
39        print ("")
40
41
42
43######################################################################
44# main test starts here
45
46try:
47    # Some handy images to work with
48    gridname = os.path.join(OIIO_TESTSUITE_IMAGEDIR, "grid.tif")
49    grid = ImageBuf (gridname)
50    checker = ImageBuf(ImageSpec(256, 256, 3, oiio.UINT8))
51    ImageBufAlgo.checker (checker, 8, 8, 8, (0,0,0), (1,1,1))
52    gray128 = make_constimage (128, 128, 3, oiio.HALF, (0.5,0.5,0.5))
53    gray64 = make_constimage (64, 64, 3, oiio.HALF, (0.5,0.5,0.5))
54    tahoetiny = ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-tiny.tif")
55
56    # black
57    # b = ImageBuf (ImageSpec(320,240,3,oiio.UINT8))
58    b = ImageBufAlgo.zero (roi=oiio.ROI(0,320,0,240,0,1,0,3))
59    write (b, "black.tif", oiio.UINT8)
60
61    # fill (including use of ROI)
62    b = ImageBuf (ImageSpec(256,256,3,oiio.UINT8));
63    ImageBufAlgo.fill (b, (1,0.5,0.5))
64    ImageBufAlgo.fill (b, (0,1,0), oiio.ROI(100,180,100,180))
65    write (b, "filled.tif", oiio.UINT8)
66
67    # checker
68    b = ImageBuf (ImageSpec(256,256,3,oiio.UINT8))
69    ImageBufAlgo.checker (b, 64, 64, 64, (1,.5,.5), (.5,1,.5), 10, 5)
70    write (b, "checker.tif", oiio.UINT8)
71
72    # noise-uniform
73    b = ImageBufAlgo.noise ("uniform", 0.25, 0.75, roi=ROI(0,64,0,64,0,1,0,3))
74    write (b, "noise-uniform3.tif", oiio.UINT8)
75
76    # noise-gaussian
77    b = ImageBufAlgo.noise ("gaussian", 0.5, 0.1, roi=ROI(0,64,0,64,0,1,0,3));
78    write (b, "noise-gauss.tif", oiio.UINT8)
79
80    # noise-gaussian
81    b = ImageBufAlgo.noise ("salt", 1, 0.01, roi=ROI(0,64,0,64,0,1,0,3));
82    write (b, "noise-salt.tif", oiio.UINT8)
83
84    # channels, channel_append
85    b = ImageBufAlgo.channels (grid, (0.25,2,"G"))
86    write (b, "chanshuffle.tif")
87    b = ImageBufAlgo.channels (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/rgbaz.exr"),
88                               ("R","G","B","A"))
89    write (b, "ch-rgba.exr")
90    b = ImageBufAlgo.channels (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/rgbaz.exr"), ("Z",))
91    write (b, "ch-z.exr")
92    b = ImageBufAlgo.channel_append (ImageBuf("ch-rgba.exr"),
93                                     ImageBuf("ch-z.exr"))
94    write (b, "chappend-rgbaz.exr")
95
96    # flatten
97    b = ImageBufAlgo.flatten (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool-deep/src/deepalpha.exr"))
98    write (b, "flat.exr")
99
100    # deepen
101    b = ImageBufAlgo.deepen (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool-deep/src/az.exr"))
102    write (b, "deepen.exr")
103
104    # crop
105    b = ImageBufAlgo.crop (grid, oiio.ROI(50,150,200,600))
106    write (b, "crop.tif")
107
108    # cut
109    b = ImageBufAlgo.cut (grid, oiio.ROI(50,150,200,600))
110    write (b, "cut.tif")
111
112    # paste
113    b = ImageBuf()
114    b.copy (checker)
115    ImageBufAlgo.paste (b, 150, 75, 0, 0, grid)
116    write (b, "pasted.tif")
117
118    # rotate90
119    b = ImageBufAlgo.rotate90 (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/image.tif"))
120    write (b, "rotate90.tif")
121
122    # rotate180
123    b = ImageBufAlgo.rotate180 (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/image.tif"))
124    write (b, "rotate180.tif")
125
126    # rotate270
127    b = ImageBufAlgo.rotate270 (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/image.tif"))
128    write (b, "rotate270.tif")
129
130    # flip
131    b = ImageBufAlgo.flip (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/image.tif"))
132    write (b, "flip.tif")
133
134    # flop
135    b = ImageBufAlgo.flop (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/image.tif"))
136    write (b, "flop.tif")
137
138    # reorient
139    image_small = ImageBuf()
140    ImageBufAlgo.resample (image_small, ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/image.tif"),  roi=oiio.ROI(0,160,0,120))
141    image_small = ImageBufAlgo.rotate90 (image_small)
142    image_small.specmod().attribute ("Orientation", 8)
143    b = ImageBufAlgo.reorient (image_small)
144    write (b, "reorient1.tif")
145    image_small = ImageBuf()
146
147    # transpose
148    b = ImageBufAlgo.transpose (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/image.tif"))
149    write (b, "transpose.tif")
150
151    # circular_shift
152    b = ImageBufAlgo.circular_shift (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/image.tif"), 100, 50)
153    write (b, "cshift.tif")
154
155    # clamp
156    b = ImageBufAlgo.resize (grid, roi=oiio.ROI(0,500,0,500))
157    b = ImageBufAlgo.clamp (b, (0.2,0.2,0.2,0.2), (100,100,0.5,1))
158    write (b, "grid-clamped.tif", oiio.UINT8)
159
160    # add
161    b = ImageBufAlgo.add (gray128, 0.25)
162    write (b, "cadd1.exr")
163    b = ImageBufAlgo.add (gray128, (0, 0.25, -0.25))
164    write (b, "cadd2.exr")
165    b = ImageBufAlgo.add (make_constimage(64,64,3,oiio.HALF,(.1,.2,.3)),
166                          make_constimage(64,64,3,oiio.HALF,(.1,.1,.1),20,20))
167    write (b, "add.exr")
168
169    # sub
170    b = ImageBufAlgo.sub (make_constimage(64,64,3,oiio.HALF,(.1,.2,.3)),
171                          make_constimage(64,64,3,oiio.HALF,(.1,.1,.1),20,20))
172    write (b, "sub.exr")
173
174    # Test --absdiff and --abs
175    # First, make a test image that's 0.5 on the left, -0.5 on the right
176    a = ImageBuf (ImageSpec(128,128,3,oiio.HALF))
177    ImageBufAlgo.fill (a, (0.5,0.5,0.5))
178    ImageBufAlgo.fill (a, (-0.25,-0.25,-0.25), oiio.ROI(0,64,0,128))
179    b = ImageBufAlgo.abs (a)
180    write (b, "abs.exr", oiio.HALF)
181    b = ImageBufAlgo.absdiff (a, (0.2,0.2,0.2))
182    write (b, "absdiff.exr", oiio.HALF)
183    a = ImageBuf()
184
185    # mul
186    b = ImageBufAlgo.mul (gray128, 1.5)
187    write (b, "cmul1.exr")
188    b = ImageBufAlgo.mul (gray128, (1.5,1,0.5))
189    write (b, "cmul2.exr")
190    b = ImageBufAlgo.mul (make_constimage(64,64,3,oiio.HALF,(.5,.5,.5)),
191                          make_constimage(64,64,3,oiio.HALF,(1.5,1,0.5)))
192    write (b, "mul.exr", oiio.HALF)
193
194    # mad
195    b = ImageBufAlgo.mad (make_constimage(64,64,3,oiio.HALF,(.5,.5,.5)),
196                          make_constimage(64,64,3,oiio.HALF,(1.5,1,0.5)),
197                          make_constimage(64,64,3,oiio.HALF,(0.1,0.1,0.1)))
198    write (b, "mad.exr", oiio.HALF)
199    b = ImageBufAlgo.mad (make_constimage(64,64,3,oiio.HALF,(.5,.5,.5)),
200                          (1.5,1,0.5),
201                          (0.1,0.1,0.1))
202    write (b, "mad2.exr", oiio.HALF)
203    b = ImageBufAlgo.mad (make_constimage(64,64,3,oiio.HALF,(.5,.5,.5)),
204                          (1.5,1,0.5),
205                          make_constimage(64,64,3,oiio.HALF,(0.1,0.1,0.1)))
206    write (b, "mad3.exr", oiio.HALF)
207
208    # div
209    b = ImageBufAlgo.div (gray64, make_constimage (64, 64, 3, oiio.HALF, (2.0,1,0.5)))
210    write (b, "div.exr", oiio.HALF)
211    b = ImageBufAlgo.div (gray64, 2.0)
212    write (b, "divc1.exr", oiio.HALF)
213    b = ImageBufAlgo.div (gray64, (2.0,1,0.5))
214    write (b, "divc2.exr", oiio.HALF)
215
216    # invert
217    a = ImageBuf (OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-small.tif")
218    b = ImageBufAlgo.invert (a)
219    write (b, "invert.tif", oiio.UINT8)
220
221    # pow
222    b = ImageBufAlgo.pow (gray128, 2)
223    write (b, "cpow1.exr")
224    b = ImageBufAlgo.pow (gray128, (2,2,1))
225    write (b, "cpow2.exr")
226
227    # channel_sum
228    b = ImageBufAlgo.channel_sum (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-small.tif"),
229                                  (.2126,.7152,.0722))
230    write (b, "chsum.tif", oiio.UINT8)
231
232    # color_map
233    b = ImageBufAlgo.color_map (tahoetiny, -1, "inferno")
234    write (b, "colormap-inferno.tif", oiio.UINT8)
235    b = ImageBufAlgo.color_map (tahoetiny, -1, 3, 3, (.25,.25,.25,0,.5,0,1,0,0))
236    write (b, "colormap-custom.tif", oiio.UINT8)
237
238    # premult/unpremult
239    b = make_constimage(100,100,4,oiio.FLOAT,(.1,.1,.1,1))
240    ImageBufAlgo.fill (b, (.2,.2,.2,.5), oiio.ROI(50,80,50,80))
241    b = ImageBufAlgo.unpremult (b)
242    write (b, "unpremult.tif")
243    b = ImageBufAlgo.premult (b)
244    write (b, "premult.tif")
245
246    b = ImageBufAlgo.contrast_remap (tahoetiny, black=0.1, white=0.75)
247    write (b, "contrast-stretch.tif")
248    b = ImageBufAlgo.contrast_remap (tahoetiny, min=0.1, max=0.75)
249    write (b, "contrast-shrink.tif")
250    b = ImageBufAlgo.contrast_remap (tahoetiny, scontrast=5.0)
251    write (b, "contrast-sigmoid5.tif")
252
253    b = ImageBuf (OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-small.tif")
254    b = ImageBufAlgo.rangecompress (b)
255    write (b, "rangecompress.tif", oiio.UINT8)
256    b = ImageBufAlgo.rangeexpand (b)
257    write (b, "rangeexpand.tif", oiio.UINT8)
258
259    # FIXME - colorconvert, ociolook need tests
260    print ("\nTesting color conversions:")
261    b = make_constimage (2,2,4,oiio.FLOAT,(0,0,0,1))
262    b.setpixel(1, 0, (.25,.25,.25,1))
263    b.setpixel(0, 1, (.5,.5,.5,1))
264    b.setpixel(1, 1, (1,1,1,1))
265    dumpimg (b, msg="linear src=")
266    r = ImageBufAlgo.colorconvert(b, "Linear", "sRGB")
267    dumpimg (r, msg="to srgb =")
268    r = ImageBufAlgo.colorconvert(r, "sRGB", "Linear")
269    dumpimg (r, msg="back to linear =")
270    # Just to test, make a matrix that halves red, doubles green,
271    # adds 0.1 to blue.
272    M = ( 0.5, 0, 0,   0,
273          0,   2, 0,   0,
274          0,   0, 1,   0,
275          0,   0, 0.1, 1)
276    r = ImageBufAlgo.colormatrixtransform (b, M)
277    dumpimg (r, msg="after *M =")
278
279    # computePixelStats
280    b = ImageBuf (OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-small.tif")
281    stats = ImageBufAlgo.computePixelStats (b)
282    print ("Stats for tahoe-small.tif:")
283    print ("  min         = ", stats.min)
284    print ("  max         = ", stats.max)
285    print ("  avg         = ", stats.avg)
286    print ("  stddev      = ", stats.stddev)
287    print ("  nancount    = ", stats.nancount)
288    print ("  infcount    = ", stats.infcount)
289    print ("  finitecount = ", stats.finitecount)
290
291    compresults = ImageBufAlgo.compare (ImageBuf("flip.tif"), ImageBuf("flop.tif"),
292                                        1.0e-6, 1.0e-6)
293    print ("Comparison: of flip.tif and flop.tif")
294    print ("  mean = %.5g" % compresults.meanerror)
295    print ("  rms  = %.5g" % compresults.rms_error)
296    print ("  PSNR = %.5g" % compresults.PSNR)
297    print ("  max  = %.5g" % compresults.maxerror)
298    print ("  max @", (compresults.maxx, compresults.maxy, compresults.maxz, compresults.maxc))
299    print ("  warns", compresults.nwarn, "fails", compresults.nfail)
300
301    # compare_Yee,
302    # isConstantColor, isConstantChannel
303
304    b = ImageBuf (ImageSpec(256,256,3,oiio.UINT8));
305    ImageBufAlgo.fill (b, (1,0.5,0.5))
306    r = ImageBufAlgo.isConstantColor (b)
307    print ("isConstantColor on pink image is (%.5g %.5g %.5g)" % r)
308    r = ImageBufAlgo.isConstantColor (checker)
309    print ("isConstantColor on checker is ", r)
310
311    b = ImageBuf("cmul1.exr")
312    print ("Is", b.name, "monochrome? ", ImageBufAlgo.isMonochrome(b))
313    b = ImageBuf("cmul2.exr")
314    print ("Is", b.name, "monochrome? ", ImageBufAlgo.isMonochrome(b))
315
316
317    # color_count
318
319    b = ImageBufAlgo.fill (top=(0,0,0), bottom=(1,1,1), roi=ROI(0,4,0,4,0,1,0,3))
320    counts = ImageBufAlgo.color_range_check (b, low=0.25, high=(0.5,0.5,0.5))
321    print ('color range counts = ', counts)
322
323    # nonzero_region
324    b = make_constimage (256,256,3,oiio.UINT8,(0,0,0))
325    ImageBufAlgo.fill (b, (0,0,0))
326    ImageBufAlgo.fill (b, (0,1,0), oiio.ROI(100,180,100,180))
327    print ("Nonzero region is: ", ImageBufAlgo.nonzero_region(b))
328
329    # resize
330    b = ImageBufAlgo.resize (grid, roi=oiio.ROI(0,256,0,256))
331    write (b, "resize.tif")
332
333    # resample
334    b = ImageBufAlgo.resample (grid, roi=oiio.ROI(0,128,0,128))
335    write (b, "resample.tif")
336
337    # fit
338    b = ImageBufAlgo.fit (grid, roi=oiio.ROI(0,360,0,240))
339    write (b, "fit.tif")
340
341    # warp
342    Mwarp = (0.7071068, 0.7071068, 0, -0.7071068, 0.7071068, 0, 128, -53.01933, 1)
343    b = ImageBufAlgo.warp (ImageBuf("resize.tif"), Mwarp)
344    write (b, "warped.tif")
345
346    # rotate
347    b = ImageBufAlgo.rotate (ImageBuf("resize.tif"), math.radians(45.0))
348    write (b, "rotated.tif")
349    b = ImageBufAlgo.rotate (ImageBuf("resize.tif"), math.radians(45.0), 50.0, 50.0)
350    write (b, "rotated-offcenter.tif")
351
352    # make_kernel
353    bsplinekernel = ImageBufAlgo.make_kernel ("bspline", 15, 15)
354    write (bsplinekernel, "bsplinekernel.exr")
355
356    # convolve -- test with bspline blur
357    b = ImageBufAlgo.convolve (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-small.tif"),
358                               bsplinekernel)
359    write (b, "bspline-blur.tif", oiio.UINT8)
360
361    # median filter
362    b = ImageBufAlgo.median_filter (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-small.tif"), 5, 5)
363    write (b, "tahoe-median.tif", oiio.UINT8)
364
365    # Dilate/erode
366    undilated = ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/morphsource.tif")
367    b = ImageBufAlgo.dilate (undilated, 3, 3)
368    write (b, "dilate.tif", oiio.UINT8)
369    b = ImageBufAlgo.erode (undilated, 3, 3)
370    write (b, "erode.tif", oiio.UINT8)
371    undilated = None
372
373    # unsharp_mask
374    b = ImageBufAlgo.unsharp_mask (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-small.tif"),
375                                   "gaussian", 3.0, 1.0, 0.0)
376    write (b, "unsharp.tif", oiio.UINT8)
377
378    # unsharp_mark with median filter
379    b = ImageBufAlgo.unsharp_mask (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-small.tif"),
380                                   "median", 3.0, 1.0, 0.0)
381    write (b, "unsharp-median.tif", oiio.UINT8)
382
383    # laplacian
384    b = ImageBufAlgo.laplacian (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-tiny.tif"))
385    write (b, "tahoe-laplacian.tif", oiio.UINT8)
386
387    # computePixelHashSHA1
388    print ("SHA-1 of bsplinekernel.exr is: " +
389           ImageBufAlgo.computePixelHashSHA1(bsplinekernel))
390
391    # fft, ifft
392    blue = ImageBufAlgo.channels (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-tiny.tif"), (2,))
393    fft = ImageBufAlgo.fft (blue)
394    write (fft, "fft.exr", oiio.FLOAT)
395    inv = ImageBufAlgo.ifft (fft)
396    b = ImageBufAlgo.channels (inv, (0,))
397    write (b, "ifft.exr", oiio.FLOAT)
398    inv.clear()
399    fft.clear()
400
401    fft = ImageBuf("fft.exr")
402    polar = ImageBufAlgo.complex_to_polar (fft)
403    b = ImageBufAlgo.polar_to_complex (polar)
404    write (polar, "polar.exr", oiio.FLOAT)
405    write (b, "unpolar.exr", oiio.FLOAT)
406    fft.clear()
407    polar.clear()
408
409    # fixNonFinite
410    bad = ImageBuf (OIIO_TESTSUITE_ROOT+"/oiiotool-fixnan/src/bad.exr")
411    b = ImageBufAlgo.fixNonFinite (bad, oiio.NONFINITE_BOX3)
412    write (b, "box3.exr")
413    bad.clear()
414
415    # fillholes_pushpull
416    b = ImageBufAlgo.fillholes_pushpull (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/ref/hole.tif"))
417    write (b, "tahoe-filled.tif", oiio.UINT8)
418
419    # over
420    b = ImageBufAlgo.over (ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool-composite/src/a.exr"),
421                           ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool-composite/src/b.exr"))
422    write (b, "a_over_b.exr")
423
424    # FIXME - no test for zover (not in oiio-composite either)
425
426    b = make_constimage (320, 240, 3, oiio.FLOAT)
427    ImageBufAlgo.render_text (b, 25, 50, "Hello, world",
428                              16, "DroidSerif", (1,1,1))
429    ImageBufAlgo.render_text (b, 50, 120, "Go Big Red!",
430                              42, "", (1,0,0))
431    write (b, "text.tif", oiio.UINT8)
432
433    b = make_constimage (320, 240, 3, oiio.FLOAT)
434    broi = b.roi
435    textsize = ImageBufAlgo.text_size ("Centered", 40)
436    if textsize.defined :
437        x = broi.xbegin + broi.width//2  - (textsize.xbegin + textsize.width//2)
438        y = broi.ybegin + broi.height//2 - (textsize.ybegin + textsize.height//2)
439        ImageBufAlgo.render_text (b, x, y, "Centered", 40)
440    write (b, "textcentered.tif", oiio.UINT8)
441
442    # histogram, histogram_draw,
443    b = make_constimage (100, 100, 3, oiio.UINT8, (.1, .2, .3))
444    Rhist = ImageBufAlgo.histogram (b, channel=0, bins=4)
445    Ghist = ImageBufAlgo.histogram (b, channel=1, bins=4)
446    Bhist = ImageBufAlgo.histogram (b, channel=2, bins=4)
447    print ("R hist: ", Rhist)
448    print ("G hist: ", Ghist)
449    print ("B hist: ", Bhist)
450
451    # make_texture
452    ImageBufAlgo.make_texture (oiio.MakeTxTexture,
453                               ImageBuf(OIIO_TESTSUITE_ROOT+"/oiiotool/src/tahoe-small.tif"),
454                               "tahoe-small.tx")
455
456    # capture_image - no test
457
458    print ("Done.")
459except Exception as detail:
460    print ("Unknown exception:", detail)
461
462