--- oup/rewrite/Global/OniImgClass.pas 2007/02/20 20:43:29 101 +++ oup/current/Global/OniImgClass.pas 2007/05/19 17:54:34 181 @@ -2,11 +2,13 @@ unit OniImgClass; interface -uses Math, Dialogs, Types, SysUtils, Classes, Data, ConnectionManager, TypeDefs; +uses Math, Dialogs, Types, SysUtils, Classes, Data, ConnectionManager, TypeDefs, + Imaging, ImagingTypes; type TImgDataType = set of (DT_OniReverted, DT_Oni, DT_Decoded32); + type TOniImage = class private @@ -17,12 +19,14 @@ type FDepth: Byte; FStoreType: Byte; + FImage: TImageData; + function ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData; procedure RevertImage; - procedure DecodeImage; procedure DecompressImage; protected public + property Image: TImageData Read FImage Write FImage; property Loaded: Boolean Read FLoaded Write FLoaded; property DataType: TImgDataType Read FDataType Write FDataType; property Width: Word Read FWidth Write FWidth; @@ -36,15 +40,21 @@ type function LoadFromPSpc(ConnectionID, FileID: Integer): Boolean; function LoadFromTXMP(ConnectionID, FileID: Integer): Boolean; function LoadFromTXMB(ConnectionID, FileID: Integer): Boolean; + function GetImgSize(w,h, storetype: Integer): Integer; function GetImageDataSize(fading: Boolean): Integer; - function GetAsData: TByteData; - function GetAs32bit: TByteData; - procedure GetAsBMP(var Target: TByteData); overload; + procedure DecodeImageTo32bit; + + procedure GetAsData(var Target: TStream); overload; + procedure GetAsData(var Target: TByteData); overload; + procedure GetAs32bit(var Target: TStream); overload; + procedure GetAs32bit(var Target: TByteData); overload; procedure GetAsBMP(var Target: TStream); overload; + procedure GetAsBMP(var Target: TByteData); overload; function LoadFromBMP(filename: String): Boolean; function WriteToBMP(filename: String): Boolean; - function GetMipMappedImage(var faded: TByteData): Boolean; + function GetMipMappedImage(var Target: TStream): Boolean; overload; + function GetMipMappedImage(var Target: TByteData): Boolean; overload; published end; @@ -52,8 +62,7 @@ type implementation //uses Functions; - - +uses Img_DDSTypes; constructor TOniImage.Create; @@ -65,6 +74,8 @@ begin Self.FHeight := 0; Self.FDepth := 0; Self.FStoreType := 0; + + InitImage(FImage); end; @@ -128,7 +139,7 @@ end; -procedure TOniImage.DecodeImage; +procedure TOniImage.DecodeImageTo32bit; var x, y: Integer; tempd: TByteData; @@ -137,7 +148,7 @@ begin begin SetLength(tempd, Self.FWidth * Self.FHeight * 4); case Self.FStoreType of - 0: + 0: // 16bit, RGB444, A4? begin for y := 0 to Self.FHeight - 1 do begin @@ -156,7 +167,7 @@ begin end; end; end; - 1, 2: + 1, 2: // 16bit, RGB555, A1? begin for y := 0 to Self.FHeight - 1 do begin @@ -175,7 +186,9 @@ begin end; end; end; - 9: + 8: // 32bit, RGB888, A8? + begin end; + 9: // Compressed, RGB565 begin DecompressImage; end; @@ -306,7 +319,6 @@ end; function TOniImage.Load(ConnectionID, FileID: Integer): Boolean; var FileInfo: TFileInfo; - ext: String; begin FileInfo := ConManager.Connection[ConnectionID].GetFileInfo(fileid); if FileInfo.Extension = 'PSpc' then @@ -366,9 +378,9 @@ begin end; txmpimg := TOniImage.Create; txmpimg.LoadFromTXMP(ConnectionID, PSpc.TXMP); - txmpimg.DecodeImage; + txmpimg.DecodeImageTo32bit; // txmpimg.WriteToBMP('C:\file.bmp'); - txmpdata := txmpimg.GetAs32bit; + txmpimg.GetAs32bit(txmpdata); { ShowMessage(IntToStr(txmpimg.Width)+'x'+IntToStr(txmpimg.Height)); for i:=0 to High(txmpdata) do txmpimg.Data[i]:=txmpdata[i]; @@ -467,12 +479,16 @@ end; function TOniImage.LoadFromTXMP(ConnectionID, FileID: Integer): Boolean; var img_addr: Integer; + data: TMemoryStream; + hdr: TDDSDXTHeader; + imginfo: Integer; + x,y, i: Integer; begin Result := True; ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth); ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight); - ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType), - @Self.FStoreType); + ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType), @Self.FStoreType); + ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $88, SizeOf(imginfo), @imginfo); if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $9C, SizeOf(img_addr), @img_addr) else @@ -480,30 +496,69 @@ begin case Self.FStoreType of 0, 1, 2: - begin - SetLength(Self.FData, Self.FWidth * Self.FHeight * 2); Self.FDepth := 16; - end; 8: - begin - SetLength(Self.FData, Self.FWidth * Self.FHeight * 4); Self.FDepth := 32; - end; 9: - begin - SetLength(Self.FData, Self.FWidth * Self.FHeight div 2); Self.FDepth := 16; - end; else Result := False; Exit; end; if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then + ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, TStream(data)) + else + ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, TStream(data)); + + with hdr do + begin + FOURCC := 'DDS '; + with SURFACEDESC2 do + begin + Size := 124; + Flags := DDSD_CAPS or DDSD_PIXELFORMAT or DDSD_WIDTH or DDSD_HEIGHT; + if FStoreType = 9 then + Flags := Flags or DDSD_LINEARSIZE + else + Flags := Flags or DDSD_PITCH; + if (imginfo and $01) > 0 then + Flags := Flags or DDSD_MIPMAPCOUNT; + Height := FHeight; + Width := FWidth; + if FStoreType = 9 then + PitchOrLinearSize := FWidth * FHeight div 2 + else + PitchOrLinearSize := FWidth * FDepth div 2; + Depth := 0; + MipMapCount := 1; + x := FWidth; + y := FHeight; + while (x > 1) and (y > 1) do + begin + x := x div 2; + y := y div 2; + Inc(MipMapCount); + end; + for i := 1 to 11 do + Reserved[i] := 0; + with PIXELFORMAT do + begin + Size := 32; + if FStoreType = 9 then + Flags := DDPF_FOURCC + else + Flags := DDPF_RGB; + end; + end; + end; + LoadImageFromStream(data, FImage); +{ + if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, FData) else ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, FData); - +} Self.FDataType := [DT_OniReverted, DT_Oni]; end; @@ -531,7 +586,7 @@ begin link := link div 256; images_decoded[i] := TOniImage.Create; images_decoded[i].LoadFromTXMP(ConnectionID, link); - images_decoded[i].DecodeImage; + images_decoded[i].DecodeImageTo32bit; images_decoded[i].RevertImage; end; SetLength(Self.FData, Self.FWidth * Self.FHeight * 4); @@ -578,35 +633,36 @@ end; +function TOniImage.GetImgSize(w,h, storetype: Integer): Integer; +begin + case storetype of + 0, 1, 2: + Result := w*h*2; + 8: + Result := w*h*4; + 9: + Result := Max(1, w div 4) * Max(1, h div 4) * 8; + else + Result := -1; + end; +end; + function TOniImage.GetImageDataSize(fading: Boolean): Integer; var size: Integer; x, y: Word; - bpp: Byte; begin - case Self.FStoreType of - 9: - bpp := 8; - 0, 1, 2: - bpp := 16; - 8: - bpp := 32; - else - Result := 0; - Exit; - end; - x := Self.FWidth; y := Self.FHeight; - size := x * y * bpp div 8; + size := GetImgSize(x, y, FStoreType); if fading then begin repeat - x := x div 2; - y := y div 2; - size := size + x * y * bpp div 8; - until (x = 1) or (y = 1); + x := Max(x div 2, 1); + y := Max(y div 2, 1); + size := size + GetImgSize(x, y, FStoreType); + until (x = 1) and (y = 1); end; Result := size; end; @@ -614,9 +670,8 @@ end; -function TOniImage.GetAsData: TByteData; +procedure TOniImage.GetAsData(var Target: TStream); var - i: Integer; revert: Boolean; begin // if not (DT_Decoded32 in Self.FDataType) then @@ -628,28 +683,46 @@ begin end else revert := False; - SetLength(Result, Length(Self.FData)); - for i := 0 to High(Result) do - Result[i] := Self.FData[i]; + if not Assigned(Target) then + Target := TMemoryStream.Create; + Target.Write(FData[0], Length(FData)); + Target.Seek(0, soFromBeginning); if revert then Self.RevertImage; end; - - - -function TOniImage.GetAs32bit: TByteData; +procedure TOniImage.GetAsData(var Target: TByteData); var - i: Integer; + mem: TStream; begin - if not (DT_Decoded32 in Self.FDataType) then - Self.DecodeImage; - SetLength(Result, Length(Self.FData)); - for i := 0 to High(Result) do - Result[i] := Self.FData[i]; + mem := TMemoryStream.Create; + GetAsData(mem); + SetLength(Target, mem.Size); + mem.Read(Target[0], mem.Size); + mem.Free; end; +procedure TOniImage.GetAs32bit(var Target: TStream); +begin + if not (DT_Decoded32 in Self.FDataType) then + Self.DecodeImageTo32bit; + if not Assigned(Target) then + Target := TMemoryStream.Create; + Target.Write(FData[0], Length(FData)); + Target.Seek(0, soFromBeginning); +end; + +procedure TOniImage.GetAs32bit(var Target: TByteData); +var + mem: TStream; +begin + mem := TMemoryStream.Create; + GetAs32bit(mem); + SetLength(Target, mem.Size); + mem.Read(Target[0], mem.Size); + mem.Free; +end; procedure TOniImage.GetAsBMP(var Target: TByteData); @@ -662,7 +735,7 @@ var i, x, y: Integer; begin if not (DT_Decoded32 in Self.FDataType) then - Self.DecodeImage; + Self.DecodeImageTo32bit; SetLength(Target, Self.FWidth * Self.FHeight * 3 + 54); for y := 0 to Self.FHeight - 1 do @@ -785,8 +858,7 @@ end; - -function TOniImage.GetMipMappedImage(var faded: TByteData): Boolean; +function TOniImage.GetMipMappedImage(var Target: TByteData): Boolean; var i: Integer; x, y: Word; @@ -809,20 +881,20 @@ begin x := Self.FWidth; y := Self.FHeight; - SetLength(faded, x * y * Self.FDepth div 8); + SetLength(Target, x * y * Self.FDepth div 8); SetLength(fadelvldata, x * y * Self.FDepth div 8); - for i := 0 to Length(faded) - 1 do + for i := 0 to Length(Target) - 1 do begin - faded[i] := Self.FData[i]; + Target[i] := Self.FData[i]; fadelvldata[i] := Self.FData[i]; end; repeat fadelvldata := Self.ResizeImage(x, y, fadelvldata); x := x div 2; y := y div 2; - SetLength(faded, Length(faded) + x * y * Self.FDepth div 8); + SetLength(Target, Length(Target) + x * y * Self.FDepth div 8); for i := 0 to Length(fadelvldata) - 1 do - faded[Length(faded) - x * y * Self.FDepth div 8 + i] := fadelvldata[i]; + Target[Length(Target) - x * y * Self.FDepth div 8 + i] := fadelvldata[i]; until (x = 1) or (y = 1) or ((x mod 2) = 1) or ((y mod 2) = 1); if (x > 1) and (y > 1) then Exit; @@ -833,4 +905,18 @@ begin end; +function TOniImage.GetMipMappedImage(var Target: TStream): Boolean; +var + data: TByteData; + streampos: Integer; +begin + Result := GetMipMappedImage(data); + if not Assigned(Target) then + Target := TMemoryStream.Create; + streampos := Target.Position; + Target.Write(data[0], Length(data)); + Target.Seek(streampos, soFromBeginning); +end; + + end. \ No newline at end of file