Adding depth (z frames) to an inputted image?

I’m trying to input an image path and I want to add more frames of depth so I can utilize the various 3d effects of filters such as blur. I’m new to G’MIC but I’ve spent a decent amount of time with the documentation and can’t seem to find an answer anywhere.

Hi @SlavaCat118

Very briefly, some commands to look at:
append example: gmic image1.png image2.png append z
slices
split

Hopefully someone will give a more detailed reply later!

2 Likes

Ah! An animator after me own heart.

G’MIC Geometry Manipulation Commands expand_* pad images in both directions:

 $ gmic 0 expand_z 16
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Input empty image at position 0 (1 image 0x0x0x0).
[gmic]-1./ Expand image [0] along the z-axis with size 16 and dirichlet boundary conditions.
[gmic]-1./ Display image [0] = '[empty]'.
[0] = '[empty]':
  size = (1,1,32,1) [128 b of float32].
  data = (0\0\0\0\0\0\0\0\0\0\0\0\(...),0\0\0\0\0\0\0\0\0\0\0\0).
  min = 0, max = 0, mean = 0, std = 0, coords_min = (0,0,0,0), coords_max = (0,0,0,0).

takes an empty image and pads 16 pixels in the -z direction and 16 pixels in the +z direction, resulting in a 1×1×32×1 image.

$ gmic 128,128,1,3 expand_xy. 16
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Input black image at position 0 (1 image 128x128x1x3).
[gmic]-1./ Expand image [0] along the xy-axes with size 16 and dirichlet boundary conditions.
[gmic]-1./ Display image [0] = '[unnamed]'.
[0] = '[unnamed]':
  size = (160,160,1,3) [300 Kio of float32].
  data = (0,0,0,0,0,0,0,0,0,0,0,0,(...),0,0,0,0,0,0,0,0,0,0,0,0).
  min = 0, max = 0, mean = 0, std = 0, coords_min = (0,0,0,0), coords_max = (0,0,0,0).
[gmic]-1./ End G'MIC interpreter.

Note: 128 + 2×16 = 160. the expand_x, expand_y, expand_z, expand_xy, expand_xyz commands “pad in both directions”, so you get 2× the padding you specify along each x, y, and z axis and the padding is added to each dimension of the selected image.

You can do something similar with resize with no interpolation, but resize expands only in +x, +y, +z directions, with only the padding amount you specify, and incorporating (not adding to) the dimensions of the selected image. But! you get an output image exactly like the dimensions that you gave to resize.

To prepare a buffer for a four second 720p black-and-white animation (1280×720×120×1) @ 30 frames/second, you could write:

$ gmic 1,1,1,1,'255' r. 1280,720,120,1,0
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Input image at position 0, with values '255' (1 image 1x1x1x1).
[gmic]-1./ Resize image [0] to 1280x720x120x1, with no interpolation, dirichlet boundary conditions and alignment (0,0,0,0).
[gmic]-1./ Display image [0] = '[255]'.
[0] = '[255]':
  size = (1280,720,120,1) [421 Mio of float32].
  data = (255,0,0,0,0,0,0,0,0,0,0,0,(...),0,0,0,0,0,0,0,0,0,0,0,0).
  min = 0, max = 255, mean = 2.30577e-06, std = 0.0242481, coords_min = (1,0,0,0), coords_max = (0,0,0,0).
[gmic]-1./ End G'MIC interpreter.

which puts a single, white pixel in the upper right hand corner of frame zero; resize expands the image from that single white point in +x=1280, +y=720 and +z=120, making an animation where a single point in the upper right hand flashes on briefly, every four seconds. Probably not especially edifying.

