def bounding_boxes(self, mode='fraction', output='dict'):
        """Get the bounding boxes of the labels on a page.

        Parameters
        ----------
        mode: 'fraction', 'actual'
            If 'fraction', the bounding boxes are expressed as a fraction of the
            height and width of the sheet. If 'actual', they are the actual
            position of the labels in millimetres from the top-left of the
            sheet.
        output: 'dict', 'json'
            If 'dict', a dictionary with label identifier tuples (row, column)
            as keys and a dictionary with 'left', 'right', 'top', and 'bottom'
            entries as the values.
            If 'json', a JSON encoded string which represents a dictionary with
            keys of the string format 'rowxcolumn' and each value being a
            bounding box dictionary with 'left', 'right', 'top', and 'bottom'
            entries.

        Returns
        -------
        The bounding boxes in the format set by the output parameter.

        """
        boxes = {}

        # Check the parameters.
        if mode not in ('fraction', 'actual'):
            raise ValueError("Unknown mode {0}.".format(mode))
        if output not in ('dict', 'json'):
            raise ValueError("Unknown output {0}.".format(output))

        # Iterate over the rows.
        for row in range(1, self.rows + 1):
            # Top and bottom of all labels in the row.
            top = self.top_margin + ((row - 1) * (self.label_height + self.row_gap))
            bottom = top + self.label_height

            # Now iterate over all columns in this row.
            for column in range(1, self.columns + 1):
                # Left and right position of this column.
                left = self.left_margin + ((column - 1) * (self.label_width + self.column_gap))
                right = left + self.label_width

                # Output in the appropriate mode format.
                if mode == 'fraction':
                    box = {
                        'top': top / self.sheet_height,
                        'bottom': bottom / self.sheet_height,
                        'left': left / self.sheet_width,
                        'right': right / self.sheet_width,
                    }
                elif mode == 'actual':
                    box = {'top': top, 'bottom': bottom, 'left': left, 'right': right}

                # Add to the collection.
                if output == 'json':
                    boxes['{0:d}x{1:d}'.format(row, column)] = box
                    box['top'] = float(box['top'])
                    box['bottom'] = float(box['bottom'])
                    box['left'] = float(box['left'])
                    box['right'] = float(box['right'])
                else:
                    boxes[(row, column)] = box

        # Done.
        if output == 'json':
            return json.dumps(boxes)
        return boxes