g | x | w | all
Bytes Lang Time Link
097JavaScript V8250207T132022ZArnauld
082Python 3.8 prerelease250207T001041ZLucenapo
01705AB1E250207T083712ZKevin Cr
021MATL250206T224215ZLuis Men
021K ngn/k250207T113526Zatt
035Charcoal250207T114919ZNeil
163Maple250207T055738Zdharr
124Perl 5 n250206T225725ZXcali

JavaScript (V8), 97 bytes

Expects (h)(w) and prints the output using option 1.

h=>w=>{for(s=j=1,i=w*h;i--;print(n+=-z|w))j=j-1||(q=s>>2,z=s++%4<2,s&1?0:n=z-~q*w-q,z?w:h-1)-q*2}

Try it online!

Commented

h =>               // outer function taking the height h
w => {             // inner function taking the width w
  for(             // main loop:
    s =            //   s = current step (4 steps per revolution)
    j = 1,         //   j = number of moves in the current step
    i = w * h;     //   i = total number of moves
    i--;           //   stop when i = 0
    print(         //   update n and print it:
      n + = -z | w //     add -1 if z is set, or w otherwise
    )              //
  )                //
    j = j - 1 || ( //   decrement j; if it's zero:
      q = s >> 2,  //     q = current revolution
      z = s++ % 4  //     z = 1 for an horizontal step
          < 2,     //         0 for a vertical step
                   //         this goes 1->0->0->1 (mod 4)
      s & 1 ?      //     if this is an odd step:
        0          //       do nothing
      :            //     else (we are at a top-right corner):
        n = z      //       reset n to z ...
          - ~q * w //       ... plus (q+1)*w
          - q,     //       ... minus q
      z ?          //     if this is an horizontal step:
        w          //       set j to w
      :            //     else:
        h - 1      //       set j to h-1
    ) - q * 2      //     minus q*2 in both cases
}                  //

Python 3.8 (pre-release), 106 98 82 bytes

lambda x,y:sorted(range(x*y),key=lambda z:[min(c:=z%y,d:=z//y,y-c-.5,x-d-.5),d-c])

Try it online!

Output is 0-based and used option 1.

05AB1E, 17 bytes

*LIôΔćˆøíćˆR}¯í˜þ

1-based and visiting top-left first (option 1). Two loose inputs in the order \$h,w\$.

Try it online or verify all test cases.

Explanation:

If we look at the first two steps of option 1, we can add a rotate clockwise and reverse in between to make extracting all four first rows from the matrix of those two steps the same. This means we can basically repeat the following four sub-steps until the matrix is empty.
E.g., with the example matrix:

 1  2  3  4  5  6
 7  8  9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30

Step 1a: Extract the first row (ćˆ):

 7  8  9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30

[[1,2,3,4,5,6]]

Step 1b: Rotate the matrix once clockwise (øí):

25 19 13  7
26 20 14  8
27 21 15  9
28 22 16 10
29 23 17 11
30 24 18 12

Step 1c: Extract the first row again (ćˆ):

26 20 14  8
27 21 15  9
28 22 16 10
29 23 17 11
30 24 18 12

[[1,2,3,4,5,6],[25,19,13,7]]

Step 1d: Reverse the matrix (R):

30 24 18 12
29 23 17 11
28 22 16 10
27 21 15  9
26 20 14  8

After the same four steps to extract the 'bottom-right' corner:

 8  9 10 11
14 15 16 17
20 21 22 23

[[1,2,3,4,5,6],[25,19,13,7],[30,24,18,12],[26,27,28,29]]

And in the end, we reverse each inner list and flatten it (¯í˜).

Code explanation:

*         # Multiply the two (implicit) input-integers together: h*w
 L        # Pop and push a list in the range [1,h*w]
  Iô      # Split it into parts of the second input's (w) size
    Δ     # Loop until the result no longer changes:
     ć    #  Extract head; pop and push first row and remainder-matrix separately
      ˆ   #  Pop and add this first row to global array `¯`
       øí #  Rotate the remainder-matrix once clockwise:
       ø  #   Zip/transpose; swapping rows/columns
        í #   Reverse each inner row
     ćˆ   #  Extract head and add to global array again
       R  #  Reverse the rows of the matrix for the next iteration
    }¯    # After the changes-loop: push the global array
      í   # Reverse each inner row
       ˜  # Flatten it
        þ # Remove the two/three trailing empty strings by only keeping integers
          # (after which the result is output implicitly)

MATL, 23 21 bytes

p:Ge`XP1&Z)0&Y)1X!t]v

Input is [w h]. Output is 1-based, with each number on a different line.

Try it online! Or verify all test cases, with each output on a single line for easier visualization.

Explanation

p        % Implicit input: [w h]. Product: w*h
:        % Range: [1 2 ... w*h]
G        % Push input again
e        % Reshape as a matrix with that size, in column-major order
`        % Do...while
  XP     %   Flip matrix vertically
  1&Z)   %   Push first column, then the rest of the matrix
  0&Y)   %   Push last row, then the rest of the matrix
  1X!    %   Rotate 90 degrees counterclockwise
  t      %   Duplicate. This will be used as loop condition
]        % End. The loop is repeated while the matrix is non-empty
v        % Concatenate all results into a column vector. Implicit display

