#include "imagelib.h"
-const int KTX_TYPE_UNSIGNED_BYTE = 0x1401;
-const int KTX_TYPE_UNSIGNED_SHORT_4_4_4_4 = 0x8033;
-const int KTX_TYPE_UNSIGNED_SHORT_5_5_5_1 = 0x8034;
-const int KTX_TYPE_UNSIGNED_SHORT_5_6_5 = 0x8363;
-
-const int KTX_FORMAT_ALPHA = 0x1906;
-const int KTX_FORMAT_RGB = 0x1907;
-const int KTX_FORMAT_RGBA = 0x1908;
-const int KTX_FORMAT_LUMINANCE = 0x1909;
-const int KTX_FORMAT_LUMINANCE_ALPHA = 0x190A;
-const int KTX_FORMAT_BGR = 0x80E0;
-const int KTX_FORMAT_BGRA = 0x80E1;
-
-const int KTX_FORMAT_ETC1_RGB8 = 0x8D64;
-
-class KTX_Decoder
-{
+const int KTX_TYPE_UNSIGNED_BYTE = 0x1401;
+const int KTX_TYPE_UNSIGNED_SHORT_4_4_4_4 = 0x8033;
+const int KTX_TYPE_UNSIGNED_SHORT_5_5_5_1 = 0x8034;
+const int KTX_TYPE_UNSIGNED_SHORT_5_6_5 = 0x8363;
+
+const int KTX_FORMAT_ALPHA = 0x1906;
+const int KTX_FORMAT_RGB = 0x1907;
+const int KTX_FORMAT_RGBA = 0x1908;
+const int KTX_FORMAT_LUMINANCE = 0x1909;
+const int KTX_FORMAT_LUMINANCE_ALPHA = 0x190A;
+const int KTX_FORMAT_BGR = 0x80E0;
+const int KTX_FORMAT_BGRA = 0x80E1;
+
+const int KTX_FORMAT_ETC1_RGB8 = 0x8D64;
+
+class KTX_Decoder {
public:
- virtual ~KTX_Decoder() = default;
- virtual void Decode( PointerInputStream& istream, byte* out ) = 0;
- virtual unsigned int GetPixelSize() = 0;
+ virtual ~KTX_Decoder() = default;
+
+ virtual void Decode(PointerInputStream &istream, byte *out) = 0;
+
+ virtual unsigned int GetPixelSize() = 0;
};
-class KTX_Decoder_A8 : public KTX_Decoder
-{
+class KTX_Decoder_A8 : public KTX_Decoder {
public:
- virtual void Decode( PointerInputStream& istream, byte* out ){
- out[0] = out[1] = out[2] = 0;
- out[3] = istream_read_byte( istream );
- }
- virtual unsigned int GetPixelSize(){
- return 1;
- }
+ virtual void Decode(PointerInputStream &istream, byte *out)
+ {
+ out[0] = out[1] = out[2] = 0;
+ out[3] = istream_read_byte(istream);
+ }
+
+ virtual unsigned int GetPixelSize()
+ {
+ return 1;
+ }
};
-class KTX_Decoder_RGB8 : public KTX_Decoder
-{
+class KTX_Decoder_RGB8 : public KTX_Decoder {
public:
- virtual void Decode( PointerInputStream& istream, byte* out ){
- istream.read( out, 3 );
- out[3] = 255;
- }
- virtual unsigned int GetPixelSize(){
- return 3;
- }
+ virtual void Decode(PointerInputStream &istream, byte *out)
+ {
+ istream.read(out, 3);
+ out[3] = 255;
+ }
+
+ virtual unsigned int GetPixelSize()
+ {
+ return 3;
+ }
};
-class KTX_Decoder_RGBA8 : public KTX_Decoder
-{
+class KTX_Decoder_RGBA8 : public KTX_Decoder {
public:
- virtual void Decode( PointerInputStream& istream, byte* out ){
- istream.read( out, 4 );
- }
- virtual unsigned int GetPixelSize(){
- return 4;
- }
+ virtual void Decode(PointerInputStream &istream, byte *out)
+ {
+ istream.read(out, 4);
+ }
+
+ virtual unsigned int GetPixelSize()
+ {
+ return 4;
+ }
};
-class KTX_Decoder_L8 : public KTX_Decoder
-{
+class KTX_Decoder_L8 : public KTX_Decoder {
public:
- virtual void Decode( PointerInputStream& istream, byte* out ){
- byte l = istream_read_byte( istream );
- out[0] = out[1] = out[2] = l;
- out[3] = 255;
- }
- virtual unsigned int GetPixelSize(){
- return 1;
- }
+ virtual void Decode(PointerInputStream &istream, byte *out)
+ {
+ byte l = istream_read_byte(istream);
+ out[0] = out[1] = out[2] = l;
+ out[3] = 255;
+ }
+
+ virtual unsigned int GetPixelSize()
+ {
+ return 1;
+ }
};
-class KTX_Decoder_LA8 : public KTX_Decoder
-{
+class KTX_Decoder_LA8 : public KTX_Decoder {
public:
- virtual void Decode( PointerInputStream& istream, byte* out ){
- byte la[2];
- istream.read( la, 2 );
- out[0] = out[1] = out[2] = la[0];
- out[3] = la[1];
- }
- virtual unsigned int GetPixelSize(){
- return 2;
- }
+ virtual void Decode(PointerInputStream &istream, byte *out)
+ {
+ byte la[2];
+ istream.read(la, 2);
+ out[0] = out[1] = out[2] = la[0];
+ out[3] = la[1];
+ }
+
+ virtual unsigned int GetPixelSize()
+ {
+ return 2;
+ }
};
-class KTX_Decoder_BGR8 : public KTX_Decoder
-{
+class KTX_Decoder_BGR8 : public KTX_Decoder {
public:
- virtual void Decode( PointerInputStream& istream, byte* out ){
- byte bgr[3];
- istream.read( bgr, 3 );
- out[0] = bgr[2];
- out[1] = bgr[1];
- out[2] = bgr[0];
- out[3] = 255;
- }
- virtual unsigned int GetPixelSize(){
- return 3;
- }
+ virtual void Decode(PointerInputStream &istream, byte *out)
+ {
+ byte bgr[3];
+ istream.read(bgr, 3);
+ out[0] = bgr[2];
+ out[1] = bgr[1];
+ out[2] = bgr[0];
+ out[3] = 255;
+ }
+
+ virtual unsigned int GetPixelSize()
+ {
+ return 3;
+ }
};
-class KTX_Decoder_BGRA8 : public KTX_Decoder
-{
+class KTX_Decoder_BGRA8 : public KTX_Decoder {
public:
- virtual void Decode( PointerInputStream& istream, byte* out ){
- byte bgra[4];
- istream.read( bgra, 4 );
- out[0] = bgra[2];
- out[1] = bgra[1];
- out[2] = bgra[0];
- out[3] = bgra[3];
- }
- virtual unsigned int GetPixelSize(){
- return 4;
- }
+ virtual void Decode(PointerInputStream &istream, byte *out)
+ {
+ byte bgra[4];
+ istream.read(bgra, 4);
+ out[0] = bgra[2];
+ out[1] = bgra[1];
+ out[2] = bgra[0];
+ out[3] = bgra[3];
+ }
+
+ virtual unsigned int GetPixelSize()
+ {
+ return 4;
+ }
};
-class KTX_Decoder_RGBA4 : public KTX_Decoder
-{
+class KTX_Decoder_RGBA4 : public KTX_Decoder {
protected:
- bool m_bigEndian;
+ bool m_bigEndian;
public:
- KTX_Decoder_RGBA4( bool bigEndian ) : m_bigEndian( bigEndian ){}
- virtual void Decode( PointerInputStream& istream, byte* out ){
- uint16_t rgba;
- if ( m_bigEndian ) {
- rgba = istream_read_uint16_be( istream );
- }
- else {
- rgba = istream_read_uint16_le( istream );
- }
- int r = ( rgba >> 12 ) & 0xf;
- int g = ( rgba >> 8 ) & 0xf;
- int b = ( rgba >> 4 ) & 0xf;
- int a = rgba & 0xf;
- out[0] = ( r << 4 ) | r;
- out[1] = ( g << 4 ) | g;
- out[2] = ( b << 4 ) | b;
- out[3] = ( a << 4 ) | a;
- }
- virtual unsigned int GetPixelSize(){
- return 2;
- }
+ KTX_Decoder_RGBA4(bool bigEndian) : m_bigEndian(bigEndian)
+ {}
+
+ virtual void Decode(PointerInputStream &istream, byte *out)
+ {
+ uint16_t rgba;
+ if (m_bigEndian) {
+ rgba = istream_read_uint16_be(istream);
+ } else {
+ rgba = istream_read_uint16_le(istream);
+ }
+ int r = (rgba >> 12) & 0xf;
+ int g = (rgba >> 8) & 0xf;
+ int b = (rgba >> 4) & 0xf;
+ int a = rgba & 0xf;
+ out[0] = (r << 4) | r;
+ out[1] = (g << 4) | g;
+ out[2] = (b << 4) | b;
+ out[3] = (a << 4) | a;
+ }
+
+ virtual unsigned int GetPixelSize()
+ {
+ return 2;
+ }
};
-class KTX_Decoder_RGBA5 : public KTX_Decoder
-{
+class KTX_Decoder_RGBA5 : public KTX_Decoder {
protected:
- bool m_bigEndian;
+ bool m_bigEndian;
public:
- KTX_Decoder_RGBA5( bool bigEndian ) : m_bigEndian( bigEndian ){}
- virtual void Decode( PointerInputStream& istream, byte* out ){
- uint16_t rgba;
- if ( m_bigEndian ) {
- rgba = istream_read_uint16_be( istream );
- }
- else {
- rgba = istream_read_uint16_le( istream );
- }
- int r = ( rgba >> 11 ) & 0x1f;
- int g = ( rgba >> 6 ) & 0x1f;
- int b = ( rgba >> 1 ) & 0x1f;
- out[0] = ( r << 3 ) | ( r >> 2 );
- out[1] = ( g << 3 ) | ( g >> 2 );
- out[2] = ( b << 3 ) | ( b >> 2 );
- out[3] = ( rgba & 1 ) * 255;
- }
- virtual unsigned int GetPixelSize(){
- return 2;
- }
+ KTX_Decoder_RGBA5(bool bigEndian) : m_bigEndian(bigEndian)
+ {}
+
+ virtual void Decode(PointerInputStream &istream, byte *out)
+ {
+ uint16_t rgba;
+ if (m_bigEndian) {
+ rgba = istream_read_uint16_be(istream);
+ } else {
+ rgba = istream_read_uint16_le(istream);
+ }
+ int r = (rgba >> 11) & 0x1f;
+ int g = (rgba >> 6) & 0x1f;
+ int b = (rgba >> 1) & 0x1f;
+ out[0] = (r << 3) | (r >> 2);
+ out[1] = (g << 3) | (g >> 2);
+ out[2] = (b << 3) | (b >> 2);
+ out[3] = (rgba & 1) * 255;
+ }
+
+ virtual unsigned int GetPixelSize()
+ {
+ return 2;
+ }
};
-class KTX_Decoder_RGB5 : public KTX_Decoder
-{
+class KTX_Decoder_RGB5 : public KTX_Decoder {
protected:
- bool m_bigEndian;
+ bool m_bigEndian;
public:
- KTX_Decoder_RGB5( bool bigEndian ) : m_bigEndian( bigEndian ){}
- virtual void Decode( PointerInputStream& istream, byte* out ){
- uint16_t rgb;
- if ( m_bigEndian ) {
- rgb = istream_read_uint16_be( istream );
- }
- else {
- rgb = istream_read_uint16_le( istream );
- }
- int r = ( rgb >> 11 ) & 0x1f;
- int g = ( rgb >> 5 ) & 0x3f;
- int b = rgb & 0x1f;
- out[0] = ( r << 3 ) | ( r >> 2 );
- out[1] = ( g << 2 ) | ( g >> 4 );
- out[2] = ( b << 3 ) | ( b >> 2 );
- out[3] = 255;
- }
- virtual unsigned int GetPixelSize(){
- return 2;
- }
+ KTX_Decoder_RGB5(bool bigEndian) : m_bigEndian(bigEndian)
+ {}
+
+ virtual void Decode(PointerInputStream &istream, byte *out)
+ {
+ uint16_t rgb;
+ if (m_bigEndian) {
+ rgb = istream_read_uint16_be(istream);
+ } else {
+ rgb = istream_read_uint16_le(istream);
+ }
+ int r = (rgb >> 11) & 0x1f;
+ int g = (rgb >> 5) & 0x3f;
+ int b = rgb & 0x1f;
+ out[0] = (r << 3) | (r >> 2);
+ out[1] = (g << 2) | (g >> 4);
+ out[2] = (b << 3) | (b >> 2);
+ out[3] = 255;
+ }
+
+ virtual unsigned int GetPixelSize()
+ {
+ return 2;
+ }
};
-static void KTX_DecodeETC1( PointerInputStream& istream, Image& image ){
- unsigned int width = image.getWidth(), height = image.getHeight();
- unsigned int stride = width * 4;
- byte* pixbuf = image.getRGBAPixels();
- byte etc[8], rgba[64];
-
- for ( unsigned int y = 0; y < height; y += 4, pixbuf += stride * 4 )
- {
- unsigned int blockrows = height - y;
- if ( blockrows > 4 ) {
- blockrows = 4;
- }
-
- byte* p = pixbuf;
- for ( unsigned int x = 0; x < width; x += 4, p += 16 )
- {
- istream.read( etc, 8 );
- ETC_DecodeETC1Block( etc, rgba, qtrue );
-
- unsigned int blockrowsize = width - x;
- if ( blockrowsize > 4 ) {
- blockrowsize = 4;
- }
- blockrowsize *= 4;
- for ( unsigned int blockrow = 0; blockrow < blockrows; blockrow++ )
- {
- memcpy( p + blockrow * stride, rgba + blockrow * 16, blockrowsize );
- }
- }
- }
+static void KTX_DecodeETC1(PointerInputStream &istream, Image &image)
+{
+ unsigned int width = image.getWidth(), height = image.getHeight();
+ unsigned int stride = width * 4;
+ byte *pixbuf = image.getRGBAPixels();
+ byte etc[8], rgba[64];
+
+ for (unsigned int y = 0; y < height; y += 4, pixbuf += stride * 4) {
+ unsigned int blockrows = height - y;
+ if (blockrows > 4) {
+ blockrows = 4;
+ }
+
+ byte *p = pixbuf;
+ for (unsigned int x = 0; x < width; x += 4, p += 16) {
+ istream.read(etc, 8);
+ ETC_DecodeETC1Block(etc, rgba, qtrue);
+
+ unsigned int blockrowsize = width - x;
+ if (blockrowsize > 4) {
+ blockrowsize = 4;
+ }
+ blockrowsize *= 4;
+ for (unsigned int blockrow = 0; blockrow < blockrows; blockrow++) {
+ memcpy(p + blockrow * stride, rgba + blockrow * 16, blockrowsize);
+ }
+ }
+ }
}
-Image* LoadKTXBuff( PointerInputStream& istream ){
- byte identifier[12];
- istream.read( identifier, 12 );
- if ( memcmp( identifier, "\xABKTX 11\xBB\r\n\x1A\n", 12 ) ) {
- globalErrorStream() << "LoadKTX: Image has the wrong identifier\n";
- return 0;
- }
-
- bool bigEndian = ( istream_read_uint32_le( istream ) == 0x01020304 );
-
- unsigned int type;
- if ( bigEndian ) {
- type = istream_read_uint32_be( istream );
- }
- else {
- type = istream_read_uint32_le( istream );
- }
-
- // For compressed textures, the format is in glInternalFormat.
- // For uncompressed textures, it's in glBaseInternalFormat.
- istream.seek( ( type ? 3 : 2 ) * sizeof( uint32_t ) );
- unsigned int format;
- if ( bigEndian ) {
- format = istream_read_uint32_be( istream );
- }
- else {
- format = istream_read_uint32_le( istream );
- }
- if ( !type ) {
- istream.seek( sizeof( uint32_t ) );
- }
-
- unsigned int width, height;
- if ( bigEndian ) {
- width = istream_read_uint32_be( istream );
- height = istream_read_uint32_be( istream );
- }
- else {
- width = istream_read_uint32_le( istream );
- height = istream_read_uint32_le( istream );
- }
- if ( !width ) {
- globalErrorStream() << "LoadKTX: Image has zero width\n";
- return 0;
- }
- if ( !height ) {
- height = 1;
- }
-
- // Skip the key/values and load the first 2D image in the texture.
- // Since KTXorientation is only a hint and has no effect on the texture data and coordinates, it must be ignored.
- istream.seek( 4 * sizeof( uint32_t ) );
- unsigned int bytesOfKeyValueData;
- if ( bigEndian ) {
- bytesOfKeyValueData = istream_read_uint32_be( istream );
- }
- else {
- bytesOfKeyValueData = istream_read_uint32_le( istream );
- }
- istream.seek( bytesOfKeyValueData + sizeof( uint32_t ) );
-
- RGBAImage* image = new RGBAImage( width, height );
-
- if ( type ) {
- KTX_Decoder* decoder = NULL;
- switch ( type )
- {
- case KTX_TYPE_UNSIGNED_BYTE:
- switch ( format )
- {
- case KTX_FORMAT_ALPHA:
- decoder = new KTX_Decoder_A8();
- break;
- case KTX_FORMAT_RGB:
- decoder = new KTX_Decoder_RGB8();
- break;
- case KTX_FORMAT_RGBA:
- decoder = new KTX_Decoder_RGBA8();
- break;
- case KTX_FORMAT_LUMINANCE:
- decoder = new KTX_Decoder_L8();
- break;
- case KTX_FORMAT_LUMINANCE_ALPHA:
- decoder = new KTX_Decoder_LA8();
- break;
- case KTX_FORMAT_BGR:
- decoder = new KTX_Decoder_BGR8();
- break;
- case KTX_FORMAT_BGRA:
- decoder = new KTX_Decoder_BGRA8();
- break;
- }
- break;
- case KTX_TYPE_UNSIGNED_SHORT_4_4_4_4:
- if ( format == KTX_FORMAT_RGBA ) {
- decoder = new KTX_Decoder_RGBA4( bigEndian );
- }
- break;
- case KTX_TYPE_UNSIGNED_SHORT_5_5_5_1:
- if ( format == KTX_FORMAT_RGBA ) {
- decoder = new KTX_Decoder_RGBA5( bigEndian );
- }
- break;
- case KTX_TYPE_UNSIGNED_SHORT_5_6_5:
- if ( format == KTX_FORMAT_RGB ) {
- decoder = new KTX_Decoder_RGB5( bigEndian );
- }
- break;
- }
-
- if ( !decoder ) {
- globalErrorStream() << "LoadKTX: Image has an unsupported pixel type " << type << " or format " << format << "\n";
- image->release();
- return 0;
- }
-
- unsigned int inRowLength = width * decoder->GetPixelSize();
- unsigned int inPadding = ( ( inRowLength + 3 ) & ~3 ) - inRowLength;
- byte* out = image->getRGBAPixels();
- for ( unsigned int y = 0; y < height; y++ )
- {
- for ( unsigned int x = 0; x < width; x++, out += 4 )
- {
- decoder->Decode( istream, out );
- }
-
- if ( inPadding ) {
- istream.seek( inPadding );
- }
- }
-
- delete decoder;
- }
- else {
- switch ( format )
- {
- case KTX_FORMAT_ETC1_RGB8:
- KTX_DecodeETC1( istream, *image );
- break;
- default:
- globalErrorStream() << "LoadKTX: Image has an unsupported compressed format " << format << "\n";
- image->release();
- return 0;
- }
- }
-
- return image;
+Image *LoadKTXBuff(PointerInputStream &istream)
+{
+ byte identifier[12];
+ istream.read(identifier, 12);
+ if (memcmp(identifier, "\xABKTX 11\xBB\r\n\x1A\n", 12)) {
+ globalErrorStream() << "LoadKTX: Image has the wrong identifier\n";
+ return 0;
+ }
+
+ bool bigEndian = (istream_read_uint32_le(istream) == 0x01020304);
+
+ unsigned int type;
+ if (bigEndian) {
+ type = istream_read_uint32_be(istream);
+ } else {
+ type = istream_read_uint32_le(istream);
+ }
+
+ // For compressed textures, the format is in glInternalFormat.
+ // For uncompressed textures, it's in glBaseInternalFormat.
+ istream.seek((type ? 3 : 2) * sizeof(uint32_t));
+ unsigned int format;
+ if (bigEndian) {
+ format = istream_read_uint32_be(istream);
+ } else {
+ format = istream_read_uint32_le(istream);
+ }
+ if (!type) {
+ istream.seek(sizeof(uint32_t));
+ }
+
+ unsigned int width, height;
+ if (bigEndian) {
+ width = istream_read_uint32_be(istream);
+ height = istream_read_uint32_be(istream);
+ } else {
+ width = istream_read_uint32_le(istream);
+ height = istream_read_uint32_le(istream);
+ }
+ if (!width) {
+ globalErrorStream() << "LoadKTX: Image has zero width\n";
+ return 0;
+ }
+ if (!height) {
+ height = 1;
+ }
+
+ // Skip the key/values and load the first 2D image in the texture.
+ // Since KTXorientation is only a hint and has no effect on the texture data and coordinates, it must be ignored.
+ istream.seek(4 * sizeof(uint32_t));
+ unsigned int bytesOfKeyValueData;
+ if (bigEndian) {
+ bytesOfKeyValueData = istream_read_uint32_be(istream);
+ } else {
+ bytesOfKeyValueData = istream_read_uint32_le(istream);
+ }
+ istream.seek(bytesOfKeyValueData + sizeof(uint32_t));
+
+ RGBAImage *image = new RGBAImage(width, height);
+
+ if (type) {
+ KTX_Decoder *decoder = NULL;
+ switch (type) {
+ case KTX_TYPE_UNSIGNED_BYTE:
+ switch (format) {
+ case KTX_FORMAT_ALPHA:
+ decoder = new KTX_Decoder_A8();
+ break;
+ case KTX_FORMAT_RGB:
+ decoder = new KTX_Decoder_RGB8();
+ break;
+ case KTX_FORMAT_RGBA:
+ decoder = new KTX_Decoder_RGBA8();
+ break;
+ case KTX_FORMAT_LUMINANCE:
+ decoder = new KTX_Decoder_L8();
+ break;
+ case KTX_FORMAT_LUMINANCE_ALPHA:
+ decoder = new KTX_Decoder_LA8();
+ break;
+ case KTX_FORMAT_BGR:
+ decoder = new KTX_Decoder_BGR8();
+ break;
+ case KTX_FORMAT_BGRA:
+ decoder = new KTX_Decoder_BGRA8();
+ break;
+ }
+ break;
+ case KTX_TYPE_UNSIGNED_SHORT_4_4_4_4:
+ if (format == KTX_FORMAT_RGBA) {
+ decoder = new KTX_Decoder_RGBA4(bigEndian);
+ }
+ break;
+ case KTX_TYPE_UNSIGNED_SHORT_5_5_5_1:
+ if (format == KTX_FORMAT_RGBA) {
+ decoder = new KTX_Decoder_RGBA5(bigEndian);
+ }
+ break;
+ case KTX_TYPE_UNSIGNED_SHORT_5_6_5:
+ if (format == KTX_FORMAT_RGB) {
+ decoder = new KTX_Decoder_RGB5(bigEndian);
+ }
+ break;
+ }
+
+ if (!decoder) {
+ globalErrorStream() << "LoadKTX: Image has an unsupported pixel type " << type << " or format " << format
+ << "\n";
+ image->release();
+ return 0;
+ }
+
+ unsigned int inRowLength = width * decoder->GetPixelSize();
+ unsigned int inPadding = ((inRowLength + 3) & ~3) - inRowLength;
+ byte *out = image->getRGBAPixels();
+ for (unsigned int y = 0; y < height; y++) {
+ for (unsigned int x = 0; x < width; x++, out += 4) {
+ decoder->Decode(istream, out);
+ }
+
+ if (inPadding) {
+ istream.seek(inPadding);
+ }
+ }
+
+ delete decoder;
+ } else {
+ switch (format) {
+ case KTX_FORMAT_ETC1_RGB8:
+ KTX_DecodeETC1(istream, *image);
+ break;
+ default:
+ globalErrorStream() << "LoadKTX: Image has an unsupported compressed format " << format << "\n";
+ image->release();
+ return 0;
+ }
+ }
+
+ return image;
}
-Image* LoadKTX( ArchiveFile& file ){
- ScopedArchiveBuffer buffer( file );
- PointerInputStream istream( buffer.buffer );
- return LoadKTXBuff( istream );
+Image *LoadKTX(ArchiveFile &file)
+{
+ ScopedArchiveBuffer buffer(file);
+ PointerInputStream istream(buffer.buffer);
+ return LoadKTXBuff(istream);
}