#include "pch.hpp"
//===========================================================================//
// File:	 Loader_BMP.cpp													 //
// Project:  GameOS					                                         //
// Contents: Used to load textures from .BMP files							 //
//---------------------------------------------------------------------------//
// Date      Who    Modification                                             //
// 06/02/99  AG     Created													 //
//---------------------------------------------------------------------------//
// Copyright (C) 1999 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
#include "Texture Manager.hpp"
#include "DXRasterizer.hpp"
#include "DirectX.hpp"
#include "MemoryManager.hpp"
#include "ijl.h"


//
// Jpeg reader functions
//
extern IJLERR (WINAPI* _ijlInit)( JPEG_CORE_PROPERTIES* jcprops );
extern IJLERR (WINAPI* _ijlFree)( JPEG_CORE_PROPERTIES* jcprops );
extern IJLERR (WINAPI* _ijlRead)( JPEG_CORE_PROPERTIES* jcprops, IJLIOTYPE iotype );

void DecodeJPGDimensions( const char* FileName, BYTE *Data, DWORD DataSize, DWORD* pTextureWidth, DWORD* pTextureHeight )
{
	LOG_BLOCK("Gos3D::Texture.DecodeJPGDimensions");
	JPEG_CORE_PROPERTIES jcp;
	if( IJL_OK != _ijlInit(&jcp) )
	{
		_ijlFree(&jcp);
		STOP(( "Problem reading %s",FileName ));
	}
	jcp.JPGBytes=Data;
	jcp.JPGSizeBytes=DataSize;

	if( IJL_OK != _ijlRead( &jcp, IJL_JBUFF_READPARAMS ) )
	{
		_ijlFree(&jcp);
		STOP(( "Problem reading %s",FileName ));
	}

	*pTextureWidth=jcp.JPGWidth;
	*pTextureHeight=jcp.JPGHeight;

	_ijlFree(&jcp);
}




//
// Read in a JPG file and return a 32bit memory surface containing it.
//
//
// pBitmap contains the JPG file
// Size is the length of the JPG file
//
void* DecodeJPG( const char* FileName, BYTE* Data, DWORD DataSize, DWORD* TextureWidth, DWORD* TextureHeight, bool TextureLoad, void *pDestSurf )
{
	LOG_BLOCK("Gos3D::Texture.DecodeJPG");
	IDirectDrawSurface7* DWSurface7=0;
	DDSURFACEDESC2 ddsd;
	JPEG_CORE_PROPERTIES jcp;
	DWORD* Memory=0;
	DWORD* Dest=0;
	DWORD Pitch=0;
	memset( &ddsd, 0, sizeof(ddsd) );

	if( IJL_OK != _ijlInit(&jcp) )
	{
		_ijlFree(&jcp);
		STOP(( "Problem reading %s",FileName ));
	}

	jcp.JPGBytes=Data;
	jcp.JPGSizeBytes=DataSize;

	if( IJL_OK != _ijlRead( &jcp, IJL_JBUFF_READPARAMS ) )
	{
		_ijlFree(&jcp);
		STOP(( "Problem reading %s",FileName ));
	}

	DWORD Width=jcp.JPGWidth;
	DWORD Height=jcp.JPGHeight;
//
// Create a buffer to read into
//
	BYTE* TempImage=(BYTE*)gos_Malloc( Width*Height*3, Heap_TextureOther );
//
// Setup pointers to surface
//
	jcp.DIBBytes=TempImage;
	jcp.DIBWidth=Width;
	jcp.DIBHeight=Height;
	jcp.DIBChannels=3;
	jcp.DIBColor=IJL_BGR;
	if( jcp.JPGChannels==1 )				// Load single channel JPG's as grey scale
		jcp.JPGColor=IJL_G;
	else
		jcp.JPGColor=IJL_YCBCR;
	jcp.DIBPadBytes=0;
//
// Read whole JPG image in
//
	if( IJL_OK != _ijlRead( &jcp, IJL_JBUFF_READWHOLEIMAGE ) )
	{
		_ijlFree(&jcp);
		STOP(( "Problem reading %s",FileName ));
	}
//
// Texture loading restrictions
//
	if( TextureLoad )
	{
		if( ((Width|Height)&(15|~2047L)) || (Width&(Width-1)) || (Height&(Height-1)) )
			STOP(( "Only power of 2 sized JPG files supported up to 1024*1024 '%s' (%d,%d)",FileName,Width,Height ));
		if( pDestSurf )
		{
			DWSurface7 = (IDirectDrawSurface7*)pDestSurf;
		}
		else
		{
//
// Setup format of the DWORD version of the system memory image
//
			ddsd.dwSize								= sizeof(ddsd);
			ddsd.dwFlags							= DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
			ddsd.ddsCaps.dwCaps						= DDSCAPS_SYSTEMMEMORY | DDSCAPS_TEXTURE;
			ddsd.dwWidth							= Width;
			ddsd.dwHeight							= Height;
			ddsd.ddpfPixelFormat.dwSize				= sizeof(DDPIXELFORMAT);
			ddsd.ddpfPixelFormat.dwFlags			= DDPF_RGB;
			ddsd.ddpfPixelFormat.dwRGBBitCount		= 32;
			ddsd.ddpfPixelFormat.dwRGBAlphaBitMask	= 0xff000000;
			ddsd.ddpfPixelFormat.dwRBitMask			= 0x00ff0000;
			ddsd.ddpfPixelFormat.dwGBitMask			= 0x0000ff00;
			ddsd.ddpfPixelFormat.dwBBitMask			= 0x000000ff;
//
// Create system memory surface
//
			wCreateSurface( DDobject, &ddsd, &DWSurface7, NULL );
//
// Calculate memory useage
//
			gos_ChangeHeapSize( Heap_TextureOther, Width*Height*4, 1 );
		}
//
// Lock the surface and get pointer to the top left
//
		ddsd.dwSize = sizeof(ddsd);
		wLock( DWSurface7, NULL, &ddsd, DDLOCK_NOSYSLOCK | DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL );
		Dest=(DWORD*)ddsd.lpSurface;
		Pitch=ddsd.lPitch>>2;
	}
	else
//
// Loading into a memory surface
//
	{
		Memory=Dest=(DWORD*)gos_Malloc(Width*Height*4, Heap_TextureOther); 
		Pitch=Width;
	}
//
// Copy the 3 pixel RGB image into the ARGB DirectDraw surface
//
	BYTE* Source=TempImage;
	for( int y=0; y<Height; y++ )
	{
		for( int x=0; x<Width; x++ )
		{
			*Dest++=*Source+(*(Source+1)<<8)+(*(Source+2)<<16)+0xff000000;
			Source+=3;
		}
		Dest=Dest-Width+Pitch;
	}
//
// Get rid of temp buffer
//
	gos_Free( TempImage );
//
// Update structure with information about surface
//
	*TextureWidth=Width;
	*TextureHeight=Height;
//
// Shut down JPG reader
//
	_ijlFree(&jcp);
//
// Loading into a texture?
//
	if( TextureLoad )
	{
		wUnlock( DWSurface7, NULL );
		return (void*)DWSurface7;
	}
	else
	{
		return (void*)Memory;
	}
}