K (ngn/k), 21 bytes

<+(+<\|&\|:\&;-).\:!:

Try it online!

Didn't read properly, oops.

Input a two-element array f h,w. 0-indexed. Chooses "Option 1".

                   !:   r,c for range(h*w)
<                       sort by:
 +(          ; ).\:       (      ;   )
              -                   r-c
                           layer:
            &                ▛ min(r,c)
         |:\                 ▟ its reverse
       &/                    min
   +<\| \                    do ▛ first

Charcoal, 35 bytes

Nθ≔⪪…⁰×θNθθW⌈θ«≔⮌Eι⮌Eθ§μλθIEθ⊟κI⮌⊟θ

Try it online! Link is to verbose version of code. 0-indexed and starts at the top left. Takes inputs in the order w, h. Explanation:

Nθ≔⪪…⁰×θNθθ

Generate the initial rectangle.

W⌈θ«

Repeat until either it is empty or its rows are.

≔⮌Eι⮌Eθ§μλθ

Transpose the rectangle antidiagonally.

IEθ⊟κ

Remove and print the last element of each row.

I⮌⊟θ

Remove and print the reverse of the last row.

Maple, 163 bytes

proc(h,w)s:=seq;n:=h*w;a,b,c,d:=1,w,1+n-w,n;L:=();to n do L,=s(b..a,-1);b+=w;a+=w;L,=s(a..c,w);a++;c++;L,=s(b..d,w);b--;d--;L,=s(d..c,-1);d-=w;c-=w;od;[L][..n]end;
proc(h,w)
s:=seq;                 # s short for seq
n:=h*w;
a,b,c,d:=1,w,1+n-w,n;   # initialize a,b,c,d
L:=();                  # initialize output list
to n do                 # too many times, but it's shorter                     
  # for each case: seq(from..to,step) then update "from" and "to"
  L,=s(b..a,-1);b+=w;a+=w; # top going left
  L,=s(a..c,w);a++;c++;    # left side going down
  L,=s(b..d,w);b--;d--;    # right side going down
  L,=s(d..c,-1);d-=w;c-=w; # bottom going left
od;
[L][..n]                # chop off extras
end;

Doesn't use an array, just generates the numbers. Starts at top-left corner. Output is 1-based. Keeps track of the numbers at the corners: a,b,c,d for top left, top right, bottom left, bottom right. Updates them after outputting a row or column.

It might be possible to have just one L,seq(...) in the loop with clever updates, but I couldn't think of a short way to do this.

The last line could be L[..n] except the 1,1 case fails then.

Perl 5 -n, 124 bytes

$w=<>;@a=map[$_*$w+1..$_*$w+$w],0..$_-1;map say,(reverse@{shift@a}),(map{shift@$_}@a),(map{pop@$_}@a),reverse@{pop@a}while@a

Try it online!