In an attempt to implement a method of recording the screen in frames for easy video playing, rewinding, etc. I built an API which does exactly that.

However, the generated file size is much too large for saving entire recordings this way. Unfortunately, I don't think that I can adapt this API to make the file size smaller and therefore better for recordings.

A practical use for this API that I thought of would be taking screenshots of your terminal. That's exactly what you can do with this API. For any developer who might have a use for this API: a neat feature (actually the whole point of the design) is that it records each point on the screen in following format: character, background color, and text color. So with that said, you can use this API to see what is written to the screen.


Here are the functions that come with this API:
SpoilerinitFrameEnvironment() - Inititalizes the _G.frameEnvironment table.

frameEnvironment.getCurrentFrame() - Returns the current frame (whatever is currently in the screen buffer) and the current system time (os.clock()).

frameEnvironment.drawFrame (frame) - Draws the given frame object. No return value (besides nil :P/>)

Global variables:
_G.frameEnvironment - This is where all of the frame related functions and data are stored globally.

_G.frameEnvironment.screenBuffer - This is what is actually recording all of the "cells" on the screen at tables with the indexes of their coordinates on the screen: screenBuffer[y][x] = {text, backgroundColor, textColor}

_G.frameEnvironment.screenBuffer.cursorBlink - The current state of the cursor blinking.
_G.frameEnvironment.screenBuffer.backgroundColor - The current background color of the terminal.
_G.frameEnvironment.screenBuffer.textColor - The current text color of the terminal.

Here's the code:
Pastebin: http://pastebin.com/uCsPTDdi
Spoiler


--[[
	Frames	  Trystan Cannon
				12 February 2013

	This is a redesign of an API
	which I had written and didn't
	function properly because of the
	faulty design.

	This API implements a method of recording
	the screen in frames. However, saving
	an entire recording isn't practical because
	of how large the file size would be.

	A decent use for this API is to take
	screenshots in game.
]]--


-- Returns the true size of a table using pairs().
local function getTableSize (myTable)
	local size = 0

	for _, __ in pairs (myTable) do
		size = size + 1
	end

	return size
end

