/*
* ImageBlock.java
* Transform
*
* Copyright (c) 2001-2010 Flagstone Software Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Flagstone Software Ltd. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.flagstone.transform.video;
import java.util.Arrays;
import com.flagstone.transform.coder.Copyable;
/**
* ImageBlock is used to sub-divide an image into a set of blocks so they can be
* streamed using Screen Video. Image blocks are compared so only pixel
* information for the portions of the image that change are sent.
*
* <p>
* An image is divided by tiling the blocks across the image from top-left to
* bottom right. If the image is not covered an integer number of blocks then
* the size of the blocks along the right and bottom edges of the image are
* reduced in size.
* </p>
*
* @see DefineVideo
*/
public final class ImageBlock implements Copyable<ImageBlock> {
/** Width of the block in pixels. */
private final transient int width;
/** Height of the block in pixels. */
private final transient int height;
/** The block pixels. */
private final transient byte[] block;
/**
* Create a new image block with the specified width and height and image
* data. The image is compressed using the zip format.
*
* @param blockWidth
* the width of the block in pixels.
* @param blockHeight
* the height of the block in pixels
* @param pixels
* the pixels covered by the block, compressed using the zip
* format.
*/
public ImageBlock(final int blockWidth, final int blockHeight,
final byte[] pixels) {
width = blockWidth;
height = blockHeight;
block = Arrays.copyOf(pixels, pixels.length);
}
/**
* Creates and initialises a ImageBlock object using the values copied
* from another ImageBlock object.
*
* @param object
* a ImageBlock object from which the values will be
* copied.
*/
public ImageBlock(final ImageBlock object) {
width = object.width;
height = object.height;
block = object.block;
}
/**
* Get the width of the block. although the block size is specified in
* parent ScreenVideoPacket object the actual block size used may vary if
* the tiled array of blocks overlaps the edge of the image.
*
* @return the width of the block.
*/
public int getWidth() {
return width;
}
/**
* Get the height of the block. although the block size is specified in
* parent ScreenVideoPacket object the actual block size used may vary if
* the tiled array of blocks overlaps the edge of the image.
*
* @return the height of the block.
*/
public int getHeight() {
return height;
}
/**
* Get the zipped image data for the block.
*
* @return a copy of the block data.
*/
public byte[] getBlock() {
return Arrays.copyOf(block, block.length);
}
/**
* When a ScreenVideo stream is created only the image blocks that change
* are included. The blocks that do not change are encoded as empty blocks
* which have width and height of zero and do not contain any image data.
* This convenience method is used to determine when an image block contains
* any valid image data.
*
* @return true if the block covers an area of the image that changed or
* false if no image data is included.
*/
public boolean isEmpty() {
return (width == 0) || (height == 0) || (block == null)
|| (block.length == 0);
}
/** {@inheritDoc} */
public ImageBlock copy() {
return new ImageBlock(this);
}
}