/******************************************************************************
 * $Id: gvraster.cpp,v 1.1 1999/01/11 15:27:24 warmerda Exp $
 *
 * Name:     gvraster.cpp
 * Project:  GDAL Qt Viewer
 * Purpose:  Raster display layer implementation.
 * Author:   Frank Warmerdam, warmerda@home.com
 *
 ******************************************************************************
 * Copyright (c) 1999, Frank Warmerdam
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 ******************************************************************************
 *
 * $Log: gvraster.cpp,v $
 * Revision 1.1  1999/01/11 15:27:24  warmerda
 * New
 *
 */

#include "gview.h"

/************************************************************************/
/*                              GVRaster()                              */
/************************************************************************/

GVRaster::GVRaster( GDALDatasetH hDSIn,
                    int nBandRed, int nBandGreen, int nBandBlue )

{
    hDS = hDSIn;

    hRed = GDALGetRasterBand( hDS, nBandRed );
    hGreen = GDALGetRasterBand( hDS, nBandGreen );
    hBlue = GDALGetRasterBand( hDS, nBandBlue );

    nXOff = nYOff = nXSize = nYSize = 0;
    
    eDataType = GDALGetRasterDataType( hRed );

    pRedData = pGreenData = pBlueData = NULL;
    poImage = NULL;

    SetView( 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS) );
}

/************************************************************************/
/*                             ~GVRaster()                              */
/************************************************************************/

GVRaster::~GVRaster()

{
    CPLFree( pRedData );
    CPLFree( pGreenData );
    CPLFree( pBlueData );

    if( poImage != NULL )
        delete poImage;
}

/************************************************************************/
/*                              SetView()                               */
/************************************************************************/

void GVRaster::SetView( int nXOffIn, int nYOffIn, int nXSizeIn, int nYSizeIn )

{
    if( nXOff == nXOffIn
        && nYOff == nYOffIn
        && nXSize == nXSizeIn 
        && nYSize == nYSizeIn )
    {
        return;
    }

    if( pRedData != NULL )
    {
        CPLFree( pRedData );
        CPLFree( pGreenData );
        CPLFree( pBlueData );
        pBlueData = pGreenData = pRedData = NULL;
    }

    if( poImage != NULL )
    {
        delete poImage;
        poImage = NULL;
    }

    nXOff = nXOffIn;
    nYOff = nYOffIn;
    nXSize = nXSizeIn;
    nYSize = nYSizeIn;
}

/************************************************************************/
/*                             GetQImage()                              */
/************************************************************************/

QImage *GVRaster::GetQImage()

{
    int		nBytesPerPixel;
    
/* -------------------------------------------------------------------- */
/*      If we have an existing OK raster, just return it.               */
/* -------------------------------------------------------------------- */
    if( poImage != NULL )
        return poImage;

/* -------------------------------------------------------------------- */
/*      Allocate a data buffer, and read into it.                       */
/* -------------------------------------------------------------------- */
    nBytesPerPixel = GDALGetDataTypeSize(eDataType) / 8;
   
    pRedData = (void *) CPLMalloc(nBytesPerPixel * nXSize * nYSize);
    pGreenData = (void *) CPLMalloc(nBytesPerPixel * nXSize * nYSize);
    pBlueData = (void *) CPLMalloc(nBytesPerPixel * nXSize * nYSize);

    GDALRasterIO( hRed, GF_Read, nXOff, nYOff, nXSize, nYSize,
                  pRedData, nXSize, nYSize, eDataType, 0, 0 );
    GDALRasterIO( hGreen, GF_Read, nXOff, nYOff, nXSize, nYSize,
                  pGreenData, nXSize, nYSize, eDataType, 0, 0 );
    GDALRasterIO( hBlue, GF_Read, nXOff, nYOff, nXSize, nYSize,
                  pBlueData, nXSize, nYSize, eDataType, 0, 0 );
                  
/* -------------------------------------------------------------------- */
/*      Allocate the QImage, and compute it.                            */
/* -------------------------------------------------------------------- */
    int		iScanline;
    
    poImage = new QImage( nXSize, nYSize, 32 );

    for( iScanline = 0; iScanline < nYSize; iScanline++ )
    {
        QRgb	*panRGBA = (QRgb *) poImage->scanLine( iScanline );
        int	iPixel;
        
        if( eDataType == GDT_Byte )
        {
            GByte	*pabyRed, *pabyGreen, *pabyBlue;

            pabyRed = ((GByte *) pRedData) + iScanline * nXSize;
            pabyGreen = ((GByte *) pGreenData) + iScanline * nXSize;
            pabyBlue = ((GByte *) pBlueData) + iScanline * nXSize;
            
            for( iPixel = 0; iPixel < nXSize; iPixel++ )
            {
                *(panRGBA++) = qRgb( *(pabyRed++),
                                     *(pabyGreen++),
                                     *(pabyBlue++) );
            }
        }
        else
            CPLAssert( FALSE );
    }

    return poImage;
}