All of this is a bit contrived, of course, just discussing what could be done with expand_* and resize in the depth direction. In practice, you can input an image with any dimensions you want and initialize in any number of ways, such as with math expressions:

 $ gmic 128,128,120,1,'x==((w/2)-1)&&y==((h/2)-1)&&z==((d/2)-1)?255:0'
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Input image at position 0, with values 'x==((w/2)-1)&&y==((h/2)-1)&&z==((d/2)-1)?255:0' (1 image 128x128x120x1).
[gmic]-1./ Display image [0] = '[x==((w/2)-1)&&y==((h/2)-1)&&z==((d/2)-1)?255:0]'.
[0] = '[x==((w/2)-1)&&y==((h/2)-1)&&z==((d/2)-1)?255:0]':
  size = (128,128,120,1) [7680 Kio of float32].
  data = (0,0,0,0,0,0,0,0,0,0,0,0,(...),0,0,0,0,0,0,0,0,0,0,0,0).
  min = 0, max = 255, mean = 0.0001297, std = 0.181861, coords_min = (0,0,0,0), coords_max = (63,63,59,0).

which sets a single white pixel on frame 59 at the center point, (x=63, y=63).

But (!) with that as a kick-off, lets blur a pop (or pop a blur?)!

blurpop: -check ${1=10}>0
    # Blur factor argument
    bfac=$1

    # White dot in the middle of the middle frame
    i 128,128,120,1,x==((w/2)-1)&&y==((h/2)-1)&&z==((d/2)-1)?255:0
    =>. anim
    
    # Make pop:
    # blur across frames
    b[anim] $bfac,0
    n[anim] 0,255

    # Colorize in a blue way
    (0,0,0^5,0,130^10,128,240^200,240,255)
    -permute. cyzx
    r. 256,1,1,3,5
    =>. palette
    
    # Normalize, because cubic interpolations
    # of the palette can produce i<0 and i>255.
    # ffmpeg does not like that…
    n[palette] 0,255

    # map palette to gray-scale animation
    map[anim] [palette],2
    rm[palette]

    # split animation out to discrete frames
    s[anim] z

    # output discrete frames as a video clip
    # (ffmpeg is the helper video maker here…)
    o blurpop.mp4,30,h264

————
 $ gmic blurpop.gmic v + blurpop 20 v -
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Input custom command file 'blurpop.gmic' (1 new, total: 4560).
[gmic]-0./ Increment verbosity level (set to 2).
[gmic]-0./blurpop/ Set local variable 'bfac=20'.
[gmic]-0./blurpop/ Input image at position 0, with values 'x==((w/2)-1)&&y==((h/2)-1)&&z==((d/2)-1)?255:0' (1 image 128x128x120x1).
[gmic]-1./blurpop/ Set name of image [0] to 'anim'.
[gmic]-1./blurpop/ Blur image [0] with standard deviation 20, dirichlet boundary conditions and gaussian kernel.
[gmic]-1./blurpop/ Normalize image [0] in range [0,255], with constant-case ratio 0.
[gmic]-1./blurpop/ Input image at position 1, with values (0,0,0^5,0,130^10,128,240^200,240,255) (1 image 3x1x1x4).
[gmic]-2./blurpop/ Permute axes of image [1], with permutation 'cyzx'.
[gmic]-2./blurpop/ Resize image [1] to 256x1x1x3, with cubic interpolation, dirichlet boundary conditions and alignment (0,0,0,0).
[gmic]-2./blurpop/ Set name of image [1] to 'palette'.
[gmic]-2./blurpop/ Normalize image [1] in range [0,255], with constant-case ratio 0.
[gmic]-2./blurpop/ Map LUT [1] on image [0], with periodic boundary conditions.
[gmic]-2./blurpop/ Remove image [1] (1 image left).
[gmic]-1./blurpop/ Split image [0] along the 'z'-axis.
[gmic]-120./blurpop/ Output images [0,1,2,(...),117,118,119] as mp4 file 'blurpop.mp4', with 30 fps and h264 codec.
[gmic]-120./ Decrement verbosity level (set to 1).
[gmic]-120./ End G'MIC interpreter.

Have fun.

1 Like

Thanks, this is great!

I originally used the resize command and failed and get something akin to the blurpop. I now realize that resize copied my input image to each slice nullifying the interest of a 3d blur. I was not aware that the expand command solved this problem completely.

Thanks for your detailed response, there are some other nuggets in here, such as normalization for ffmpeg, that are really helpful too!