int
avtImageReader::Read(char *input)
{
    int  size = 0;

    //
    // Find out how long the image is.
    //
    int  length;
    memcpy(&length, input, sizeof(int));
    input += sizeof(int); size += sizeof(int);
 
    //
    // Save the image as one of our data members.
    //
    imgRep = avtImageRepresentation(input, length);
    size += length;

    haveReadImage = false;

    GetOutputImage() = imgRep;
    return size;
}
avtImage_p
avtMultiWindowSaver::CreateImage()
{
    //
    // Create a vtkImageData object to contain the tiled image.
    //
    const int nColorComponents = 3;
    vtkImageData *newImage = vtkImageData::New();
    newImage->SetDimensions(width, height, 1);
    newImage->AllocateScalars(VTK_UNSIGNED_CHAR, nColorComponents);
    unsigned char *out_ptr = (unsigned char *)newImage->GetScalarPointer();

    int nLayers = 16;
    for (int j = nLayers-1 ; j >= 0 ; j--)
    {
        for (int i = 0 ; i < 16 ; i++)
        {
            SaveSubWindowAttributes winAtts = atts.GetAttsForWindow(i+1);
            if (winAtts.GetLayer() != j || winAtts.GetOmitWindow())
                continue;
            if (*(images[i]) == NULL)
                continue;

            int imgWidth = 0, imgHeight = 0;
            images[i]->GetImage().GetSize(&imgHeight, &imgWidth);
            if (imgWidth != winAtts.GetSize()[0] || imgHeight != winAtts.GetSize()[1])
            {
                EXCEPTION1(VisItException, "The image passed in to the multi-window save is "
                            "incorrectly sized.  This is an internal error.");
            }

            int *pos = winAtts.GetPosition();
            float t = winAtts.GetTransparency();
            vtkImageData *img = images[i]->GetImage().GetImageVTK();
            unsigned char *in_ptr = (unsigned char *)img->GetScalarPointer();
            for (int h = 0 ; h < imgHeight ; h++)
            {
                int hh = h+pos[1];
                if (hh < 0 || hh >= height)
                    continue;
                for (int w = 0 ; w < imgWidth ; w++)
                {
                    int ww = w+pos[0];
                    if (ww < 0 || ww >= width)
                        continue;
                    int indexOut = hh*width   + ww;
                    int indexIn  = h*imgWidth + w;
                    if (t == 0.0)
                    {
                        out_ptr[3*indexOut+0] = in_ptr[3*indexIn+0];
                        out_ptr[3*indexOut+1] = in_ptr[3*indexIn+1];
                        out_ptr[3*indexOut+2] = in_ptr[3*indexIn+2];
                    }
                    else
                    {
                        out_ptr[3*indexOut+0] = (1-t)*in_ptr[3*indexIn+0]+
                                                   t *out_ptr[3*indexOut+0];
                        out_ptr[3*indexOut+1] = (1-t)*in_ptr[3*indexIn+1]+
                                                   t *out_ptr[3*indexOut+1];
                        out_ptr[3*indexOut+2] = (1-t)*in_ptr[3*indexIn+2]+
                                                   t *out_ptr[3*indexOut+2];
                    }
                }
            }
        }
    }

    //
    // Now that we have a vtkImageData object, wrap it in something AVT likes.
    //
    avtImage_p retval = new avtImage(0);
    retval->GetImage() = avtImageRepresentation(newImage);
    newImage->Delete();

    return retval;
}