-- Hooks the given screen buffer to the current terminal API.
function hookTerminal (screenBuffer)
	local hookedTerminal = {}
	for index, item in pairs (term.native) do
		hookedTerminal[index] = item
	end


	-- TODO: Implement this function!
	hookedTerminal["scroll"] = function (linesToScroll)
		local lines = {}

		for line = linesToScroll + 1, screenBuffer.screenHeight do
			lines[#lines + 1] = screenBuffer[line]
		end
		-- Fill in any remaining lines with empty space.
		for line = (getTableSize (lines) == 1 and getTableSize (lines) or 1), screenBuffer.screenHeight do
			lines[#lines + 1] = {}

			for xPos = 1, screenBuffer.screenWidth do
				lines[#lines][xPos] = {text = ' ', backgroundColor = colors.black, textColor = colors.white}
			end
		end

		-- Insert the lines table as the current screen buffer lines.
		for line = 1, screenBuffer.screenHeight do
			screenBuffer[line] = lines[line]
		end
		return term.native.scroll (linesToScroll)
	end

	hookedTerminal["clearLine"] = function()
		local _, line = term.native.getCursorPos()

		-- Clear the line by replacing every cell in it with spaces.
		for xPos = 1, screenBuffer.screenWidth do
			screenBuffer[line][xPos] = {text = ' ', backgroundColor = screenBuffer.backgroundColor, textColor = screenBuffer.textColor}
		end

		return term.native.clearLine()
	end

	hookedTerminal["clear"] = function()
		-- Clear the screen buffer by, instead of dumping it, replace every line with spaces.
		for line = 1, screenBuffer.screenHeight do
			for xPos = 1, screenBuffer.screenWidth do
				screenBuffer[line][xPos] = {text = ' ', backgroundColor = screenBuffer.backgroundColor, textColor = screenBuffer.textColor}
			end
		end

		return term.native.clear()
	end

	hookedTerminal["setTextColor"] = function (textColor)
		screenBuffer.textColor = textColor
		return term.native.setTextColor (textColor)
	end

	hookedTerminal["setBackgroundColor"] = function (backgroundColor)
		screenBuffer.backgroundColor = backgroundColor
		return term.native.setBackgroundColor (backgroundColor)
	end

	hookedTerminal["setCursorBlink"] = function (cursorBlink)
		screenBuffer.cursorBlink = cursorBlink
		return term.native.setCursorBlink (cursorBlink)
	end

	hookedTerminal["write"] = function (text)
		local currentX, currentY = term.native.getCursorPos()
		local currentX_offset	= currentX
		local backgroundColor	= screenBuffer.backgroundColor
		local textColor		  = screenBuffer.textColor

		local subOffset = 1
		while currentX < currentX_offset + text:len() do
			screenBuffer[currentY][currentX] = {text = text:sub (subOffset, subOffset), backgroundColor = backgroundColor, textColor = textColor}

			subOffset = subOffset + 1
			currentX  = currentX  + 1
		end

		return term.native.write (text)
	end

	term.redirect (hookedTerminal)
end

-- Initializes the frame environment.
function initFrameEnvironment()
	local screenWidth, screenHeight = term.getSize()
	_G.frameEnvironment			  = {}


	_G.frameEnvironment.screenBuffer = {
		cursorBlink	 = true,
		backgroundColor = colors.black,
		textColor	   = colors.white,
		screenWidth	 = screenWidth,
		screenHeight	= screenHeight
	}
	-- Initialize the screen buffer by adding all of the cell tables.
	for line = 1, _G.frameEnvironment.screenBuffer.screenHeight do
		_G.frameEnvironment.screenBuffer[line] = {}

		for xPos = 1, _G.frameEnvironment.screenBuffer.screenWidth do
			_G.frameEnvironment.screenBuffer[line][xPos] = {text = ' ', backgroundColor = _G.frameEnvironment.screenBuffer.backgroundColor, textColor = _G.frameEnvironment.screenBuffer.textColor}
		end
	end


	-- Returns a copy of the screen buffer and the current os.clock() time. This is a frame.
	-- NOTE: A frame object always has a 'cursorBlink' field too!
	_G.frameEnvironment.getCurrentFrame = function()
		local currentX, currentY = term.native.getCursorPos()

		local currentFrame = {
			cursorBlink = _G.frameEnvironment.screenBuffer.cursorBlink,
			cursorPos   = {x = currentX, y = currentY}
		}

		for line = 1, _G.frameEnvironment.screenBuffer.screenHeight do
			currentFrame[line] = {}

			for xPos = 1, _G.frameEnvironment.screenBuffer.screenWidth do
				currentFrame[line][xPos] = {}

				for index, item in pairs (_G.frameEnvironment.screenBuffer[line][xPos]) do
					currentFrame[line][xPos][index] = item
				end
			end
		end

		return currentFrame, os.clock()
	end

	-- Draws the given frame.
	-- NOTE: This function does not return the cursor position, blink, or screen colors to their original state!
	_G.frameEnvironment.drawFrame = function (frame)
		term.native.setCursorBlink (false)

		for line = 1, _G.frameEnvironment.screenBuffer.screenHeight do
			for xPos = 1, _G.frameEnvironment.screenBuffer.screenWidth do
				local cell = frame[line][xPos]

				if getTableSize (cell) > 0 then
					term.native.setCursorPos (xPos, line)
					term.native.setBackgroundColor (cell.backgroundColor)
					term.native.setTextColor (cell.textColor)
					term.write (cell.text)
				end
			end
		end

		term.native.setCursorBlink (frame.cursorBlink)
		term.native.setCursorPos (frame.cursorPos.x, frame.cursorPos.y)
	end



	-- Ensure that the terminal API is writing to the screen buffer by hooking the screen buffer to the terminal API.
	hookTerminal (_G.frameEnvironment.screenBuffer)
end

You have permission to use this in any way that you'd like, but please give credit where it is due. (it would also be nice if you let me know just so I could feel all warm and fuzzy inside ;)/>)