GXS.Graphics.pas 127 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit GXS.Graphics;
  5. (*
  6. Utility class and functions to manipulate a bitmap in OpenGL's default
  7. byte order (GL_RGBA vs TBitmap's GL_BGRA)
  8. Note: TgxBitmap32 has support for Alex Denissov's Graphics32 library
  9. (http://www.g32.org), just make sure the USE_GRAPHICS32 conditionnal
  10. is active in Scene.inc and recompile.
  11. *)
  12. interface
  13. {$I Stage.Defines.inc}
  14. uses
  15. Winapi.Windows,
  16. System.Classes,
  17. System.SysUtils,
  18. System.SyncObjs,
  19. System.UITypes,
  20. System.Math,
  21. FMX.Graphics,
  22. FMX.Dialogs,
  23. FMX.Types,
  24. FMX.Consts,
  25. {$IFDEF USE_GRAPHICS32}
  26. GR32,
  27. {$ENDIF}
  28. Stage.OpenGL4,
  29. Stage.VectorGeometry,
  30. Stage.Utils,
  31. Stage.TextureFormat,
  32. Stage.Strings,
  33. GXS.PersistentClasses,
  34. GXS.ApplicationFileIO,
  35. GXS.Context,
  36. GXS.ImageUtils,
  37. GXS.Color;
  38. type
  39. TgxPixel24 = packed record
  40. r, g, b: Byte;
  41. end;
  42. PgxPixel24 = ^TgxPixel24;
  43. TgxPixel32 = packed record
  44. r, g, b, a: Byte;
  45. end;
  46. PgxPixel32 = ^TgxPixel32;
  47. TgxPixel32Array = array[0..MaxInt shr 3] of TgxPixel32;
  48. PgxPixel32Array = ^TgxPixel32Array;
  49. TgxLODStreamingState = (ssKeeping, ssLoading, ssLoaded, ssTransfered);
  50. TgxImageLevelDesc = record
  51. Width: Integer;
  52. Height: Integer;
  53. Depth: Integer;
  54. PBO: TgxUnpackPBOHandle;
  55. MapAddress: Pointer;
  56. Offset: LongWord;
  57. StreamOffset: LongWord;
  58. Size: LongWord;
  59. State: TgxLODStreamingState;
  60. end;
  61. TgxImageLODRange = 0..15;
  62. TgxImagePiramid = array[TgxImageLODRange] of TgxImageLevelDesc;
  63. TgxBaseImage = class(TgxDataFile)
  64. private
  65. FSourceStream: TStream;
  66. FStreamLevel: TgxImageLODRange;
  67. FFinishEvent: TgxFinishTaskEvent;
  68. {$IFDEF USE_SERVICE_CONTEXT}
  69. procedure ImageStreamingTask; stdcall;
  70. {$ENDIF}
  71. protected
  72. fData: PgxPixel32Array;
  73. FLOD: TgxImagePiramid;
  74. fLevelCount: TgxImageLODRange;
  75. fColorFormat: Cardinal;
  76. fInternalFormat: TglInternalFormat;
  77. fDataType: Cardinal;
  78. fElementSize: Integer;
  79. fCubeMap: Boolean;
  80. fTextureArray: Boolean;
  81. function GetData: PgxPixel32Array; virtual;
  82. function GetWidth: Integer;
  83. function GetHeight: Integer;
  84. function GetDepth: Integer;
  85. function GetLevelAddress(ALevel: Byte): Pointer; overload;
  86. function GetLevelAddress(ALevel, AFace: Byte): Pointer; overload;
  87. function GetLevelWidth(ALOD: TgxImageLODRange): Integer;
  88. function GetLevelHeight(ALOD: TgxImageLODRange): Integer;
  89. function GetLevelDepth(ALOD: TgxImageLODRange): Integer;
  90. function GetLevelPBO(ALOD: TgxImageLODRange): TgxUnpackPBOHandle;
  91. function GetLevelOffset(ALOD: TgxImageLODRange): Integer;
  92. function GetLevelSizeInByte(ALOD: TgxImageLODRange): Integer;
  93. function GetLevelStreamingState(ALOD: TgxImageLODRange): TgxLODStreamingState;
  94. procedure SetLevelStreamingState(ALOD: TgxImageLODRange; AState: TgxLODStreamingState);
  95. procedure SaveHeader;
  96. procedure LoadHeader;
  97. procedure StartStreaming;
  98. procedure DoStreaming;
  99. public
  100. constructor Create; reintroduce; virtual;
  101. destructor Destroy; override;
  102. procedure Assign(Source: TPersistent); override;
  103. function GetTextureTarget: TGLTextureTarget;
  104. // Registers the bitmap's content as an OpenGL texture map.
  105. procedure RegisterAsOpenRXTexture(
  106. AHandle: TgxTextureHandle;
  107. aMipmapGen: Boolean;
  108. aTexFormat: NativeUInt;
  109. out texWidth: integer;
  110. out texHeight: integer;
  111. out texDepth: integer); virtual;
  112. // Assigns from any Texture.
  113. function AssignFromTexture(
  114. AHandle: TgxTextureHandle;
  115. const CastToFormat: Boolean;
  116. const intFormat: TglInternalFormat = tfRGBA8;
  117. const colorFormat: NativeUInt = 0;
  118. const dataType: NativeUInt = 0): Boolean; virtual;
  119. (* Convert vertical cross format of non compressed, non mipmaped image
  120. to six face of cube map *)
  121. function ConvertCrossToCubeMap: Boolean;
  122. // Convert flat image to volume by dividing it into slice.
  123. function ConvertToVolume(const col, row: Integer; const MakeArray: Boolean): Boolean;
  124. // Return size in byte of all image
  125. function DataSize: Cardinal;
  126. // True if the bitmap is empty (ie. width or height is zero).
  127. function IsEmpty: Boolean;
  128. function IsCompressed: Boolean;
  129. function IsVolume: Boolean;
  130. // Narrow image data to simple RGBA8 ubyte
  131. procedure Narrow;
  132. // Generate LOD pyramid
  133. procedure GenerateMipmap(AFilter: TImageFilterFunction); virtual;
  134. // Leave top level and remove other
  135. procedure UnMipmap; virtual;
  136. // Direct Access to image data
  137. property Data: PgxPixel32Array read GetData;
  138. // Set image of error.
  139. procedure SetErrorImage;
  140. // Recalculate levels information based on first level.
  141. procedure UpdateLevelsInfo;
  142. property LevelWidth[ALOD: TgxImageLODRange]: Integer
  143. read GetLevelWidth;
  144. property LevelHeight[ALOD: TgxImageLODRange]: Integer
  145. read GetLevelHeight;
  146. property LevelDepth[ALOD: TgxImageLODRange]: Integer
  147. read GetLevelDepth;
  148. property LevelPixelBuffer[ALOD: TgxImageLODRange]: TgxUnpackPBOHandle
  149. read GetLevelPBO;
  150. // LOD offset in byte
  151. property LevelOffset[ALOD: TgxImageLODRange]: Integer
  152. read GetLevelOffset;
  153. // LOD size in byte
  154. property LevelSizeInByte[ALOD: TgxImageLODRange]: Integer
  155. read GetLevelSizeInByte;
  156. property LevelStreamingState[ALOD: TgxImageLODRange]: TgxLODStreamingState
  157. read GetLevelStreamingState write SetLevelStreamingState;
  158. // Number of levels.
  159. property LevelCount: TgxImageLODRange read fLevelCount;
  160. property InternalFormat: TglInternalFormat read FInternalFormat;
  161. property ColorFormat: Cardinal read fColorFormat;
  162. property DataType: Cardinal read fDataType;
  163. property ElementSize: Integer read fElementSize;
  164. property CubeMap: Boolean read fCubeMap;
  165. property TextureArray: Boolean read fTextureArray;
  166. end;
  167. TgxBaseImageClass = class of TgxBaseImage;
  168. (* Contains and manipulates a 32 bits (24+8) bitmap.
  169. This is the base class for preparing and manipulating textures in GXS.Scene,
  170. this function does not rely on a windows handle and should be used for
  171. in-memory manipulations only.
  172. 16 bits textures are automatically converted to 24 bits and an opaque (255)
  173. alpha channel is assumed for all planes, the byte order is as specified
  174. in GL_RGBA. If 32 bits is used in this class, it can however output 16 bits texture
  175. data for use in OpenGL.
  176. The class has support for registering its content as a texture, as well
  177. as for directly drawing/reading from the current OpenGL buffer. *)
  178. TgxImage = class(TgxBaseImage)
  179. private
  180. FVerticalReverseOnAssignFromBitmap: Boolean;
  181. FBlank: boolean;
  182. fOldColorFormat: Cardinal;
  183. fOldDataType: Cardinal;
  184. procedure DataConvertTask;
  185. protected
  186. procedure SetWidth(val: Integer);
  187. procedure SetHeight(const val: Integer);
  188. procedure SetDepth(const val: Integer);
  189. procedure SetBlank(const Value: boolean);
  190. procedure SetCubeMap(const val: Boolean);
  191. procedure SetArray(const val: Boolean);
  192. function GetScanLine(index: Integer): PgxPixel32Array;
  193. procedure AssignFrom24BitsBitmap(aBitmap: TBitmap);
  194. procedure AssignFrom32BitsBitmap(aBitmap: TBitmap);
  195. {$IFDEF USE_GRAPHICS32}
  196. procedure AssignFromBitmap32(aBitmap32: TBitmap32);
  197. {$ENDIF}
  198. procedure AssignFromPngImage(aPngImage: TBitmapImage);
  199. public
  200. constructor Create; override;
  201. destructor Destroy; override;
  202. // Accepts TgxImage and TGraphic subclasses.
  203. procedure Assign(Source: TPersistent); override;
  204. (* Assigns from a 24 bits bitmap without swapping RGB.
  205. This is faster than a regular assignment, but R and B channels
  206. will be reversed (from what you would view in a TImage). Suitable
  207. if you do your own drawing and reverse RGB on the drawing side.
  208. If you're after speed, don't forget to set the bitmap's dimensions
  209. to a power of two! *)
  210. procedure AssignFromBitmap24WithoutRGBSwap(aBitmap: TBitmap);
  211. (* Assigns from a 2D Texture.
  212. The context which holds the texture must be active and the texture
  213. handle valid. *)
  214. procedure AssignFromTexture2D(textureHandle: Cardinal); overload;
  215. (* Assigns from a Texture handle.
  216. If the handle is invalid, the bitmap32 will be empty. *)
  217. procedure AssignFromTexture2D(textureHandle: TgxTextureHandle); overload;
  218. // Create a 32 bits TBitmap from self content.
  219. function Create32BitsBitmap: TBitmap;
  220. // Width of the bitmap.
  221. property Width: Integer read GetWidth write SetWidth;
  222. // Height of the bitmap.
  223. property Height: Integer read GetHeight write SetHeight;
  224. // Depth of the bitmap.
  225. property Depth: Integer read GetDepth write SetDepth;
  226. // OpenGL color format
  227. property ColorFormat: Cardinal read fColorFormat;
  228. // Recommended texture internal format
  229. property InternalFormat: TglInternalFormat read FInternalFormat write
  230. FInternalFormat;
  231. // OpenGL data type
  232. property DataType: Cardinal read fDataType;
  233. // Size in bytes of pixel or block
  234. property ElementSize: Integer read fElementSize;
  235. property CubeMap: Boolean read fCubeMap write SetCubeMap;
  236. property TextureArray: Boolean read fTextureArray write SetArray;
  237. (* Access to a specific Bitmap ScanLine. index should be in the [0; Height[ range.
  238. Warning : this function is NOT protected against invalid indexes,
  239. and invoking it is invalid if the bitmap is Empty. *)
  240. property ScanLine[index: Integer]: PgxPixel32Array read GetScanLine;
  241. property VerticalReverseOnAssignFromBitmap: Boolean read
  242. FVerticalReverseOnAssignFromBitmap write
  243. FVerticalReverseOnAssignFromBitmap;
  244. (* Set Blank to true if you actually don't need to allocate data in main memory.
  245. Useful for textures that are generated by the GPU on the fly. *)
  246. property Blank: boolean read FBlank write SetBlank;
  247. // Recast image OpenGL data type and color format.
  248. procedure SetColorFormatDataType(const AColorFormat, ADataType: Cardinal);
  249. (* Set Alpha channel values to the pixel intensity.
  250. The intensity is calculated as the mean of RGB components. *)
  251. procedure SetAlphaFromIntensity;
  252. (* Set Alpha channel to 0 for pixels of given color, 255 for others).
  253. This makes pixels of given color totally transparent while the others
  254. are completely opaque. *)
  255. procedure SetAlphaTransparentForColor(const aColor: TColor); overload;
  256. procedure SetAlphaTransparentForColor(const aColor: TgxPixel32); overload;
  257. procedure SetAlphaTransparentForColor(const aColor: TgxPixel24); overload;
  258. // Set Alpha channel values to given byte value.
  259. procedure SetAlphaToValue(const aValue: Byte);
  260. // Set Alpha channel values to given float [0..1] value.
  261. procedure SetAlphaToFloatValue(const aValue: Single);
  262. (* Inverts the AlphaChannel component.
  263. What was transparent becomes opaque and vice-versa. *)
  264. procedure InvertAlpha;
  265. // AlphaChannel components are replaced by their sqrt.
  266. procedure SqrtAlpha;
  267. // Apply a brightness (scaled saturating) correction to the RGB components.
  268. procedure BrightnessCorrection(const factor: Single);
  269. // Apply a gamma correction to the RGB components.
  270. procedure GammaCorrection(const gamma: Single);
  271. (* Downsample the bitmap by a factor of 2 in both dimensions.
  272. If one of the dimensions is 1 or less, does nothing. *)
  273. procedure DownSampleByFactor2;
  274. (* Reads the given area from the current active OpenGL rendering context.
  275. The best spot for reading pixels is within a SceneViewer's PostRender
  276. event : the scene has been fully rendered and the OpenGL context
  277. is still active. *)
  278. procedure ReadPixels(const area: TRect);
  279. (* Draws the whole bitmap at given position in the current OpenGL context.
  280. This function must be called with a rendering context active.
  281. Blending and Alpha channel functions are not altered by this function
  282. and must be adjusted separately. *)
  283. procedure DrawPixels(const x, y: Single);
  284. (* Converts a grayscale 'elevation' bitmap to normal map.
  285. Actually, only the Green component in the original bitmap is used. *)
  286. procedure GrayScaleToNormalMap(const scale: Single;
  287. wrapX: Boolean = True; wrapY: Boolean = True);
  288. // Assumes the bitmap content is a normal map and normalizes all pixels.
  289. procedure NormalizeNormalMap;
  290. //Converts a TImage back into a TBitmap
  291. procedure AssignToBitmap(aBitmap: TBitmap);
  292. // Generate level of detail.
  293. procedure GenerateMipmap(AFilter: TImageFilterFunction); override;
  294. // Clear all levels except first.
  295. procedure UnMipmap; override;
  296. end;
  297. TgxBitmap32 = TgxImage;
  298. TRasterFileFormat = class
  299. public
  300. BaseImageClass: TgxBaseImageClass;
  301. Extension: string;
  302. Description: string;
  303. DescResID: Integer;
  304. end;
  305. // Stores registered raster file Formatx.
  306. TRasterFileFormatsList = class(TgxPersistentObjectList)
  307. public
  308. destructor Destroy; override;
  309. procedure Add(const Ext, Desc: string; DescID: Integer; AClass: TgxBaseImageClass);
  310. function FindExt(ext: string): TgxBaseImageClass;
  311. function FindFromFileName(const fileName: string): TgxBaseImageClass;
  312. function FindFromStream(const AStream: TStream): TgxBaseImageClass;
  313. procedure Remove(AClass: TgxBaseImageClass);
  314. procedure BuildFilterStrings(imageFileClass: TgxBaseImageClass;
  315. var descriptions, filters: string;
  316. formatsThatCanBeOpened: Boolean = True;
  317. formatsThatCanBeSaved: Boolean = False);
  318. function FindExtByIndex(index: Integer;
  319. formatsThatCanBeOpened: Boolean = True;
  320. formatsThatCanBeSaved: Boolean = False): string;
  321. end;
  322. EInvalidRasterFile = class(Exception);
  323. procedure Div2(var Value: Integer);
  324. procedure BGR24ToRGB24(src, dest: Pointer; pixelCount: Integer);
  325. procedure BGR24ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  326. procedure RGB24ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  327. procedure BGRA32ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  328. procedure GammaCorrectRGBArray(base: Pointer; pixelCount: Integer; gamma: Single);
  329. procedure BrightenRGBArray(base: Pointer; pixelCount: Integer; factor: Single);
  330. // Read access to the list of registered vector file formats
  331. function GetRasterFileFormats: TRasterFileFormatsList;
  332. (* Returns an extension by its index
  333. in the internal image files dialogs filter.
  334. Use InternalImageFileFormatsFilter to obtain the filter. *)
  335. function RasterFileFormatExtensionByIndex(index: Integer): string;
  336. procedure RegisterRasterFormat(const AExtension, ADescription: string;
  337. AClass: TgxBaseImageClass);
  338. procedure UnregisterRasterFormat(AClass: TgxBaseImageClass);
  339. // Return an optimal number of texture pyramid
  340. function GetImageLodNumber(w, h, d: integer; IsVolume: Boolean): Integer;
  341. var
  342. vVerticalFlipDDS: Boolean = True;
  343. // ------------------------------------------------------------------
  344. implementation
  345. // ------------------------------------------------------------------
  346. var
  347. vRasterFileFormats: TRasterFileFormatsList;
  348. // ------- Raster File Registries ------------------
  349. function GetRasterFileFormats: TRasterFileFormatsList;
  350. begin
  351. if not Assigned(vRasterFileFormats) then
  352. vRasterFileFormats := TRasterFileFormatsList.Create;
  353. Result := vRasterFileFormats;
  354. end;
  355. procedure RegisterRasterFormat(const AExtension, ADescription: string;
  356. AClass: TgxBaseImageClass);
  357. begin
  358. RegisterClass(AClass);
  359. GetRasterFileFormats.Add(AExtension, ADescription, 0, AClass);
  360. end;
  361. procedure UnregisterRasterFormat(AClass: TgxBaseImageClass);
  362. begin
  363. if Assigned(vRasterFileFormats) then
  364. vRasterFileFormats.Remove(AClass);
  365. end;
  366. function RasterFileFormatExtensionByIndex(index: Integer): string;
  367. begin
  368. Result := GetRasterFileFormats.FindExtByIndex(index);
  369. end;
  370. destructor TRasterFileFormatsList.Destroy;
  371. begin
  372. Clean;
  373. inherited;
  374. end;
  375. procedure TRasterFileFormatsList.Add(const Ext, Desc: string; DescID: Integer;
  376. AClass: TgxBaseImageClass);
  377. var
  378. newRec: TRasterFileFormat;
  379. begin
  380. newRec := TRasterFileFormat.Create;
  381. with newRec do
  382. begin
  383. Extension := AnsiLowerCase(Ext);
  384. BaseImageClass := AClass;
  385. Description := Desc;
  386. DescResID := DescID;
  387. end;
  388. inherited Add(newRec);
  389. end;
  390. function TRasterFileFormatsList.FindExt(ext: string): TgxBaseImageClass;
  391. var
  392. i: Integer;
  393. begin
  394. ext := AnsiLowerCase(ext);
  395. for i := Count - 1 downto 0 do
  396. with TRasterFileFormat(Items[I]) do
  397. begin
  398. if Extension = ext then
  399. begin
  400. Result := BaseImageClass;
  401. Exit;
  402. end;
  403. end;
  404. Result := nil;
  405. end;
  406. function TRasterFileFormatsList.FindFromFileName(const fileName: string): TgxBaseImageClass;
  407. var
  408. Ext: string;
  409. begin
  410. Ext := ExtractFileExt(FileName);
  411. System.Delete(Ext, 1, 1);
  412. Result := FindExt(Ext);
  413. if not Assigned(Result) then
  414. raise EInvalidRasterFile.CreateFmt(strUnknownExtension,
  415. [Ext, 'GLFile' + UpperCase(Ext)]);
  416. end;
  417. function TRasterFileFormatsList.FindFromStream(const AStream: TStream): TgxBaseImageClass;
  418. var
  419. Ext: string;
  420. magic: array [0 .. 1] of LongWord;
  421. begin
  422. magic[0] := 0;
  423. magic[1] := 1;
  424. AStream.ReadBuffer(magic, 2 * SizeOf(LongWord));
  425. AStream.Seek(-2 * SizeOf(LongWord), 1);
  426. if magic[0] = $20534444 then
  427. Ext := 'DDS'
  428. else if magic[1] = $4354334F then
  429. Ext := 'O3TC'
  430. else if (magic[0] and $0000FFFF) = $00003F23 then
  431. Ext := 'HDR'
  432. else if (magic[0] = $474E5089) and (magic[1] = $0A1A0A0D) then
  433. Ext := 'PNG'
  434. else if (magic[0] = $E0FFD8FF) and (magic[1] = $464A1000) then
  435. Ext := 'JPG';
  436. Result := FindExt(Ext);
  437. if not Assigned(Result) then
  438. raise EInvalidRasterFile.CreateFmt(strUnknownExtension,
  439. [Ext, 'GLFile' + UpperCase(Ext)]);
  440. end;
  441. procedure TRasterFileFormatsList.Remove(AClass: TgxBaseImageClass);
  442. var
  443. i: Integer;
  444. begin
  445. for i := Count - 1 downto 0 do
  446. begin
  447. if TRasterFileFormat(Items[i]).BaseImageClass.InheritsFrom(AClass) then
  448. DeleteAndFree(i);
  449. end;
  450. end;
  451. procedure TRasterFileFormatsList.BuildFilterStrings(
  452. imageFileClass: TgxBaseImageClass;
  453. var descriptions, filters: string;
  454. formatsThatCanBeOpened: Boolean = True;
  455. formatsThatCanBeSaved: Boolean = False);
  456. var
  457. k, i: Integer;
  458. p: TRasterFileFormat;
  459. begin
  460. descriptions := '';
  461. filters := '';
  462. k := 0;
  463. for i := 0 to Count - 1 do
  464. begin
  465. p := TRasterFileFormat(Items[i]);
  466. if p.BaseImageClass.InheritsFrom(imageFileClass) and (p.Extension <> '')
  467. and ((formatsThatCanBeOpened and (dfcRead in
  468. p.BaseImageClass.Capabilities))
  469. or (formatsThatCanBeSaved and (dfcWrite in p.BaseImageClass.Capabilities))) then
  470. begin
  471. with p do
  472. begin
  473. if k <> 0 then
  474. begin
  475. descriptions := descriptions + '|';
  476. filters := filters + ';';
  477. end;
  478. if (Description = '') and (DescResID <> 0) then
  479. Description := LoadStr(DescResID);
  480. FmtStr(descriptions, '%s%s (*.%s)|*.%2:s', [descriptions, Description,
  481. Extension]);
  482. filters := filters + '*.' + Extension;
  483. Inc(k);
  484. end;
  485. end;
  486. end;
  487. if (k > 1) and (not formatsThatCanBeSaved) then
  488. FmtStr(descriptions, '%s (%s)|%1:s|%s',
  489. [sAllFilter, filters, descriptions]);
  490. end;
  491. function TRasterFileFormatsList.FindExtByIndex(index: Integer;
  492. formatsThatCanBeOpened: Boolean = True;
  493. formatsThatCanBeSaved: Boolean = False): string;
  494. var
  495. i: Integer;
  496. p: TRasterFileFormat;
  497. begin
  498. Result := '';
  499. if index > 0 then
  500. begin
  501. for i := 0 to Count - 1 do
  502. begin
  503. p := TRasterFileFormat(Items[i]);
  504. if (formatsThatCanBeOpened and (dfcRead in p.BaseImageClass.Capabilities))
  505. or (formatsThatCanBeSaved and (dfcWrite in
  506. p.BaseImageClass.Capabilities)) then
  507. begin
  508. if index = 1 then
  509. begin
  510. Result := p.Extension;
  511. Break;
  512. end
  513. else
  514. Dec(index);
  515. end;
  516. end;
  517. end;
  518. end;
  519. procedure Div2(var Value: Integer);
  520. begin
  521. Value := Value div 2;
  522. if Value = 0 then
  523. Inc(Value);
  524. end;
  525. function GetImageLodNumber(w, h, d: integer; IsVolume: Boolean): Integer;
  526. var
  527. L: Integer;
  528. begin
  529. L := 1;
  530. d := MaxInteger(d, 1);
  531. while ((w > 1) or (h > 1) or (d > 1)) do
  532. begin
  533. Div2(w);
  534. Div2(h);
  535. if IsVolume then
  536. Div2(d);
  537. Inc(L);
  538. end;
  539. Result := L;
  540. end;
  541. procedure CalcImagePiramid(var APiramid: TgxImagePiramid);
  542. begin
  543. end;
  544. procedure GammaCorrectRGBArray(base: Pointer; pixelCount: Integer;
  545. gamma: Single);
  546. var
  547. vGammaLUT: array[0..255] of Byte;
  548. invGamma: Single;
  549. i: Integer;
  550. ptr: PByte;
  551. begin
  552. if pixelCount < 1 then
  553. Exit;
  554. Assert(gamma > 0);
  555. // build LUT
  556. if gamma < 0.1 then
  557. invGamma := 10
  558. else
  559. invGamma := 1 / gamma;
  560. for i := 0 to 255 do
  561. vGammaLUT[i] := Round(255 * Power(i * (1 / 255), InvGamma));
  562. // perform correction
  563. ptr := base;
  564. for i := 0 to pixelCount * 3 - 1 do
  565. begin
  566. ptr^ := vGammaLUT[ptr^];
  567. Inc(ptr);
  568. end;
  569. end;
  570. procedure GammaCorrectRGBAArray(base: Pointer; pixelCount: Integer;
  571. gamma: Single);
  572. var
  573. vGammaLUT: array[0..255] of Byte;
  574. pLUT: PByteArray;
  575. invGamma: Single;
  576. i: Integer;
  577. ptr: PByte;
  578. begin
  579. if pixelCount < 1 then
  580. Exit;
  581. Assert(gamma > 0);
  582. // build LUT
  583. if gamma < 0.1 then
  584. invGamma := 10
  585. else
  586. invGamma := 1 / gamma;
  587. for i := 0 to 255 do
  588. vGammaLUT[i] := Round(255 * Power(i * (1 / 255), InvGamma));
  589. // perform correction
  590. ptr := base;
  591. pLUT := @vGammaLUT[0];
  592. for i := 0 to pixelCount - 1 do
  593. begin
  594. ptr^ := pLUT^[ptr^];
  595. Inc(ptr);
  596. ptr^ := pLUT^[ptr^];
  597. Inc(ptr);
  598. ptr^ := pLUT^[ptr^];
  599. Inc(ptr, 2);
  600. end;
  601. end;
  602. procedure BrightenRGBArray(base: Pointer; pixelCount: Integer; factor: Single);
  603. var
  604. vBrightnessLUT: array[0..255] of Byte;
  605. i, k: Integer;
  606. ptr: PByte;
  607. begin
  608. if pixelCount < 1 then
  609. Exit;
  610. Assert(factor >= 0);
  611. // build LUT
  612. for i := 0 to 255 do
  613. begin
  614. k := Round(factor * i);
  615. if k > 255 then
  616. k := 255;
  617. vBrightnessLUT[i] := Byte(k);
  618. end;
  619. // perform correction
  620. ptr := base;
  621. for i := 0 to pixelCount * 3 - 1 do
  622. begin
  623. ptr^ := vBrightnessLUT[ptr^];
  624. Inc(ptr);
  625. end;
  626. end;
  627. procedure BrightenRGBAArray(base: Pointer; pixelCount: Integer; factor: Single);
  628. var
  629. vBrightnessLUT: array[0..255] of Byte;
  630. pLUT: PByteArray;
  631. i: Integer;
  632. ptr: PByte;
  633. k: Integer;
  634. begin
  635. if pixelCount < 1 then
  636. Exit;
  637. Assert(factor >= 0);
  638. // build LUT
  639. for i := 0 to 255 do
  640. begin
  641. k := Round(factor * i);
  642. if k > 255 then
  643. k := 255;
  644. vBrightnessLUT[i] := k;
  645. end;
  646. // perform correction
  647. ptr := base;
  648. pLUT := @vBrightnessLUT[0];
  649. for i := 0 to pixelCount - 1 do
  650. begin
  651. ptr^ := pLUT^[ptr^];
  652. Inc(ptr);
  653. ptr^ := pLUT^[ptr^];
  654. Inc(ptr);
  655. ptr^ := pLUT^[ptr^];
  656. Inc(ptr, 2);
  657. end;
  658. end;
  659. procedure BGR24ToRGB24(src, dest: Pointer; pixelCount: Integer); register;
  660. begin
  661. while pixelCount > 0 do
  662. begin
  663. PAnsiChar(dest)[0] := PAnsiChar(src)[2];
  664. PAnsiChar(dest)[1] := PAnsiChar(src)[1];
  665. PAnsiChar(dest)[2] := PAnsiChar(src)[0];
  666. Inc(PAnsiChar(dest), 3);
  667. Inc(PAnsiChar(src), 3);
  668. Dec(pixelCount);
  669. end;
  670. end;
  671. procedure BGR24ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  672. begin
  673. while pixelCount > 0 do
  674. begin
  675. PAnsiChar(dest)[0] := PAnsiChar(src)[2];
  676. PAnsiChar(dest)[1] := PAnsiChar(src)[1];
  677. PAnsiChar(dest)[2] := PAnsiChar(src)[0];
  678. PAnsiChar(dest)[3] := #255;
  679. Inc(PAnsiChar(dest), 4);
  680. Inc(PAnsiChar(src), 3);
  681. Dec(pixelCount);
  682. end;
  683. end;
  684. procedure RGB24ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  685. begin
  686. while pixelCount > 0 do
  687. begin
  688. PAnsiChar(dest)[0] := PAnsiChar(src)[0];
  689. PAnsiChar(dest)[1] := PAnsiChar(src)[1];
  690. PAnsiChar(dest)[2] := PAnsiChar(src)[2];
  691. PAnsiChar(dest)[3] := #255;
  692. Inc(PAnsiChar(dest), 4);
  693. Inc(PAnsiChar(src), 3);
  694. Dec(pixelCount);
  695. end;
  696. end;
  697. procedure BGRA32ToRGBA32(src, dest: Pointer; pixelCount: Integer);
  698. begin
  699. while pixelCount > 0 do
  700. begin
  701. PAnsiChar(dest)[0] := PAnsiChar(src)[2];
  702. PAnsiChar(dest)[1] := PAnsiChar(src)[1];
  703. PAnsiChar(dest)[2] := PAnsiChar(src)[0];
  704. PAnsiChar(dest)[3] := PAnsiChar(src)[3];
  705. Inc(PAnsiChar(dest), 4);
  706. Inc(PAnsiChar(src), 4);
  707. Dec(pixelCount);
  708. end;
  709. end;
  710. // ------------------
  711. // ------------------ TgxBaseImage ------------------
  712. // ------------------
  713. constructor TgxBaseImage.Create;
  714. begin
  715. inherited Create(Self);
  716. FillChar(FLOD, SizeOf(TgxImagePiramid), $00);
  717. fLevelCount := 1; // first level always is present
  718. fColorFormat := GL_RGBA;
  719. fInternalFormat := tfRGBA8;
  720. fDataType := GL_UNSIGNED_BYTE;
  721. fElementSize := 4;
  722. fCubeMap := false;
  723. fTextureArray := false;
  724. end;
  725. destructor TgxBaseImage.Destroy;
  726. var
  727. level: TgxImageLODRange;
  728. begin
  729. if Assigned(fData) then
  730. begin
  731. FreeMem(fData);
  732. fData := nil;
  733. end;
  734. FreeAndNil(FFinishEvent);
  735. for level := 0 to High(TgxImageLODRange) do
  736. begin
  737. FLOD[level].PBO.Free;
  738. end;
  739. FSourceStream.Free;
  740. inherited Destroy;
  741. end;
  742. procedure TgxBaseImage.Assign(Source: TPersistent);
  743. var
  744. img: TgxBaseImage;
  745. size: integer;
  746. begin
  747. if Source is TgxBaseImage then
  748. begin
  749. img := Source as TgxBaseImage;
  750. FLOD := img.FLOD;
  751. fLevelCount := img.fLevelCount;
  752. fColorFormat := img.fColorFormat;
  753. fInternalFormat := img.fInternalFormat;
  754. fDataType := img.fDataType;
  755. fElementSize := img.fElementSize;
  756. fCubeMap := img.fCubeMap;
  757. fTextureArray := img.fTextureArray;
  758. size := img.DataSize;
  759. ReallocMem(FData, size);
  760. Move(img.fData^, fData^, size);
  761. end
  762. else if Source <> nil then
  763. inherited; // raise AssingError
  764. end;
  765. function TgxBaseImage.GetTextureTarget: TGLTextureTarget;
  766. begin
  767. Result := ttTexture2D;
  768. // Choose a texture target
  769. if GetHeight = 1 then
  770. Result := ttTexture1D;
  771. if FCubeMap then
  772. Result := ttTextureCube;
  773. if IsVolume then
  774. Result := ttTexture3D;
  775. if FTextureArray then
  776. begin
  777. if (GetDepth < 2) then
  778. Result := ttTexture1Darray
  779. else
  780. Result := ttTexture2DArray;
  781. if FCubeMap then
  782. Result := ttTextureCubeArray;
  783. end;
  784. if ((FInternalFormat >= tfFLOAT_R16)
  785. and (FInternalFormat <= tfFLOAT_RGBA32)) then
  786. Result := ttTextureRect;
  787. end;
  788. function TgxBaseImage.DataSize: Cardinal;
  789. var
  790. l: TgxImageLODRange;
  791. s: Cardinal;
  792. begin
  793. s := 0;
  794. if not IsEmpty then
  795. begin
  796. UpdateLevelsInfo;
  797. for l := 0 to FLevelCount - 1 do
  798. s := s + FLOD[l].Size;
  799. end;
  800. Result := s;
  801. end;
  802. function TgxBaseImage.GetWidth: Integer;
  803. begin
  804. Result := FLOD[0].Width;
  805. end;
  806. function TgxBaseImage.GetDepth: Integer;
  807. begin
  808. Result := FLOD[0].Depth;
  809. end;
  810. function TgxBaseImage.GetHeight: Integer;
  811. begin
  812. Result := FLOD[0].Height;
  813. end;
  814. function TgxBaseImage.GetLevelAddress(ALevel: Byte): Pointer;
  815. begin
  816. Result := FData;
  817. Inc(PByte(Result), FLOD[ALevel].Offset);
  818. end;
  819. function TgxBaseImage.GetLevelAddress(ALevel, AFace: Byte): Pointer;
  820. begin
  821. Result := FData;
  822. Inc(PByte(Result), FLOD[ALevel].Offset);
  823. Inc(PByte(Result), AFace*(FLOD[ALevel].Size div 6));
  824. end;
  825. function TgxBaseImage.GetLevelDepth(ALOD: TgxImageLODRange): Integer;
  826. begin
  827. Result := FLOD[ALOD].Depth;
  828. end;
  829. function TgxBaseImage.GetLevelHeight(ALOD: TgxImageLODRange): Integer;
  830. begin
  831. Result := FLOD[ALOD].Height;
  832. end;
  833. function TgxBaseImage.GetLevelOffset(ALOD: TgxImageLODRange): Integer;
  834. begin
  835. Result := FLOD[ALOD].Offset;
  836. end;
  837. function TgxBaseImage.GetLevelPBO(ALOD: TgxImageLODRange): TgxUnpackPBOHandle;
  838. begin
  839. Result := FLOD[ALOD].PBO;
  840. end;
  841. function TgxBaseImage.GetLevelSizeInByte(ALOD: TgxImageLODRange): Integer;
  842. begin
  843. Result := FLOD[ALOD].Size;
  844. end;
  845. function TgxBaseImage.GetLevelStreamingState(ALOD: TgxImageLODRange): TgxLODStreamingState;
  846. begin
  847. Result := FLOD[ALOD].State;
  848. end;
  849. function TgxBaseImage.GetLevelWidth(ALOD: TgxImageLODRange): Integer;
  850. begin
  851. Result := FLOD[ALOD].Width;
  852. end;
  853. function TgxBaseImage.IsEmpty: Boolean;
  854. begin
  855. Result := (GetWidth = 0) or (GetHeight = 0);
  856. end;
  857. function TgxBaseImage.IsCompressed: Boolean;
  858. begin
  859. Result := IsCompressedFormat(fInternalFormat);
  860. end;
  861. function TgxBaseImage.IsVolume: boolean;
  862. begin
  863. Result := (GetDepth > 0) and not fTextureArray and not fCubeMap;
  864. end;
  865. function TgxBaseImage.ConvertCrossToCubemap: Boolean;
  866. var
  867. fW, fH, cubeSize, realCubeSize, e: integer;
  868. lData: PByteArray;
  869. ptr: PGLubyte;
  870. i, j: integer;
  871. bGenMipmap: Boolean;
  872. begin
  873. Result := False;
  874. // Can't already be a cubemap
  875. if fCubeMap or fTextureArray then
  876. Exit;
  877. //this function only supports vertical cross format for now (3 wide by 4 high)
  878. if (GetWidth div 3 <> GetHeight div 4)
  879. or (GetWidth mod 3 <> 0)
  880. or (GetHeight mod 4 <> 0)
  881. or (GetDepth > 0) then
  882. Exit;
  883. bGenMipmap := FLevelCount > 1;
  884. UnMipmap;
  885. // Get the source data
  886. lData := PByteArray(fData);
  887. if IsCompressed then
  888. begin
  889. fW := (GetWidth + 3) div 4;
  890. fH := (GetHeight + 3) div 4;
  891. realCubeSize := (fH div 4) * 4;
  892. end
  893. else
  894. begin
  895. fW := GetWidth;
  896. fH := GetHeight;
  897. realCubeSize := fH div 4;
  898. end;
  899. cubeSize := fH;
  900. GetMem(fData, fW * fH * fElementSize);
  901. FLOD[0].Width := realCubeSize;
  902. FLOD[0].Height := realCubeSize;
  903. FLOD[0].Depth := 6;
  904. // Extract the faces
  905. ptr := PGLubyte(fData);
  906. // positive X
  907. for j := 0 to cubeSize - 1 do
  908. begin
  909. e := ((fH - (cubeSize + j + 1)) * fW + 2 * cubeSize) * fElementSize;
  910. Move(lData[E], ptr^, cubeSize * fElementSize);
  911. Inc(ptr, cubeSize * fElementSize);
  912. end;
  913. // negative X
  914. for j := 0 to cubeSize - 1 do
  915. begin
  916. Move(lData[(fH - (cubeSize + j + 1)) * fW * fElementSize],
  917. ptr^, cubeSize * fElementSize);
  918. Inc(ptr, cubeSize * fElementSize);
  919. end;
  920. // positive Y
  921. for j := 0 to cubeSize - 1 do
  922. begin
  923. e := ((4 * cubeSize - j - 1) * fW + cubeSize) * fElementSize;
  924. Move(lData[e], ptr^, cubeSize * fElementSize);
  925. Inc(ptr, cubeSize * fElementSize);
  926. end;
  927. // negative Y
  928. for j := 0 to cubeSize - 1 do
  929. begin
  930. e := ((2 * cubeSize - j - 1) * fW + cubeSize) * fElementSize;
  931. Move(lData[e], ptr^, cubeSize * fElementSize);
  932. Inc(ptr, cubeSize * fElementSize);
  933. end;
  934. // positive Z
  935. for j := 0 to cubeSize - 1 do
  936. begin
  937. e := ((fH - (cubeSize + j + 1)) * fW + cubeSize) * fElementSize;
  938. Move(lData[e], ptr^, cubeSize * fElementSize);
  939. Inc(ptr, cubeSize * fElementSize);
  940. end;
  941. // negative Z
  942. for j := 0 to cubeSize - 1 do
  943. for i := 0 to cubeSize - 1 do
  944. begin
  945. e := (j * fW + 2 * cubeSize - (i + 1)) * fElementSize;
  946. Move(lData[e], ptr^, fElementSize);
  947. Inc(ptr, fElementSize);
  948. end;
  949. // Set the new # of faces, width and height
  950. fCubeMap := true;
  951. FreeMem(lData);
  952. if bGenMipmap then
  953. GenerateMipmap(ImageTriangleFilter);
  954. Result := true;
  955. end;
  956. function TgxBaseImage.ConvertToVolume(const col, row: Integer; const MakeArray:
  957. Boolean): Boolean;
  958. var
  959. fW, fH, sW, sH, sD: Integer;
  960. lData: PByteArray;
  961. ptr: PGLubyte;
  962. i, j, k: Integer;
  963. begin
  964. Result := false;
  965. if fCubeMap then
  966. Exit;
  967. if (GetDepth > 0) and not fTextureArray and MakeArray then
  968. begin
  969. // Let volume be array
  970. fTextureArray := true;
  971. Result := true;
  972. exit;
  973. end;
  974. if fTextureArray and not MakeArray then
  975. begin
  976. // Let array be volume
  977. fTextureArray := false;
  978. Result := true;
  979. exit;
  980. end;
  981. Result := MakeArray;
  982. // Check sizes
  983. sD := col * row;
  984. if sD < 1 then
  985. Exit;
  986. if IsCompressed then
  987. begin
  988. fW := (GetWidth + 3) div 4;
  989. fH := (GetHeight + 3) div 4;
  990. end
  991. else
  992. begin
  993. fW := GetWidth;
  994. fH := GetHeight;
  995. end;
  996. sW := fW div col;
  997. sH := fH div row;
  998. if (sW = 0) or (sH = 0) then
  999. begin
  1000. Result := False;
  1001. Exit;
  1002. end;
  1003. // Mipmaps are not supported
  1004. UnMipmap;
  1005. // Get the source data
  1006. lData := PByteArray(fData);
  1007. GetMem(fData, sW * sH * sD * fElementSize);
  1008. ptr := PGLubyte(fData);
  1009. for i := 0 to row - 1 do
  1010. for j := 0 to col - 1 do
  1011. for k := 0 to sH - 1 do
  1012. begin
  1013. Move(lData[(i * fW * sH + j * sW + k * fW) * fElementSize],
  1014. ptr^, sW * fElementSize);
  1015. Inc(ptr, sW * fElementSize);
  1016. end;
  1017. if IsCompressed then
  1018. begin
  1019. FLOD[0].Width := sW * 4;
  1020. FLOD[0].Height := sH * 4;
  1021. end
  1022. else
  1023. begin
  1024. FLOD[0].Width := sW;
  1025. FLOD[0].Height := sH;
  1026. end;
  1027. FLOD[0].Depth := sD;
  1028. fTextureArray := Result;
  1029. FreeMem(lData);
  1030. Result := True;
  1031. end;
  1032. procedure TgxBaseImage.SetErrorImage;
  1033. const
  1034. cTextureError: array[0..12287] of Byte = (
  1035. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1036. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1037. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1038. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1039. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$3A,$00,$00,$FF,$DB,$90,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$90,$DB,$FF,$FF,$B6,$90,$90,$DB,$FF,$00,$00,$3A,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$3A,$00,$00,$FF,$DB,$90,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$90,$DB,$FF,$00,$00,$00,
  1040. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$00,$66,$B6,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1041. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$B6,$FF,$FF,$00,$00,$66,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1042. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$90,$DB,$FF,$FF,$B6,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1043. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1044. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1045. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$3A,$90,$DB,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1046. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$90,$DB,$FF,$00,$00,$3A,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$90,$DB,$FF,$00,$00,$3A,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1047. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$90,$DB,$FF,$00,$00,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1048. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$3A,$90,$DB,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1049. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1050. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1051. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1052. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1053. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1054. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1055. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1056. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$DB,$90,$3A,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1057. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1058. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1059. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$90,$3A,$00,$DB,$FF,$DB,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1060. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$90,$3A,$00,$DB,$FF,$DB,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1061. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$90,$DB,$FF,$00,$00,$3A,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1062. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$B6,$66,$00,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1063. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$DB,$FF,$FF,$00,$3A,$90,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$FF,$B6,$66,$66,$B6,$FF,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1064. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$FF,$FF,$00,$00,$66,$00,$00,$00,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$90,$3A,$00,$FF,$FF,$DB,$00,$66,$B6,$00,$00,$00,$00,$00,$00,$3A,$00,$00,$FF,$DB,$90,$3A,$90,$DB,$00,$00,$00,$66,$00,$00,$FF,$FF,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$3A,$90,$DB,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1065. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1066. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1067. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1068. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1069. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1070. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1071. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1072. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1073. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1074. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1075. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1076. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1077. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1078. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1079. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1080. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1081. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1082. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1083. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1084. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1085. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1086. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1087. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1088. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1089. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1090. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1091. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1092. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$90,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1093. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$66,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1094. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1095. $00,$00,$00,$00,$00,$00,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$66,$B6,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$B6,$90,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$66,$B6,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$DB,$90,$3A,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3A,$90,$DB,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$B6,$66,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1096. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1097. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
  1098. $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
  1099. );
  1100. begin
  1101. UnMipmap;
  1102. FLOD[0].Width := 64;
  1103. FLOD[0].Height := 64;
  1104. FLOD[0].Depth := 0;
  1105. fColorFormat := GL_RGBA;
  1106. fInternalFormat := tfRGB8;
  1107. fDataType := GL_UNSIGNED_BYTE;
  1108. fElementSize := 4;
  1109. fCubeMap := false;
  1110. fTextureArray := false;
  1111. FColorFormat := GL_RGB;
  1112. ReallocMem(FData, DataSize);
  1113. Move(cTextureError[0], FData[0], DataSize);
  1114. end;
  1115. procedure TgxBaseImage.SetLevelStreamingState(ALOD: TgxImageLODRange;
  1116. AState: TgxLODStreamingState);
  1117. begin
  1118. FLOD[ALOD].State := AState;
  1119. end;
  1120. procedure TgxBaseImage.Narrow;
  1121. var
  1122. size: Integer;
  1123. newData: Pointer;
  1124. begin
  1125. // Check for already norrow
  1126. if (fColorFormat = GL_RGBA)
  1127. and (GetDepth = 0)
  1128. and (fDataType = GL_UNSIGNED_BYTE)
  1129. and (FLevelCount = 1)
  1130. and not (fTextureArray or fCubeMap) then
  1131. Exit;
  1132. UnMipmap;
  1133. // Use image utils
  1134. size := GetWidth * GetHeight * 4;
  1135. GetMem(newData, size);
  1136. try
  1137. ConvertImage(
  1138. fData, newData,
  1139. fColorFormat, GL_RGBA,
  1140. fDataType, GL_UNSIGNED_BYTE,
  1141. GetWidth, GetHeight);
  1142. except
  1143. ShowMessage(Format(strCantConvertImg, [ClassName]));
  1144. SetErrorImage;
  1145. FreeMem(newData);
  1146. exit;
  1147. end;
  1148. fInternalFormat := tfRGBA8;
  1149. fColorFormat := GL_RGBA;
  1150. fDataType := GL_UNSIGNED_BYTE;
  1151. fElementSize := 4;
  1152. fTextureArray := False;
  1153. fCubeMap := False;
  1154. FreeMem(fData);
  1155. fData := newData;
  1156. end;
  1157. procedure TgxBaseImage.GenerateMipmap(AFilter: TImageFilterFunction);
  1158. var
  1159. LAddresses: TPointerArray;
  1160. level, slice, d: Integer;
  1161. begin
  1162. UnMipmap;
  1163. if IsVolume then
  1164. begin
  1165. fLevelCount := GetImageLodNumber(GetWidth, GetHeight, GetDepth, True);
  1166. UpdateLevelsInfo;
  1167. ReallocMem(FData, DataSize);
  1168. {Message Hint 'TgxBaseImage.GenerateMipmap not yet implemented for volume images' }
  1169. end
  1170. else
  1171. begin
  1172. fLevelCount := GetImageLodNumber(GetWidth, GetHeight, GetDepth, False);
  1173. ReallocMem(FData, DataSize);
  1174. SetLength(LAddresses, fLevelCount-1);
  1175. for level := 1 to fLevelCount-1 do
  1176. LAddresses[level-1] := GetLevelAddress(level);
  1177. d := MaxInteger(GetDepth, 1);
  1178. for slice := 0 to d - 1 do
  1179. begin
  1180. Build2DMipmap(
  1181. GetLevelAddress(0),
  1182. LAddresses,
  1183. fColorFormat,
  1184. fDataType,
  1185. AFilter,
  1186. GetWidth,
  1187. GetHeight);
  1188. for level := 1 to fLevelCount-1 do
  1189. Inc(PByte(LAddresses[level-1]), GetLevelSizeInByte(level) div d);
  1190. end;
  1191. end;
  1192. end;
  1193. procedure TgxBaseImage.UnMipmap;
  1194. var
  1195. level: TgxImageLODRange;
  1196. begin
  1197. for level := 1 to High(TgxImageLODRange) do
  1198. begin
  1199. FLOD[level].Width := 0;
  1200. FLOD[level].Height := 0;
  1201. FLOD[level].Depth := 0;
  1202. end;
  1203. FLevelCount := 1;
  1204. end;
  1205. procedure TgxBaseImage.UpdateLevelsInfo;
  1206. var
  1207. level: TgxImageLODRange;
  1208. w, h, d: Integer;
  1209. function GetSize(const level: Integer): integer;
  1210. var
  1211. ld, bw, bh, lsize: integer;
  1212. begin
  1213. if fTextureArray then
  1214. ld := FLOD[0].Depth
  1215. else
  1216. ld := d;
  1217. if ld = 0 then
  1218. ld := 1;
  1219. if IsCompressed then
  1220. begin
  1221. bw := (w + 3) div 4;
  1222. bh := (h + 3) div 4;
  1223. end
  1224. else
  1225. begin
  1226. bw := w;
  1227. bh := h;
  1228. end;
  1229. if bh = 0 then
  1230. bh := 1;
  1231. lsize := bw * bh * ld * fElementSize;
  1232. if fCubeMap and not fTextureArray then
  1233. lsize := lsize * 6;
  1234. // Align to Double Word
  1235. if (lsize and 3) <> 0 then
  1236. lsize := 4 * (1 + lsize div 4);
  1237. Result := lsize;
  1238. end;
  1239. begin
  1240. w := FLOD[0].Width;
  1241. h := FLOD[0].Height;
  1242. d := FLOD[0].Depth;
  1243. FLOD[0].Size := GetSize(0);
  1244. FLOD[0].Offset := 0;
  1245. for level := 1 to High(TgxImageLODRange) do
  1246. begin
  1247. Div2(w);
  1248. Div2(h);
  1249. if not fTextureArray then
  1250. d := d div 2;
  1251. FLOD[level].Width := w;
  1252. FLOD[level].Height := h;
  1253. FLOD[level].Depth := d;
  1254. FLOD[level].Offset := FLOD[level - 1].Offset + FLOD[level - 1].Size;
  1255. FLOD[level].Size := GetSize(level);
  1256. end;
  1257. end;
  1258. function TgxBaseImage.GetData: PgxPixel32Array;
  1259. begin
  1260. Result := fData;
  1261. end;
  1262. procedure TgxBaseImage.RegisterAsOpenRXTexture(
  1263. AHandle: TgxTextureHandle;
  1264. aMipmapGen: Boolean;
  1265. aTexFormat: NativeUInt;
  1266. out texWidth: integer;
  1267. out texHeight: integer;
  1268. out texDepth: integer);
  1269. var
  1270. glTarget: GLEnum;
  1271. glHandle: GLuint;
  1272. Level: integer;
  1273. LLevelCount, face: integer;
  1274. bCompress, bBlank: boolean;
  1275. w, h, d, cw, ch, maxSize: GLsizei;
  1276. p, buffer: Pointer;
  1277. vtcBuffer, top, bottom: PGLubyte;
  1278. i, j, k: Integer;
  1279. TransferMethod: 0..3;
  1280. function blockOffset(x, y, z: Integer): Integer;
  1281. begin
  1282. if z >= (d and -4) then
  1283. Result := fElementSize * (cw * ch * (d and -4) + x +
  1284. cw * (y + ch * (z - 4 * ch)))
  1285. else
  1286. Result := fElementSize * (4 * (x + cw * (y + ch * floor(z / 4))) + (z and
  1287. 3));
  1288. if Result < 0 then
  1289. Result := 0;
  1290. end;
  1291. begin
  1292. if AHandle.Target = ttNoShape then
  1293. exit;
  1294. begin
  1295. UpdateLevelsInfo;
  1296. if Self is TgxImage then
  1297. bBlank := TgxImage(Self).Blank
  1298. else
  1299. bBlank := False;
  1300. // Check for Non-power-of-two
  1301. if not GL_ARB_texture_non_power_of_two then
  1302. begin
  1303. w := RoundUpToPowerOf2(GetWidth);
  1304. h := RoundUpToPowerOf2(GetHeight);
  1305. d := RoundUpToPowerOf2(GetDepth);
  1306. if GetDepth = 0 then
  1307. d := 0;
  1308. end
  1309. else
  1310. begin
  1311. w := GetWidth;
  1312. h := GetHeight;
  1313. d := GetDepth;
  1314. end;
  1315. // Check maximum dimension
  1316. maxSize := CurrentContext.gxStates.MaxTextureSize;
  1317. if w > maxSize then
  1318. w := maxSize;
  1319. if h > maxSize then
  1320. h := maxSize;
  1321. texWidth := w;
  1322. texHeight := h;
  1323. texDepth := d;
  1324. LLevelCount := FLevelCount;
  1325. bCompress := IsCompressed;
  1326. // Rescale if need and can
  1327. buffer := nil;
  1328. if (w <> GetWidth) or (h <> GetHeight) then
  1329. begin
  1330. if not ((d > 0) // not volume
  1331. or bCompress // not compressed
  1332. or bBlank) then // not blank
  1333. begin
  1334. GetMem(buffer, w * h * fElementSize);
  1335. try
  1336. RescaleImage(
  1337. FData,
  1338. buffer,
  1339. FColorFormat,
  1340. FDataType,
  1341. ImageLanczos3Filter,
  1342. GetWidth, GetHeight,
  1343. w, h);
  1344. LLevelCount := 1;
  1345. except
  1346. bBlank := true;
  1347. end;
  1348. end
  1349. else
  1350. bBlank := true;
  1351. end;
  1352. if Self is TgxImage then
  1353. TgxImage(Self).FBlank := bBlank;
  1354. glHandle := AHandle.Handle;
  1355. glTarget := DecodeTextureTarget(AHandle.Target);
  1356. // Hardware mipmap autogeneration
  1357. aMipmapGen := aMipmapGen and IsTargetSupportMipmap(glTarget);
  1358. aMipmapGen := aMipmapGen and (LLevelCount = 1);
  1359. if aMipmapGen then
  1360. begin
  1361. if GL_SGIS_generate_mipmap then
  1362. begin
  1363. if GL_EXT_direct_state_access then
  1364. glTexParameterf(glTarget, GL_GENERATE_MIPMAP_SGIS, GL_TRUE)
  1365. else
  1366. glTexParameteri(glTarget, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
  1367. end
  1368. else
  1369. begin
  1370. // Software LODs generation
  1371. Self.GenerateMipmap(ImageTriangleFilter);
  1372. LLevelCount := LevelCount;
  1373. end;
  1374. end;
  1375. // Setup top limitation of LODs
  1376. if GL_SGIS_texture_lod and (LLevelCount > 1) then
  1377. if GL_EXT_direct_state_access then
  1378. glTexParameterf(glTarget, GL_TEXTURE_MAX_LEVEL_SGIS, LLevelCount - 1)
  1379. else
  1380. glTexParameteri(glTarget, GL_TEXTURE_MAX_LEVEL_SGIS, LLevelCount - 1);
  1381. // Select transfer method
  1382. if bCompress then
  1383. transferMethod := 1
  1384. else
  1385. transferMethod := 0;
  1386. if GL_EXT_direct_state_access then
  1387. transferMethod := transferMethod + 2;
  1388. // if image is blank then doing only allocatation texture in videomemory
  1389. vtcBuffer := nil;
  1390. case AHandle.Target of
  1391. ttTexture1D:
  1392. for Level := 0 to LLevelCount - 1 do
  1393. begin
  1394. if Assigned(buffer) then
  1395. p := buffer
  1396. else if not bBlank then
  1397. p := GetLevelAddress(Level)
  1398. else
  1399. p := nil;
  1400. case transferMethod of
  1401. 0: glTexImage1D(glTarget, Level, aTexFormat, w, 0, FColorFormat, FDataType, p);
  1402. 1: glCompressedTexImage1D(glTarget, Level, aTexFormat, w, 0, GetLevelSizeInByte(Level), p);
  1403. /// 2: glTextureImage1DEXT(glHandle, glTarget, Level, aTexFormat, w, 0, FColorFormat, FDataType, p);
  1404. /// 3: glCompressedTexImage1DARB(glHandle, glTarget, Level, aTexFormat, w, 0, GetLevelSizeInByte(Level), p)
  1405. end;
  1406. Div2(w);
  1407. end;
  1408. ttTexture2D:
  1409. for Level := 0 to LLevelCount - 1 do
  1410. begin
  1411. if Assigned(buffer) then
  1412. p := buffer
  1413. else if not bBlank then
  1414. p := GetLevelAddress(Level)
  1415. else
  1416. p := nil;
  1417. case transferMethod of
  1418. 0: glTexImage2D(glTarget, Level, aTexFormat, w, h, 0, FColorFormat, FDataType, p);
  1419. 1: glCompressedTexImage2D(glTarget, Level, aTexFormat, w, h, 0, GetLevelSizeInByte(Level), p);
  1420. /// 2: glTextureImage2DEXT(glHandle, glTarget, Level, aTexFormat, w, h, 0, FColorFormat, FDataType, p);
  1421. /// 3: glCompressedTextureImage2DEXT(glHandle, glTarget, Level, aTexFormat, w, h, 0, GetLevelSizeInByte(Level), p);
  1422. end;
  1423. Div2(w);
  1424. Div2(h);
  1425. end;
  1426. ttTextureRect:
  1427. begin
  1428. if Assigned(buffer) then
  1429. p := buffer
  1430. else if not bBlank then
  1431. p := GetLevelAddress(0)
  1432. else
  1433. p := nil;
  1434. case transferMethod of
  1435. 0: glTexImage2D(glTarget, 0, aTexFormat, w, h, 0, FColorFormat, FDataType, p);
  1436. 1: glCompressedTexImage2D(glTarget, 0, aTexFormat, w, h, 0, GetLevelSizeInByte(0), p);
  1437. /// 2: glTextureImage2DEXT(glHandle, glTarget, 0, aTexFormat, w, h, 0, FColorFormat, FDataType, p);
  1438. /// 3: glCompressedTextureImage2DEXT(glHandle, glTarget, 0, aTexFormat, w, h, 0, GetLevelSizeInByte(0), p);
  1439. end;
  1440. end;
  1441. ttTexture3D:
  1442. for Level := 0 to LLevelCount - 1 do
  1443. begin
  1444. if Assigned(buffer) then
  1445. p := buffer
  1446. else if not bBlank then
  1447. p := GetLevelAddress(Level)
  1448. else
  1449. p := nil;
  1450. if GL_NV_texture_compression_vtc and bCompress then
  1451. begin
  1452. // Shufle blocks for Volume Texture Compression
  1453. if Assigned(p) then
  1454. begin
  1455. cw := (w + 3) div 4;
  1456. ch := (h + 3) div 4;
  1457. if Level = 0 then
  1458. GetMem(vtcBuffer, GetLevelSizeInByte(0));
  1459. top := p;
  1460. for k := 0 to d - 1 do
  1461. for i := 0 to ch - 1 do
  1462. for j := 0 to cw - 1 do
  1463. begin
  1464. bottom := vtcBuffer;
  1465. Inc(bottom, blockOffset(j, i, k));
  1466. Move(top^, bottom^, fElementSize);
  1467. Inc(top, fElementSize);
  1468. end;
  1469. end;
  1470. if GL_EXT_direct_state_access then
  1471. glCompressedTexImage3D(glTarget, Level, aTexFormat, w, h, d, 0, GetLevelSizeInByte(Level), vtcBuffer)
  1472. else
  1473. glCompressedTexImage3D(glTarget, Level, aTexFormat, w, h, d, 0, GetLevelSizeInByte(Level), vtcBuffer);
  1474. end
  1475. else
  1476. begin
  1477. // Normal compression
  1478. case transferMethod of
  1479. 0: glTexImage3D(glTarget, Level, aTexFormat, w, h, d, 0, FColorFormat, FDataType, p);
  1480. 1: glCompressedTexImage3D(glTarget, Level, aTexFormat, w, h, d, 0, GetLevelSizeInByte(Level), p);
  1481. /// 2: glTextureImage3DEXT(glHandle, glTarget, Level, aTexFormat, w, h, d, 0, FColorFormat, FDataType, p);
  1482. /// 3: glCompressedTextureImage3DEXT(glHandle, glTarget, Level, aTexFormat, w, h, d, 0, GetLevelSizeInByte(Level), p);
  1483. end;
  1484. end;
  1485. Div2(w);
  1486. Div2(h);
  1487. Div2(d);
  1488. end;
  1489. ttTextureCube:
  1490. for Level := 0 to LLevelCount - 1 do
  1491. begin
  1492. for face := GL_TEXTURE_CUBE_MAP_POSITIVE_X to
  1493. GL_TEXTURE_CUBE_MAP_NEGATIVE_Z do
  1494. begin
  1495. if Assigned(buffer) then
  1496. p := buffer
  1497. else if not bBlank then
  1498. p := GetLevelAddress(Level, face - GL_TEXTURE_CUBE_MAP_POSITIVE_X)
  1499. else
  1500. p := nil;
  1501. case transferMethod of
  1502. 0: glTexImage2D(face, Level, aTexFormat, w, h, 0, FColorFormat, FDataType, p);
  1503. 1: glCompressedTexImage2D(face, Level, aTexFormat, w, h, 0, GetLevelSizeInByte(Level) div 6, p);
  1504. /// 2: glTextureImage2DEXT(glHandle, face, Level, aTexFormat, w, h, 0, FColorFormat, FDataType, p);
  1505. /// 3: glCompressedTextureImage2DEXT(glHandle, face, Level, aTexFormat, w, h, 0, GetLevelSizeInByte(Level) div 6, p);
  1506. end;
  1507. end;
  1508. Div2(w);
  1509. Div2(h);
  1510. end;
  1511. ttTexture1DArray:
  1512. for Level := 0 to LLevelCount - 1 do
  1513. begin
  1514. if Assigned(buffer) then
  1515. p := buffer
  1516. else if not bBlank then
  1517. p := GetLevelAddress(Level)
  1518. else
  1519. p := nil;
  1520. case transferMethod of
  1521. 0: glTexImage2D(glTarget, Level, aTexFormat, w, h, 0, FColorFormat, FDataType, p);
  1522. 1: glCompressedTexImage2D(glTarget, Level, aTexFormat, w, h, 0, GetLevelSizeInByte(Level), p);
  1523. /// 2: glTextureImage2DEXT(glHandle, glTarget, Level, aTexFormat, w, h, 0, FColorFormat, FDataType, p);
  1524. /// 3: glCompressedTextureImage2DEXT(glHandle, glTarget, Level, aTexFormat, w, h, 0, GetLevelSizeInByte(Level), p);
  1525. end;
  1526. Div2(w);
  1527. end;
  1528. ttTexture2DArray, ttTextureCubeArray:
  1529. for Level := 0 to LLevelCount - 1 do
  1530. begin
  1531. if Assigned(buffer) then
  1532. p := buffer
  1533. else if not bBlank then
  1534. p := GetLevelAddress(Level)
  1535. else
  1536. p := nil;
  1537. case transferMethod of
  1538. 0: glTexImage3D(glTarget, Level, aTexFormat, w, h, d, 0, FColorFormat, FDataType, p);
  1539. 1: glCompressedTexImage3D(glTarget, Level, aTexFormat, w, h, d, 0, GetLevelSizeInByte(Level), p);
  1540. /// 2: glTextureImage3DEXT(glHandle, glTarget, Level, aTexFormat, w, h, d, 0, FColorFormat, FDataType, p);
  1541. /// 3: glCompressedTextureImage3DEXT(glHandle, glTarget, Level, aTexFormat, w, h, d, 0, GetLevelSizeInByte(Level), p);
  1542. end;
  1543. Div2(w);
  1544. Div2(h);
  1545. end;
  1546. end; // of case
  1547. if Assigned(buffer) then
  1548. FreeMem(buffer);
  1549. if Assigned(vtcBuffer) then
  1550. FreeMem(vtcBuffer);
  1551. end; // of with GL
  1552. end;
  1553. function TgxBaseImage.AssignFromTexture(
  1554. AHandle: TgxTextureHandle;
  1555. const CastToFormat: Boolean;
  1556. const intFormat: TglInternalFormat = tfRGBA8;
  1557. const colorFormat: NativeUInt = 0;
  1558. const dataType: NativeUInt = 0): Boolean;
  1559. var
  1560. LContext: TgxContext;
  1561. texFormat, texLod, optLod: Cardinal;
  1562. glTarget: GLEnum;
  1563. level, maxFace, face: Integer;
  1564. lData: PGLubyte;
  1565. residentFormat: TglInternalFormat;
  1566. bCompressed: Boolean;
  1567. vtcBuffer, top, bottom: PGLubyte;
  1568. i, j, k: Integer;
  1569. w, d, h, cw, ch: Integer;
  1570. function blockOffset(x, y, z: Integer): Integer;
  1571. begin
  1572. if z >= (d and -4) then
  1573. Result := fElementSize * (cw * ch * (d and -4) + x +
  1574. cw * (y + ch * (z - 4 * ch)))
  1575. else
  1576. Result := fElementSize * (4 * (x + cw * (y + ch * floor(z / 4))) + (z and
  1577. 3));
  1578. end;
  1579. begin
  1580. Result := False;
  1581. LContext := CurrentContext;
  1582. if LContext = nil then
  1583. begin
  1584. LContext := AHandle.RenderingContext;
  1585. if LContext = nil then
  1586. exit;
  1587. end;
  1588. LContext.Activate;
  1589. if AHandle.IsDataNeedUpdate then
  1590. begin
  1591. LContext.Deactivate;
  1592. exit;
  1593. end;
  1594. glTarget := DecodeTextureTarget(AHandle.Target);
  1595. try
  1596. LContext.gxStates.TextureBinding[0, AHandle.Target] := AHandle.Handle;
  1597. FLevelCount := 0;
  1598. glGetTexParameteriv(glTarget, GL_TEXTURE_MAX_LEVEL, @texLod);
  1599. if glTarget = GL_TEXTURE_CUBE_MAP then
  1600. begin
  1601. fCubeMap := true;
  1602. maxFace := 5;
  1603. glTarget := GL_TEXTURE_CUBE_MAP_POSITIVE_X;
  1604. end
  1605. else
  1606. begin
  1607. fCubeMap := false;
  1608. maxFace := 0;
  1609. end;
  1610. fTextureArray := (glTarget = GL_TEXTURE_1D_ARRAY)
  1611. or (glTarget = GL_TEXTURE_2D_ARRAY)
  1612. or (glTarget = GL_TEXTURE_CUBE_MAP_ARRAY);
  1613. repeat
  1614. // Check level existence
  1615. glGetTexLevelParameteriv(glTarget, FLevelCount,
  1616. GL_TEXTURE_INTERNAL_FORMAT,
  1617. @texFormat);
  1618. if texFormat = 1 then
  1619. Break;
  1620. Inc(FLevelCount);
  1621. if FLevelCount = 1 then
  1622. begin
  1623. glGetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_WIDTH, @FLOD[0].Width);
  1624. glGetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_HEIGHT,@FLOD[0].Height);
  1625. FLOD[0].Depth := 0;
  1626. if (glTarget = GL_TEXTURE_3D)
  1627. or (glTarget = GL_TEXTURE_2D_ARRAY)
  1628. or (glTarget = GL_TEXTURE_CUBE_MAP_ARRAY) then
  1629. glGetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_DEPTH, @FLOD[0].Depth);
  1630. residentFormat := OpenGLFormatToInternalFormat(texFormat);
  1631. if CastToFormat then
  1632. fInternalFormat := residentFormat
  1633. else
  1634. fInternalFormat := intFormat;
  1635. FindCompatibleDataFormat(fInternalFormat, fColorFormat, fDataType);
  1636. // Substitute properties if need
  1637. if colorFormat > 0 then
  1638. fColorFormat := colorFormat;
  1639. if dataType > 0 then
  1640. fDataType := dataType;
  1641. // Get optimal number or MipMap levels
  1642. optLod := GetImageLodNumber(GetWidth, GetHeight, GetDepth, glTarget = GL_TEXTURE_3D);
  1643. if texLod > optLod then
  1644. texLod := optLod;
  1645. // Check for MipMap posibility
  1646. if ((fInternalFormat >= tfFLOAT_R16)
  1647. and (fInternalFormat <= tfFLOAT_RGBA32)) then
  1648. texLod := 1;
  1649. end;
  1650. until FLevelCount = Integer(texLod);
  1651. if FLevelCount > 0 then
  1652. begin
  1653. fElementSize := GetTextureElementSize(fColorFormat, fDataType);
  1654. UpdateLevelsInfo;
  1655. ReallocMem(FData, DataSize);
  1656. lData := PGLubyte(fData);
  1657. bCompressed := IsCompressed;
  1658. vtcBuffer := nil;
  1659. w := GetWidth;
  1660. h := GetHeight;
  1661. d := GetDepth;
  1662. for face := 0 to maxFace do
  1663. begin
  1664. if fCubeMap then
  1665. glTarget := face + GL_TEXTURE_CUBE_MAP_POSITIVE_X;
  1666. for level := 0 to FLevelCount - 1 do
  1667. begin
  1668. if bCompressed then
  1669. begin
  1670. if {NV_texture_compression_vtc and} (d > 1) and not fTextureArray then
  1671. begin
  1672. if level = 0 then
  1673. GetMem(vtcBuffer, GetLevelSizeInByte(0));
  1674. glGetCompressedTexImage(glTarget, level, vtcBuffer);
  1675. // Shufle blocks from VTC to S3TC
  1676. cw := (w + 3) div 4;
  1677. ch := (h + 3) div 4;
  1678. top := lData;
  1679. for k := 0 to d - 1 do
  1680. for i := 0 to ch - 1 do
  1681. for j := 0 to cw - 1 do
  1682. begin
  1683. bottom := vtcBuffer;
  1684. Inc(bottom, blockOffset(j, i, k));
  1685. Move(bottom^, top^, fElementSize);
  1686. Inc(top, fElementSize);
  1687. end;
  1688. Div2(w);
  1689. Div2(h);
  1690. Div2(d);
  1691. end
  1692. else
  1693. glGetCompressedTexImage(glTarget, level, lData);
  1694. end
  1695. else
  1696. glGetTexImage(glTarget, level, fColorFormat, fDataType, lData);
  1697. Inc(lData, GetLevelSizeInByte(level));
  1698. end; // for level
  1699. end; // for face
  1700. if Assigned(vtcBuffer) then
  1701. FreeMem(vtcBuffer);
  1702. // Check memory corruption
  1703. ReallocMem(FData, DataSize);
  1704. end;
  1705. if Self is TgxImage then
  1706. begin
  1707. TgxImage(Self).FBlank := FLevelCount = 0;
  1708. if FLevelCount = 0 then
  1709. begin
  1710. UnMipmap;
  1711. FreeMem(fData);
  1712. fData := nil;
  1713. end;
  1714. end;
  1715. glGetError;
  1716. Result := True;
  1717. finally
  1718. LContext.Deactivate;
  1719. end;
  1720. end;
  1721. procedure TgxBaseImage.SaveHeader;
  1722. var
  1723. Temp: Integer;
  1724. LStream: TStream;
  1725. begin
  1726. Temp := 0;
  1727. LStream := nil;
  1728. try
  1729. LStream := TFileStream.Create(ResourceName, fmOpenWrite or fmCreate);
  1730. with LStream do
  1731. begin
  1732. Write(Temp, SizeOf(Integer)); // Version
  1733. Write(FLOD[0].Width, SizeOf(Integer));
  1734. Write(FLOD[0].Height, SizeOf(Integer));
  1735. Write(FLOD[0].Depth, SizeOf(Integer));
  1736. Write(fColorFormat, SizeOf(GLenum));
  1737. Temp := Integer(fInternalFormat);
  1738. Write(Temp, SizeOf(Integer));
  1739. Write(fDataType, SizeOf(GLenum));
  1740. Write(fElementSize, SizeOf(Integer));
  1741. Write(fLevelCount, SizeOf(TgxImageLODRange));
  1742. Temp := Integer(fCubeMap);
  1743. Write(Temp, SizeOf(Integer));
  1744. Temp := Integer(fTextureArray);
  1745. Write(Temp, SizeOf(Integer));
  1746. end;
  1747. finally
  1748. LStream.Free;
  1749. end;
  1750. end;
  1751. procedure TgxBaseImage.LoadHeader;
  1752. var
  1753. Temp: Integer;
  1754. LStream: TStream;
  1755. begin
  1756. LStream := nil;
  1757. try
  1758. LStream := TFileStream.Create(ResourceName, fmOpenRead);
  1759. with LStream do
  1760. begin
  1761. Read(Temp, SizeOf(Integer)); // Version
  1762. if Temp > 0 then
  1763. begin
  1764. ShowMessage(Format(strUnknownArchive, [Self.ClassType, Temp]));
  1765. Abort;
  1766. end;
  1767. Read(FLOD[0].Width, SizeOf(Integer));
  1768. Read(FLOD[0].Height, SizeOf(Integer));
  1769. Read(FLOD[0].Depth, SizeOf(Integer));
  1770. Read(fColorFormat, SizeOf(GLenum));
  1771. Read(Temp, SizeOf(Integer));
  1772. fInternalFormat := TglInternalFormat(Temp);
  1773. Read(fDataType, SizeOf(GLenum));
  1774. Read(fElementSize, SizeOf(Integer));
  1775. Read(fLevelCount, SizeOf(TgxImageLODRange));
  1776. Read(Temp, SizeOf(Integer));
  1777. fCubeMap := Boolean(Temp);
  1778. Read(Temp, SizeOf(Integer));
  1779. fTextureArray := Boolean(Temp);
  1780. UpdateLevelsInfo;
  1781. end;
  1782. finally
  1783. LStream.Free;
  1784. end;
  1785. end;
  1786. var
  1787. vGlobalStreamingTaskCounter: Integer = 0;
  1788. procedure TgxBaseImage.StartStreaming;
  1789. var
  1790. level: TgxImageLODRange;
  1791. begin
  1792. FStreamLevel := fLevelCount - 1;
  1793. for level := 0 to High(TgxImageLODRange) do
  1794. FLOD[level].State := ssKeeping;
  1795. end;
  1796. procedure TgxBaseImage.DoStreaming;
  1797. begin
  1798. {$IFDEF USE_SERVICE_CONTEXT}
  1799. if Assigned(FFinishEvent) then
  1800. begin
  1801. if FFinishEvent.WaitFor(0) <> wrSignaled then
  1802. exit;
  1803. end
  1804. else
  1805. FFinishEvent := TFinishTaskEvent.Create;
  1806. Inc(vGlobalStreamingTaskCounter);
  1807. AddTaskForServiceContext(ImageStreamingTask, FFinishEvent);
  1808. {$ENDIF}
  1809. end;
  1810. {$IFDEF USE_SERVICE_CONTEXT}
  1811. procedure TgxBaseImage.ImageStreamingTask;
  1812. var
  1813. readSize: Integer;
  1814. ptr: PByte;
  1815. begin
  1816. with FLOD[FStreamLevel] do
  1817. begin
  1818. if PBO = nil then
  1819. PBO := TgxUnpackPBOHandle.Create;
  1820. PBO.AllocateHandle;
  1821. if PBO.IsDataNeedUpdate then
  1822. begin
  1823. { This may work with multiple unshared context, but never tested
  1824. because unlikely. }
  1825. PBO.BindBufferData(nil, MaxInteger(Size, 1024), GL_STREAM_DRAW);
  1826. if Assigned(MapAddress) then;
  1827. if not (glUnmapBuffer(PBO.AllocateHandle) = 1) then
  1828. exit;
  1829. MapAddress := PBO.MapBuffer(GL_WRITE_ONLY);
  1830. StreamOffset := 0;
  1831. PBO.UnBind;
  1832. PBO.NotifyDataUpdated;
  1833. end;
  1834. if FSourceStream = nil then
  1835. begin
  1836. FSourceStream := TFileStream.Create(ResourceName + IntToHex(FStreamLevel, 2));
  1837. end;
  1838. // Move to position of next piece and read it
  1839. readSize := MinInteger(Cardinal(8192 div vGlobalStreamingTaskCounter),
  1840. Cardinal(Size - StreamOffset));
  1841. if readSize > 0 then
  1842. begin
  1843. ptr := PByte(MapAddress);
  1844. Inc(ptr, StreamOffset);
  1845. FSourceStream.Read(ptr^, readSize);
  1846. Inc(StreamOffset, readSize);
  1847. end;
  1848. Dec(vGlobalStreamingTaskCounter);
  1849. if StreamOffset >= Size then
  1850. begin
  1851. PBO.Bind;
  1852. if glUnmapBuffer(PBO.AllocateHandle) > 0 then
  1853. State := ssLoaded;
  1854. PBO.UnBind;
  1855. if State <> ssLoaded then
  1856. exit; // Can't unmap
  1857. MapAddress := nil;
  1858. StreamOffset := 0;
  1859. if FStreamLevel > 0 then
  1860. Dec(FStreamLevel);
  1861. FSourceStream.Destroy;
  1862. FSourceStream := nil;
  1863. end;
  1864. end;
  1865. end;
  1866. {$ENDIF}
  1867. // ------------------
  1868. // ------------------ TgxImage ------------------
  1869. // ------------------
  1870. constructor TgxImage.Create;
  1871. begin
  1872. inherited Create;
  1873. SetBlank(false);
  1874. end;
  1875. destructor TgxImage.Destroy;
  1876. begin
  1877. inherited Destroy;
  1878. end;
  1879. procedure TgxImage.Assign(Source: TPersistent);
  1880. var
  1881. bmp: TBitmap;
  1882. graphic: TBitmap;
  1883. begin
  1884. if (Source is TgxImage) or (Source is TgxBaseImage) then
  1885. begin
  1886. if Source is TgxImage then
  1887. FBlank := TgxImage(Source).fBlank
  1888. else
  1889. FBlank := false;
  1890. if not FBlank then
  1891. inherited
  1892. else
  1893. begin
  1894. FLOD := TgxImage(Source).FLOD;
  1895. FLevelCount := TgxImage(Source).FLevelCount;
  1896. fCubeMap := TgxImage(Source).fCubeMap;
  1897. fColorFormat := TgxImage(Source).fColorFormat;
  1898. fInternalFormat := TgxImage(Source).fInternalFormat;
  1899. fDataType := TgxImage(Source).fDataType;
  1900. fElementSize := TgxImage(Source).fElementSize;
  1901. fTextureArray := TgxImage(Source).fTextureArray;
  1902. end;
  1903. end
  1904. else if Source is TBitmap then
  1905. begin
  1906. if (Source is TBitmap)
  1907. and (TBitmap(Source).PixelFormat in [TPixelFormat.RGBA16, TPixelFormat.RGBA32F])
  1908. and (((TBitmap(Source).Width and 3) = 0) or (GL_EXT_bgra)) then
  1909. begin
  1910. if TBitmap(Source).PixelFormat = TPixelFormat.RGBA32F then
  1911. AssignFrom24BitsBitmap(TBitmap(Source))
  1912. else
  1913. AssignFrom32BitsBitmap(TBitmap(Source))
  1914. end
  1915. {$IFDEF USE_PngImage_SUPPORT}
  1916. else if Source is TPngImage then
  1917. AssignFromPngImage(TPngImage(Source))
  1918. {$ENDIF}
  1919. else
  1920. begin
  1921. graphic := TBitmap(Source);
  1922. bmp := TBitmap.Create;
  1923. try
  1924. // crossbuilder: useless to set pixelformat before setting the size ?
  1925. // or maybe just useless at all on gtk .. as soon as
  1926. // bmp.canvas is touched, it's the pixelformat of the device
  1927. // no matter what was adjusted before ??
  1928. // bmp.PixelFormat:=glpf24bit;
  1929. // bmp.Height:=graphic.Height;
  1930. // crossbuilder: using setsize because setting width or height while
  1931. // the other one is zero results in not setting with/hight
  1932. { TODO -oPW : E2129 Cannot assign to a read-only property }
  1933. (*bmp.PixelFormat := glpf24bit;*)
  1934. { TODO -oPW : E2010 Incompatible types: 'Integer' and 'Single' }
  1935. (*bmp.Height := Graphic.Height;*)
  1936. { TODO -oPW : E2015 Operator not applicable to this operand type }
  1937. (*
  1938. if (graphic.Width and 3) = 0 then
  1939. begin
  1940. bmp.Width := graphic.Width;
  1941. bmp.Canvas.Draw(0, 0, graphic);
  1942. end
  1943. else
  1944. begin
  1945. bmp.Width := (graphic.Width and $FFFC) + 4;
  1946. bmp.Canvas.StretchDraw(Rect(0, 0, bmp.Width, bmp.Height), graphic);
  1947. end;
  1948. *)
  1949. AssignFrom24BitsBitmap(bmp);
  1950. finally
  1951. bmp.Free;
  1952. end;
  1953. end;
  1954. end
  1955. {$IFDEF USE_GRAPHICS32}
  1956. else if Source is TBitmap32 then
  1957. begin
  1958. Narrow;
  1959. AssignFromBitmap32(TBitmap32(Source));
  1960. end
  1961. {$ENDIF}
  1962. else
  1963. inherited;
  1964. end;
  1965. procedure TgxImage.AssignFrom24BitsBitmap(aBitmap: TBitmap);
  1966. var
  1967. y, lineSize: Integer;
  1968. rowOffset: Int64;
  1969. pSrc, pDest: PAnsiChar;
  1970. begin
  1971. Assert(aBitmap.PixelFormat = TPixelFormat.RGBA32F);
  1972. UnMipmap;
  1973. FLOD[0].Width := aBitmap.Width;
  1974. FLOD[0].Height := aBitmap.Height;
  1975. FLOD[0].Depth := 0;
  1976. if (GL_EXT_bgra) then
  1977. begin
  1978. fColorFormat := GL_BGR;
  1979. fElementSize := 3;
  1980. end
  1981. else
  1982. begin
  1983. Assert((aBitmap.Width and 3) = 0);
  1984. fColorFormat := GL_RGBA;
  1985. fElementSize := 4;
  1986. end;
  1987. fInternalFormat := tfRGBA8;
  1988. fDataType := GL_UNSIGNED_BYTE;
  1989. fCubeMap := false;
  1990. fTextureArray := false;
  1991. ReallocMem(FData, DataSize);
  1992. FBlank := false;
  1993. lineSize := GetWidth * fElementSize;
  1994. if Height > 0 then
  1995. begin
  1996. pDest := @PAnsiChar(FData)[GetWidth * fElementSize * (GetHeight - 1)];
  1997. if Height = 1 then
  1998. begin
  1999. if true {GL_EXT_bgra} then
  2000. begin
  2001. pSrc := BitmapScanLine(aBitmap, 0);
  2002. Move(pSrc^, pDest^, lineSize);
  2003. end
  2004. else
  2005. BGR24ToRGBA32(BitmapScanLine(aBitmap, 0), pDest, GetWidth);
  2006. end
  2007. else
  2008. begin
  2009. if VerticalReverseOnAssignFromBitmap then
  2010. begin
  2011. pSrc := BitmapScanLine(aBitmap, GetHeight - 1);
  2012. rowOffset := Integer(BitmapScanLine(aBitmap, GetHeight - 2)) -
  2013. Integer(pSrc);
  2014. end
  2015. else
  2016. begin
  2017. pSrc := BitmapScanLine(aBitmap, 0);
  2018. rowOffset := Int64(BitmapScanLine(aBitmap, 1)) - Int64(pSrc);
  2019. end;
  2020. if true {GL_EXT_bgra} then
  2021. begin
  2022. for y := 0 to Height - 1 do
  2023. begin
  2024. Move(pSrc^, pDest^, lineSize);
  2025. Dec(pDest, lineSize);
  2026. Inc(pSrc, rowOffset);
  2027. end;
  2028. end
  2029. else
  2030. begin
  2031. for y := 0 to Height - 1 do
  2032. begin
  2033. BGR24ToRGBA32(pSrc, pDest, Width);
  2034. Dec(pDest, lineSize);
  2035. Inc(pSrc, rowOffset);
  2036. end;
  2037. end;
  2038. end;
  2039. end;
  2040. end;
  2041. procedure TgxImage.AssignFromBitmap24WithoutRGBSwap(aBitmap: TBitmap);
  2042. var
  2043. y: Integer;
  2044. rowOffset: Int64;
  2045. pSrc, pDest: PAnsiChar;
  2046. begin
  2047. Assert(aBitmap.PixelFormat = TPixelFormat.RGBA32F);
  2048. Assert((aBitmap.Width and 3) = 0);
  2049. UnMipmap;
  2050. FLOD[0].Width := aBitmap.Width;
  2051. FLOD[0].Height := aBitmap.Height;
  2052. FLOD[0].Depth := 0;
  2053. fColorFormat := GL_RGBA;
  2054. fInternalFormat := tfRGBA8;
  2055. fDataType := GL_UNSIGNED_BYTE;
  2056. fElementSize := 4;
  2057. fCubeMap := false;
  2058. fTextureArray := false;
  2059. ReallocMem(FData, DataSize);
  2060. FBlank := false;
  2061. if Height > 0 then
  2062. begin
  2063. pDest := @PAnsiChar(FData)[Width * 4 * (Height - 1)];
  2064. if Height = 1 then
  2065. begin
  2066. RGB24ToRGBA32(BitmapScanLine(aBitmap, 0), pDest, GetWidth);
  2067. end
  2068. else
  2069. begin
  2070. if VerticalReverseOnAssignFromBitmap then
  2071. begin
  2072. pSrc := BitmapScanLine(aBitmap, GetHeight - 1);
  2073. rowOffset := Cardinal(BitmapScanLine(aBitmap, GetHeight - 2));
  2074. Dec(rowOffset, Cardinal(pSrc));
  2075. end
  2076. else
  2077. begin
  2078. pSrc := BitmapScanLine(aBitmap, 0);
  2079. rowOffset := Cardinal(BitmapScanLine(aBitmap, 1));
  2080. Dec(rowOffset, Cardinal(pSrc));
  2081. end;
  2082. for y := 0 to Height - 1 do
  2083. begin
  2084. RGB24ToRGBA32(pSrc, pDest, GetWidth);
  2085. Dec(pDest, GetWidth * 4);
  2086. Inc(pSrc, rowOffset);
  2087. end;
  2088. end;
  2089. end;
  2090. end;
  2091. procedure TgxImage.AssignFrom32BitsBitmap(aBitmap: TBitmap);
  2092. var
  2093. y: Integer;
  2094. rowOffset: Int64;
  2095. pSrc, pDest: PAnsiChar;
  2096. begin
  2097. Assert(aBitmap.PixelFormat = TPixelFormat.RGBA32F);
  2098. UnMipmap;
  2099. FLOD[0].Width := aBitmap.Width;
  2100. FLOD[0].Height := aBitmap.Height;
  2101. FLOD[0].Depth := 0;
  2102. if true {GL_EXT_bgra} then
  2103. fColorFormat := GL_BGRA
  2104. else
  2105. begin
  2106. Assert((aBitmap.Width and 3) = 0);
  2107. fColorFormat := GL_RGBA;
  2108. end;
  2109. fInternalFormat := tfRGBA8;
  2110. fDataType := GL_UNSIGNED_BYTE;
  2111. fElementSize := 4;
  2112. fCubeMap := false;
  2113. fTextureArray := false;
  2114. ReallocMem(FData, DataSize);
  2115. FBlank := false;
  2116. if Height > 0 then
  2117. begin
  2118. pDest := @PAnsiChar(FData)[Width * 4 * (Height - 1)];
  2119. if VerticalReverseOnAssignFromBitmap then
  2120. begin
  2121. pSrc := BitmapScanLine(aBitmap, Height - 1);
  2122. if Height > 1 then
  2123. begin
  2124. rowOffset := Cardinal(BitmapScanLine(aBitmap, Height - 2));
  2125. Dec(rowOffset, Cardinal(pSrc));
  2126. end
  2127. else
  2128. rowOffset := 0;
  2129. end
  2130. else
  2131. begin
  2132. pSrc := BitmapScanLine(aBitmap, 0);
  2133. if Height > 1 then
  2134. begin
  2135. rowOffset := Cardinal(BitmapScanLine(aBitmap, 1));
  2136. Dec(rowOffset, Cardinal(pSrc));
  2137. end
  2138. else
  2139. rowOffset := 0;
  2140. end;
  2141. if GL_EXT_bgra then
  2142. begin
  2143. for y := 0 to Height - 1 do
  2144. begin
  2145. Move(pSrc^, pDest^, Width * 4);
  2146. Dec(pDest, Width * 4);
  2147. Inc(pSrc, rowOffset);
  2148. end;
  2149. end
  2150. else
  2151. begin
  2152. for y := 0 to Height - 1 do
  2153. begin
  2154. BGRA32ToRGBA32(pSrc, pDest, Width);
  2155. Dec(pDest, Width * 4);
  2156. Inc(pSrc, rowOffset);
  2157. end;
  2158. end;
  2159. end;
  2160. end;
  2161. {$IFDEF USE_GRAPHICS32}
  2162. procedure TgxImage.AssignFromBitmap32(aBitmap32: TBitmap32);
  2163. var
  2164. y: Integer;
  2165. pSrc, pDest: PAnsiChar;
  2166. begin
  2167. UnMipmap;
  2168. FLOD[0].Width := aBitmap32.Width;
  2169. FLOD[0].Height := aBitmap32.Height;
  2170. FLOD[0].Depth := 0;
  2171. fColorFormat := GL_RGBA;
  2172. fInternalFormat := tfRGBA8;
  2173. fDataType := GL_UNSIGNED_BYTE;
  2174. fElementSize := 4;
  2175. fCubeMap := false;
  2176. fTextureArray := false;
  2177. ReallocMem(FData, DataSize);
  2178. FBlank := false;
  2179. if Height > 0 then
  2180. begin
  2181. pDest := @PAnsiChar(FData)[Width * 4 * (Height - 1)];
  2182. for y := 0 to Height - 1 do
  2183. begin
  2184. if VerticalReverseOnAssignFromBitmap then
  2185. pSrc := PAnsiChar(aBitmap32.ScanLine[Height - 1 - y])
  2186. else
  2187. pSrc := PAnsiChar(aBitmap32.ScanLine[y]);
  2188. BGRA32ToRGBA32(pSrc, pDest, Width);
  2189. Dec(pDest, Width * 4);
  2190. end;
  2191. end;
  2192. end;
  2193. {$ENDIF}
  2194. // AlphaChannel Support
  2195. procedure TgxImage.AssignFromPngImage(aPngImage: TBitmapImage);
  2196. var
  2197. i, j: Integer;
  2198. SourceScan: PRGBQuad; //VCL->PRGBLine;
  2199. DestScan: PgxPixel32Array;
  2200. AlphaScan: pByteArray;
  2201. Pixel: Integer;
  2202. begin
  2203. (*
  2204. if (aPngImage.Width and 3) > 0 then
  2205. aPngImage.Resize((aPngImage.Width and $FFFC) + 4, aPngImage.Height);
  2206. *)
  2207. UnMipmap;
  2208. FLOD[0].Width := aPngImage.Width;
  2209. FLOD[0].Height := aPngImage.Height;
  2210. FLOD[0].Depth := 0;
  2211. fColorFormat := GL_RGBA;
  2212. fInternalFormat := tfRGBA8;
  2213. fDataType := GL_UNSIGNED_BYTE;
  2214. fElementSize := 4;
  2215. fCubeMap := false;
  2216. fTextureArray := false;
  2217. ReallocMem(FData, DataSize);
  2218. FBlank := False;
  2219. (*
  2220. case aPngImage.Header.ColorType of
  2221. { Direct ScanLine (24 Bits) }
  2222. COLOR_RGB, COLOR_RGBALPHA: for j := 1 to aPngImage.Height do
  2223. begin
  2224. SourceScan := aPngImage.Scanline[aPngImage.Height - j];
  2225. AlphaScan := aPngImage.AlphaScanline[aPngImage.Height - j];
  2226. DestScan := ScanLine[Pred(j)];
  2227. for i := 0 to Pred(aPngImage.Width) do
  2228. begin
  2229. DestScan^[i].r := SourceScan^[i].rgbtRed;
  2230. DestScan^[i].g := SourceScan^[i].rgbtGreen;
  2231. DestScan^[i].b := SourceScan^[i].rgbtBlue;
  2232. if Assigned(AlphaScan) then
  2233. DestScan^[i].a := AlphaScan^[i]
  2234. else
  2235. DestScan^[i].a := $FF;
  2236. end;
  2237. end;
  2238. else
  2239. { Internal Decode TColor - Palette }
  2240. for j := 1 to aPngImage.Height do
  2241. begin
  2242. AlphaScan := aPngImage.AlphaScanline[aPngImage.Height - j];
  2243. DestScan := ScanLine[Pred(j)];
  2244. for i := 0 to Pred(aPngImage.Width) do
  2245. begin
  2246. Pixel := aPngImage.Pixels[i, aPngImage.Height - j];
  2247. DestScan^[i].r := Pixel and $FF;
  2248. DestScan^[i].g := (Pixel shr 8) and $FF;
  2249. DestScan^[i].b := (Pixel shr 16) and $FF;
  2250. if Assigned(AlphaScan) then
  2251. DestScan^[i].a := AlphaScan^[i]
  2252. else
  2253. DestScan^[i].a := $FF;
  2254. end;
  2255. end;
  2256. end;
  2257. *)
  2258. end;
  2259. procedure TgxImage.AssignFromTexture2D(textureHandle: Cardinal);
  2260. var
  2261. oldTex: Cardinal;
  2262. begin
  2263. UnMipmap;
  2264. with CurrentContext.gxStates do
  2265. begin
  2266. oldTex := TextureBinding[ActiveTexture, ttTexture2D];
  2267. TextureBinding[ActiveTexture, ttTexture2D] := textureHandle;
  2268. glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, @FLOD[0].Width);
  2269. glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, @FLOD[0].Height);
  2270. FLOD[0].Depth := 0;
  2271. fColorFormat := GL_RGBA;
  2272. fInternalFormat := tfRGBA8;
  2273. fDataType := GL_UNSIGNED_BYTE;
  2274. fElementSize := 4;
  2275. fCubeMap := false;
  2276. fTextureArray := false;
  2277. ReallocMem(FData, DataSize);
  2278. glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, FData);
  2279. FBlank := false;
  2280. TextureBinding[ActiveTexture, ttTexture2D] := oldTex;
  2281. end;
  2282. end;
  2283. procedure TgxImage.AssignFromTexture2D(textureHandle: TgxTextureHandle);
  2284. var
  2285. oldContext: TgxContext;
  2286. contextActivate: Boolean;
  2287. begin
  2288. if Assigned(textureHandle) and (textureHandle.Handle <> 0) then
  2289. begin
  2290. oldContext := CurrentContext;
  2291. contextActivate := (oldContext <> textureHandle.RenderingContext);
  2292. if contextActivate then
  2293. begin
  2294. if Assigned(oldContext) then
  2295. oldContext.Deactivate;
  2296. textureHandle.RenderingContext.Activate;
  2297. end;
  2298. try
  2299. AssignFromTexture2D(textureHandle.Handle);
  2300. finally
  2301. if contextActivate then
  2302. begin
  2303. textureHandle.RenderingContext.Deactivate;
  2304. if Assigned(oldContext) then
  2305. oldContext.Activate;
  2306. end;
  2307. end;
  2308. end
  2309. else
  2310. begin
  2311. // Make image empty
  2312. UnMipmap;
  2313. FLOD[0].Width := 0;
  2314. FLOD[0].Height := 0;
  2315. FLOD[0].Depth := 0;
  2316. fColorFormat := GL_RGBA;
  2317. fInternalFormat := tfRGBA8;
  2318. fDataType := GL_UNSIGNED_BYTE;
  2319. fElementSize := 4;
  2320. fCubeMap := false;
  2321. fTextureArray := false;
  2322. ReallocMem(FData, DataSize);
  2323. end;
  2324. end;
  2325. function TgxImage.Create32BitsBitmap: TBitmap;
  2326. var
  2327. y, x, x4: Integer;
  2328. pSrc, pDest: PAnsiChar;
  2329. begin
  2330. if FBlank then
  2331. begin
  2332. Result := nil;
  2333. exit;
  2334. end;
  2335. Narrow;
  2336. Result := TBitmap.Create;
  2337. { TODO : E2129 Cannot assign to a read-only property }
  2338. (*Result.PixelFormat := glpf32bit;*)
  2339. Result.Width := Width;
  2340. Result.Height := Height;
  2341. if Height > 0 then
  2342. begin
  2343. pSrc := @PAnsiChar(FData)[Width * 4 * (Height - 1)];
  2344. for y := 0 to Height - 1 do
  2345. begin
  2346. pDest := BitmapScanLine(Result, y);
  2347. for x := 0 to Width - 1 do
  2348. begin
  2349. x4 := x * 4;
  2350. pDest[x4 + 0] := pSrc[x4 + 2];
  2351. pDest[x4 + 1] := pSrc[x4 + 1];
  2352. pDest[x4 + 2] := pSrc[x4 + 0];
  2353. pDest[x4 + 3] := pSrc[x4 + 3];
  2354. end;
  2355. Dec(pSrc, Width * 4);
  2356. end;
  2357. end;
  2358. end;
  2359. procedure TgxImage.SetWidth(val: Integer);
  2360. begin
  2361. if val <> FLOD[0].Width then
  2362. begin
  2363. Assert(val >= 0);
  2364. FLOD[0].Width := val;
  2365. FBlank := true;
  2366. end;
  2367. end;
  2368. procedure TgxImage.SetHeight(const val: Integer);
  2369. begin
  2370. if val <> FLOD[0].Height then
  2371. begin
  2372. Assert(val >= 0);
  2373. FLOD[0].Height := val;
  2374. FBlank := true;
  2375. end;
  2376. end;
  2377. procedure TgxImage.SetDepth(const val: Integer);
  2378. begin
  2379. if val <> FLOD[0].Depth then
  2380. begin
  2381. Assert(val >= 0);
  2382. FLOD[0].Depth := val;
  2383. FBlank := true;
  2384. end;
  2385. end;
  2386. procedure TgxImage.SetCubeMap(const val: Boolean);
  2387. begin
  2388. if val <> fCubeMap then
  2389. begin
  2390. fCubeMap := val;
  2391. FBlank := true;
  2392. end;
  2393. end;
  2394. procedure TgxImage.SetArray(const val: Boolean);
  2395. begin
  2396. if val <> fTextureArray then
  2397. begin
  2398. fTextureArray := val;
  2399. FBlank := true;
  2400. end;
  2401. end;
  2402. procedure TgxImage.SetColorFormatDataType(const AColorFormat, ADataType: GLenum);
  2403. begin
  2404. if fBlank then
  2405. begin
  2406. fDataType := ADataType;
  2407. fColorFormat := AColorFormat;
  2408. exit;
  2409. end;
  2410. fOldDataType := fDataType;
  2411. fOldColorFormat := fColorFormat;
  2412. fDataType := ADataType;
  2413. fColorFormat := AColorFormat;
  2414. fElementSize := GetTextureElementSize(fColorFormat, fDataType);
  2415. DataConvertTask;
  2416. end;
  2417. function TgxImage.GetScanLine(index: Integer): PgxPixel32Array;
  2418. begin
  2419. Narrow;
  2420. Result := PgxPixel32Array(@FData[index * GetWidth]);
  2421. end;
  2422. procedure TgxImage.SetAlphaFromIntensity;
  2423. var
  2424. i: Integer;
  2425. begin
  2426. Narrow;
  2427. for i := 0 to (DataSize div 4) - 1 do
  2428. with FData^[i] do
  2429. a := (Integer(r) + Integer(g) + Integer(b)) div 3;
  2430. end;
  2431. procedure TgxImage.SetAlphaTransparentForColor(const aColor: TColor);
  2432. var
  2433. color: TgxPixel24;
  2434. begin
  2435. color.r := GetRValue(aColor);
  2436. color.g := GetGValue(aColor);
  2437. color.b := GetBValue(aColor);
  2438. SetAlphaTransparentForColor(color);
  2439. end;
  2440. procedure TgxImage.SetAlphaTransparentForColor(const aColor: TgxPixel32);
  2441. var
  2442. color: TgxPixel24;
  2443. begin
  2444. color.r := aColor.r;
  2445. color.g := aColor.g;
  2446. color.b := aColor.b;
  2447. SetAlphaTransparentForColor(color);
  2448. end;
  2449. procedure TgxImage.SetAlphaTransparentForColor(const aColor: TgxPixel24);
  2450. var
  2451. i: Integer;
  2452. intCol: Integer;
  2453. begin
  2454. Narrow;
  2455. intCol := (PInteger(@aColor)^) and $FFFFFF;
  2456. for i := 0 to (DataSize div 4) - 1 do
  2457. if PInteger(@FData[i])^ and $FFFFFF = intCol then
  2458. FData^[i].a := 0
  2459. else
  2460. FData^[i].a := 255;
  2461. end;
  2462. procedure TgxImage.SetAlphaToValue(const aValue: Byte);
  2463. var
  2464. i: Integer;
  2465. begin
  2466. Narrow;
  2467. for i := 0 to (DataSize div 4) - 1 do
  2468. FData^[i].a := aValue
  2469. end;
  2470. procedure TgxImage.SetAlphaToFloatValue(const aValue: Single);
  2471. begin
  2472. SetAlphaToValue(Byte(Trunc(aValue * 255) and 255));
  2473. end;
  2474. procedure TgxImage.InvertAlpha;
  2475. var
  2476. i: Integer;
  2477. begin
  2478. Narrow;
  2479. for i := (DataSize div 4) - 1 downto 0 do
  2480. FData^[i].a := 255 - FData^[i].a;
  2481. end;
  2482. procedure TgxImage.SqrtAlpha;
  2483. var
  2484. i: Integer;
  2485. sqrt255Array: PSqrt255Array;
  2486. begin
  2487. Narrow;
  2488. sqrt255Array := GetSqrt255Array;
  2489. for i := 0 to (DataSize div 4) - 1 do
  2490. with FData^[i] do
  2491. a := sqrt255Array^[(Integer(r) + Integer(g) + Integer(b)) div 3];
  2492. end;
  2493. procedure TgxImage.BrightnessCorrection(const factor: Single);
  2494. begin
  2495. if Assigned(FData) then
  2496. begin
  2497. Narrow;
  2498. BrightenRGBAArray(Data, DataSize div 4, factor);
  2499. end;
  2500. end;
  2501. procedure TgxImage.GammaCorrection(const gamma: Single);
  2502. begin
  2503. if Assigned(FData) then
  2504. begin
  2505. Narrow;
  2506. GammaCorrectRGBAArray(Data, DataSize div 4, gamma);
  2507. end;
  2508. end;
  2509. procedure TgxImage.DownSampleByFactor2;
  2510. type
  2511. T2Pixel32 = packed array[0..1] of TgxPixel32;
  2512. P2Pixel32 = ^T2Pixel32;
  2513. procedure ProcessRowPascal(pDest: PgxPixel32; pLineA, pLineB: P2Pixel32; n:
  2514. Integer);
  2515. var
  2516. i: Integer;
  2517. begin
  2518. for i := 0 to n - 1 do
  2519. begin
  2520. pDest^.r := (pLineA^[0].r + pLineA^[1].r + pLineB^[0].r + pLineB^[1].r)
  2521. shr 2;
  2522. pDest^.g := (pLineA^[0].g + pLineA^[1].g + pLineB^[0].g + pLineB^[1].g)
  2523. shr 2;
  2524. pDest^.b := (pLineA^[0].b + pLineA^[1].b + pLineB^[0].b + pLineB^[1].b)
  2525. shr 2;
  2526. pDest^.a := (pLineA^[0].a + pLineA^[1].a + pLineB^[0].a + pLineB^[1].a)
  2527. shr 2;
  2528. Inc(pLineA);
  2529. Inc(pLineB);
  2530. Inc(pDest);
  2531. end;
  2532. end; // }
  2533. var
  2534. y, w2, h2: Integer;
  2535. pDest: PgxPixel32;
  2536. pLineA, pLineB: P2Pixel32;
  2537. begin
  2538. if (GetWidth <= 1) or (GetHeight <= 1) then
  2539. Exit;
  2540. Narrow;
  2541. w2 := GetWidth shr 1;
  2542. h2 := GetHeight shr 1;
  2543. pDest := @FData[0];
  2544. pLineA := @FData[0];
  2545. pLineB := @FData[Width];
  2546. begin
  2547. for y := 0 to h2 - 1 do
  2548. begin
  2549. ProcessRowPascal(pDest, pLineA, pLineB, w2);
  2550. Inc(pDest, w2);
  2551. Inc(pLineA, Width);
  2552. Inc(pLineB, Width);
  2553. end;
  2554. end;
  2555. FLOD[0].Width := w2;
  2556. FLOD[0].Height := h2;
  2557. ReallocMem(FData, DataSize);
  2558. end;
  2559. procedure TgxImage.ReadPixels(const area: TRect);
  2560. begin
  2561. UnMipmap;
  2562. FLOD[0].Width := (area.Right - area.Left) and $FFFC;
  2563. FLOD[0].Height := (area.Bottom - area.Top);
  2564. FLOD[0].Depth := 0;
  2565. fColorFormat := GL_RGBA;
  2566. fInternalFormat := tfRGBA8;
  2567. fDataType := GL_UNSIGNED_BYTE;
  2568. fElementSize := 4;
  2569. fCubeMap := false;
  2570. fTextureArray := false;
  2571. fBlank := false;
  2572. ReallocMem(FData, DataSize);
  2573. glReadPixels(0, 0, GetWidth, GetHeight, GL_RGBA, GL_UNSIGNED_BYTE, FData);
  2574. end;
  2575. procedure TgxImage.DrawPixels(const x, y: Single);
  2576. begin
  2577. if fBlank or IsEmpty then
  2578. Exit;
  2579. Assert(not CurrentContext.gxStates.ForwardContext);
  2580. glRasterPos2f(x, y);
  2581. glDrawPixels(Width, Height, fColorFormat, fDataType, FData);
  2582. end;
  2583. procedure TgxImage.GrayScaleToNormalMap(const scale: Single;
  2584. wrapX: Boolean = True; wrapY: Boolean = True);
  2585. var
  2586. x, y: Integer;
  2587. dcx, dcy: Single;
  2588. invLen: Single;
  2589. maskX, maskY: Integer;
  2590. curRow, nextRow, prevRow: PgxPixel32Array;
  2591. normalMapBuffer: PgxPixel32Array;
  2592. p: PgxPixel32;
  2593. begin
  2594. if Assigned(FData) then
  2595. begin
  2596. Narrow;
  2597. GetMem(normalMapBuffer, DataSize);
  2598. try
  2599. maskX := Width - 1;
  2600. maskY := Height - 1;
  2601. p := @normalMapBuffer[0];
  2602. for y := 0 to Height - 1 do
  2603. begin
  2604. curRow := GetScanLine(y);
  2605. if wrapY then
  2606. begin
  2607. prevRow := GetScanLine((y - 1) and maskY);
  2608. nextRow := GetScanLine((y + 1) and maskY);
  2609. end
  2610. else
  2611. begin
  2612. if y > 0 then
  2613. prevRow := GetScanLine(y - 1)
  2614. else
  2615. prevRow := curRow;
  2616. if y < Height - 1 then
  2617. nextRow := GetScanLine(y + 1)
  2618. else
  2619. nextRow := curRow;
  2620. end;
  2621. for x := 0 to Width - 1 do
  2622. begin
  2623. if wrapX then
  2624. dcx := scale * (curRow^[(x - 1) and maskX].g - curRow^[(x + 1) and
  2625. maskX].g)
  2626. else
  2627. begin
  2628. if x = 0 then
  2629. dcx := scale * (curRow^[x].g - curRow^[x + 1].g)
  2630. else if x < Width - 1 then
  2631. dcx := scale * (curRow^[x - 1].g - curRow^[x].g)
  2632. else
  2633. dcx := scale * (curRow^[x - 1].g - curRow^[x + 1].g);
  2634. end;
  2635. dcy := scale * (prevRow^[x].g - nextRow^[x].g);
  2636. invLen := 127 * RSqrt(dcx * dcx + dcy * dcy + 1);
  2637. with p^ do
  2638. begin
  2639. r := Integer(Round(128 + ClampValue(dcx * invLen, -128, 127)));
  2640. g := Integer(Round(128 + ClampValue(dcy * invLen, -128, 127)));
  2641. b := Integer(Round(128 + ClampValue(invLen, -128, 127)));
  2642. a := 255;
  2643. end;
  2644. Inc(p);
  2645. end;
  2646. end;
  2647. Move(normalMapBuffer^, FData^, DataSize);
  2648. finally
  2649. FreeMem(normalMapBuffer);
  2650. end;
  2651. end;
  2652. end;
  2653. procedure TgxImage.NormalizeNormalMap;
  2654. var
  2655. x, y: Integer;
  2656. sr, sg, sb: Single;
  2657. invLen: Single;
  2658. curRow: PgxPixel32Array;
  2659. p: PgxPixel32;
  2660. const
  2661. cInv128: Single = 1 / 128;
  2662. begin
  2663. if not IsEmpty and not Blank then
  2664. begin
  2665. Narrow;
  2666. for y := 0 to Height - 1 do
  2667. begin
  2668. curRow := @FData[y * GetWidth];
  2669. for x := 0 to GetWidth - 1 do
  2670. begin
  2671. p := @curRow[x];
  2672. sr := (p^.r - 128) * cInv128;
  2673. sg := (p^.g - 128) * cInv128;
  2674. sb := (p^.b - 128) * cInv128;
  2675. invLen := RSqrt(sr * sr + sg * sg + sb * sb);
  2676. p^.r := Round(128 + 127 * ClampValue(sr * invLen, -1, 1));
  2677. p^.g := Round(128 + 127 * ClampValue(sg * invLen, -1, 1));
  2678. p^.b := Round(128 + 127 * ClampValue(sb * invLen, -1, 1));
  2679. end;
  2680. end;
  2681. end;
  2682. end;
  2683. procedure TgxImage.SetBlank(const Value: boolean);
  2684. begin
  2685. if not Value and not IsEmpty then
  2686. ReallocMem(FData, DataSize);
  2687. FBlank := Value;
  2688. end;
  2689. //Converts a TgxImage back into a TBitmap
  2690. procedure TgxImage.AssignToBitmap(aBitmap: TBitmap); //TBitmap = TBitmap
  2691. var
  2692. y: integer;
  2693. pSrc, pDest: PAnsiChar;
  2694. begin
  2695. Narrow;
  2696. aBitmap.Width := GetWidth;
  2697. aBitmap.Height := GetHeight;
  2698. { TODO : E2129 Cannot assign to a read-only property }
  2699. (*aBitmap.PixelFormat := glpf32bit;*)
  2700. if FVerticalReverseOnAssignFromBitmap then
  2701. begin
  2702. for y := 0 to GetHeight - 1 do
  2703. begin
  2704. pSrc := @PAnsiChar(FData)[y * (GetWidth * 4)];
  2705. pDest := BitmapScanLine(aBitmap, y);
  2706. BGRA32ToRGBA32(pSrc, pDest, GetWidth);
  2707. end;
  2708. end
  2709. else
  2710. begin
  2711. for y := 0 to GetHeight - 1 do
  2712. begin
  2713. pSrc := @PAnsiChar(FData)[y * (GetWidth * 4)];
  2714. pDest := BitmapScanLine(aBitmap, GetHeight - 1 - y);
  2715. BGRA32ToRGBA32(pSrc, pDest, GetWidth);
  2716. end;
  2717. end;
  2718. end;
  2719. procedure TgxImage.GenerateMipmap(AFilter: TImageFilterFunction);
  2720. begin
  2721. if not FBlank then
  2722. inherited GenerateMipmap(AFilter);
  2723. end;
  2724. procedure TgxImage.UnMipmap;
  2725. begin
  2726. inherited UnMipmap;
  2727. if not (fBlank or IsEmpty) then
  2728. ReallocMem(FData, DataSize);
  2729. end;
  2730. procedure TgxImage.DataConvertTask;
  2731. var
  2732. oldLOD: TgxImagePiramid;
  2733. newData: Pointer;
  2734. ptr: PByte;
  2735. L: TgxImageLODRange;
  2736. d: Integer;
  2737. begin
  2738. oldLOD := FLOD;
  2739. if IsVolume then
  2740. begin
  2741. (* Message Hint 'TgxImage.DataConvertTask not yet implemented for volume images' *)
  2742. end
  2743. else
  2744. begin
  2745. GetMem(newData, DataSize);
  2746. d := MaxInteger(GetDepth, 1);
  2747. try
  2748. for L := FLevelCount - 1 downto 0 do
  2749. begin
  2750. ptr := newData;
  2751. Inc(ptr, oldLOD[L].Offset);
  2752. ConvertImage(
  2753. GetLevelAddress(L), ptr,
  2754. fOldColorFormat, fColorFormat,
  2755. fOldDataType, fDataType,
  2756. oldLOD[L].Width, oldLOD[L].Height * d);
  2757. end;
  2758. FreeMem(fData);
  2759. fData := newData;
  2760. except
  2761. FreeMem(newData);
  2762. ShowMessage(Format(strCantConvertImg, [ClassName]));
  2763. SetErrorImage;
  2764. end;
  2765. end;
  2766. end;
  2767. //---------------------------------------------------
  2768. initialization
  2769. //---------------------------------------------------
  2770. finalization
  2771. FreeAndNil(vRasterFileFormats);
  2772. end.