Look at the example:
extern const uint8_t penguin;
tft.setAddrWindow(wid - 40 - 40, 20 + 0, wid - 1 - 40, 20 + 39);
tft.pushColors(penguin, 1600, 1);
It is easier to follow if you put in fixed numbers:
extern const uint8_t penguin; //array of 3200 bytes in Flash memory
tft.setAddrWindow(25, 80, 64, 119); //TLHC at 25,80 and BRHC at 64,119
tft.pushColors(penguin, 1600, 1); //40x40 pixels = 1600 pixels = 3200 bytes
Note that setAddrWindow() uses coordinates of the Rectangle i.e. TLHC, BLHC.
Whereas fillRect() uses TLHC and dimensions of rectangle i.e. TLHC, width, height
I just followed the style of the Adafruit methods. In an ideal world, I would prefer to use TLHC and dimensions of rectangle for all methods. It seems more intuitive (to me)
Note that the coordinates of the TLHC of the screen are 0,0
The BRHC (bottom right hand corner) is 239,319 on a 240x320 Portrait.
The BRHC (bottom right hand corner) is 319,239 on a 320x240 Landscape.
Adafruit have Tutorials and good documentation for the Adafruit_GFX graphics library.
I have never produced any documentation for the MCUFRIEND_kbv library.
The penguin[ ] array is just stored as a sequence of bytes. Two bytes per pixel. Stored as bigendian.