一个关于图像格式转换的问题(200)

  • 主题发起人 主题发起人 dfw1001
  • 开始时间 开始时间
D

dfw1001

Unregistered / Unconfirmed
GUEST, unregistred user!
因为初涉及到图像方面的程序,遇到个格式转换方面的问题:首先获取到1个24位的真色彩图片,然后按需求分别转换成pf1bit, pf4bit, pf8bit, pf15bit, pf16bit。我用的是先load然后设置bmp.PixelFormat ,但是发现PixelFormat 值为pf16bit和pf1bit的时候,转换出来的图片是花屏。问题1:以上问题是怎么产生的问题2:同样的程序跟图片到其他硬件环境会如何?问题3:有什么更好的转换方法,请熟悉的高手赐教了。。问题4:如何转换成2位的
 
如果是操作BMP图的话比较简单.BMP有固定的格式,带有位图的相关信息,他的颜色数据是按数组的形式存放的.可以直接把它的颜色数据取出来,然后自己再进行转换,就OK了.想怎么转换都行.
 
to onelife: 能给写下24位bmp图片转换成pf1bit, pf4bit, pf8bit, pf15bit, pf16bit的代码么谢谢了。
 
唉,这里冷清到一定程度了[:(]
 
求代码的一般没人理。
 
给你一段代码不过要用到GDI+你自已装一个就可以了procedure FSDither(Source, Dest: Tbitmap);type TRgb = packed record Blue: Byte; Green: Byte; Red: Byte; Filler: Byte; end; TIntegerArray = array[0..(MaxLongInt div 4) - 1] of Integer; TpIntegerArray = ^TIntegerArray;var RErr1: TpIntegerArray; { red errors } RErr2: TpIntegerArray; GErr1: TpIntegerArray; { green errors } GErr2: TpIntegerArray; BErr1: TpIntegerArray; { blue errors } BErr2: TpIntegerArray; function RGB2Color(RGB: TRgb): TColor; begin with RGB do begin Result := Blue shl 16 or Green shl 8 or Red; end; // with end; function BoundInteger(const Value: longint; const MinValue: longint; const MaxValue: longint): longint; begin Result := Value; if Result < MinValue then Result := MinValue; if Result > MaxValue then Result := MaxValue; end; function color2rgb(Color: TColor): TRgb; begin with Result do begin Red := Color and $FF; Green := (Color and $FF00) shr 8; Blue := (Color and $FF0000) shr 16; end; end; procedure AllocateErrors; var Size: longint; begin Size := Source.Width * SizeOf(Integer); GetMem(RErr1, Size); GetMem(RErr2, Size); GetMem(GErr1, Size); GetMem(GErr2, Size); GetMem(BErr1, Size); GetMem(BErr2, Size); FillChar(RErr1^, Size, 0); FillChar(RErr2^, Size, 0); FillChar(GErr1^, Size, 0); FillChar(GErr2^, Size, 0); FillChar(BErr1^, Size, 0); FillChar(BErr2^, Size, 0); end; procedure ReleaseErrors; var Size: longint; begin Size := Source.Width * SizeOf(Integer); FreeMem(RErr1, Size); FreeMem(RErr2, Size); FreeMem(GErr1, Size); FreeMem(GErr2, Size); FreeMem(BErr1, Size); FreeMem(BErr2, Size); end; procedure DitherScanLine(const LineNo: longint); var X: longint; RGB: TRgb; RErr: Integer; GErr: Integer; BErr: Integer; begin for X := 0 to (Source.Width - 1) do begin RGB := color2rgb(Source.Canvas.Pixels[X, LineNo]); RErr1^[X] := BoundInteger(RErr2^[X] + RGB.Red, 0, 255); RErr2^[X] := 0; GErr1^[X] := BoundInteger(GErr2^[X] + RGB.Green, 0, 255); GErr2^[X] := 0; BErr1^[X] := BoundInteger(BErr2^[X] + RGB.Blue, 0, 255); BErr2^[X] := 0; end; RGB.Red := RErr1^[0]; RGB.Green := GErr1^[0]; RGB.Blue := BErr1^[0]; Dest.Canvas.Pixels[0, LineNo] := RGB2Color(RGB); for X := 1 to (Source.Width - 2) do begin RGB.Red := RErr1^[X]; RGB.Green := GErr1^[X]; RGB.Blue := BErr1^[X]; { Using the Rgb property will perform the Color matching } Dest.Canvas.Pixels[X, LineNo] := RGB2Color(RGB); { get the actual Rgb value after Color matching to compute the error } RGB := color2rgb(Dest.Canvas.Pixels[X, LineNo]); { compute errors } RErr := RErr1^[X]; RErr := RErr - RGB.Red; GErr := GErr1^[X]; GErr := GErr - RGB.Green; BErr := BErr1^[X]; BErr := BErr - RGB.Blue; RErr1^[X + 1] := BoundInteger((RErr1^[X + 1] + ((RErr * 7)) div 16), 0, 255); RErr2^[X - 1] := BoundInteger((RErr2^[X - 1] + ((RErr * 3)) div 16), 0, 255); RErr2^[X] := BoundInteger((RErr2^[X] + ((RErr * 5)) div 16), 0, 255); RErr2^[X + 1] := BoundInteger((RErr2^[X + 1] + ((RErr * 1)) div 16), 0, 255); GErr1^[X + 1] := BoundInteger((GErr1^[X + 1] + ((GErr * 7)) div 16), 0, 255); GErr2^[X - 1] := BoundInteger((GErr2^[X - 1] + ((GErr * 3)) div 16), 0, 255); GErr2^[X] := BoundInteger((GErr2^[X] + ((GErr * 5)) div 16), 0, 255); GErr2^[X + 1] := BoundInteger((GErr2^[X + 1] + ((GErr * 1)) div 16), 0, 255); BErr1^[X + 1] := BoundInteger((BErr1^[X + 1] + ((BErr * 7)) div 16), 0, 255); BErr2^[X - 1] := BoundInteger((BErr2^[X - 1] + ((BErr * 3)) div 16), 0, 255); BErr2^[X] := BoundInteger((BErr2^[X] + ((BErr * 5)) div 16), 0, 255); BErr2^[X + 1] := BoundInteger((BErr2^[X + 1] + ((BErr * 1)) div 16), 0, 255); end; RGB.Red := RErr1^[Source.Width - 1]; RGB.Green := GErr1^[Source.Width - 1]; RGB.Blue := BErr1^[Source.Width - 1]; Dest.Canvas.Pixels[Source.Width - 1, LineNo] := RGB2Color(RGB); end;var Y: longint; HeightMinusOne: longint;begin AllocateErrors; try HeightMinusOne := Source.Height - 1; for Y := 0 to HeightMinusOne do begin DitherScanLine(Y); end; finally ReleaseErrors; end;end;procedure convertBmpPixelFormat(SourceBmp: TGPBitmap; PixelFormat: Integer);var Graphics: TGPGraphics; X, Y: Integer; Bitmap, tmpBit: Tbitmap; A, R, G, B: Integer; Color: TGPColor;begin Graphics := TGPGraphics.create(SourceBmp); Graphics.SetSmoothingMode(SmoothingModeHighQuality); Graphics.SetInterpolationMode(InterpolationModeHighQuality); Graphics.SetPixelOffsetMode(PixelOffsetModeHighQuality); Graphics.DrawImage(SourceBmp, 0, 0, SourceBmp.GetWidth, SourceBmp.GetHeight); Graphics.Free; Bitmap := Tbitmap.create; Bitmap.Width := SourceBmp.GetWidth; Bitmap.Height := SourceBmp.GetHeight; for X := 0 to Bitmap.Width - 1 do begin for Y := 0 to Bitmap.Height - 1 do begin SourceBmp.GetPixel(X, Y, Color); A := GetAlpha(Color); R := GetRed(Color); G := GetGreen(Color); B := GetBlue(Color); if A > 125 then A := 255 else A := 0; SourceBmp.SetPixel(X, Y, MakeColor(A, R, G, B)); end; end; Graphics := TGPGraphics.create(Bitmap.Canvas.Handle); if PixelFormat <> 32 then begin Graphics.SetInterpolationMode(InterpolationModeNearestNeighbor); Graphics.SetPixelOffsetMode(SmoothingModeHighQuality); end else begin Graphics.SetInterpolationMode(InterpolationModeHighQualityBilinear); Graphics.SetPixelOffsetMode(SmoothingModeHighQuality); end; Graphics.DrawImage(SourceBmp, 0, 0, Bitmap.Width, Bitmap.Height); Graphics.Free; tmpBit := Tbitmap.create; tmpBit.Width := Bitmap.Width; tmpBit.Height := Bitmap.Height; case PixelFormat of 8: tmpBit.PixelFormat := pf8bit; 4: tmpBit.PixelFormat := pf4bit; 1: tmpBit.PixelFormat := pf1bit; end; FSDither(Bitmap, tmpBit); { case PixelFormat of 8: BitMap.PixelFormat := pf8bit; 4: BitMap.PixelFormat := pf4bit; 1: BitMap.PixelFormat := pf1bit; end;} for X := 0 to tmpBit.Width - 1 do begin for Y := 0 to tmpBit.Height - 1 do begin SourceBmp.GetPixel(X, Y, Color); A := GetAlpha(Color); R := GetRValue(tmpBit.Canvas.Pixels[X, Y]); G := GetGValue(tmpBit.Canvas.Pixels[X, Y]); B := GetBValue(tmpBit.Canvas.Pixels[X, Y]); if A <> 0 then A := 255 else A := 0; SourceBmp.SetPixel(X, Y, MakeColor(A, R, G, B)); end; end; Bitmap.Free; tmpBit.Free;end;
 
to fang_csc: 非常感谢你的回复,因为初次涉及到图片方面的操作,对GDI更是不熟悉,能拜托再给写个,转换过程么。比如我现在有个bmp图片是24位的,需要转换成pf16bit的,要怎么转,我试了没有成功Gbmp :=TGPBitmap.Create('d:/abc24.bmp');convertBmpPixelFormat(Gbmp,16);
 
你调用参数错了convertBmpPixelFormat(Gbmp,8);就是把图形转为24位图形;convertBmpPixelFormat(Gbmp,4);就是把图形转为16位图形;convertBmpPixelFormat(Gbmp,1);就是把图形转为2位图形;然后再给你一个GPBIT到Bitmap的函数procedure SaveGpBitMapToBmp(SourceBmp: TGPBitmap; SaveFilename: string);var TempBmp: Tbitmap; i, j, A, R, G, B: Integer; GColor: TGPColor;begin TempBmp := Tbitmap.create; TempBmp.PixelFormat := pf24bit; TempBmp.Width := SourceBmp.GetWidth; TempBmp.Height := SourceBmp.GetHeight; for i := 0 to SourceBmp.GetWidth do for j := 0 to SourceBmp.GetHeight do begin SourceBmp.GetPixel(i, j, GColor); A := GetAlpha(GColor); R := GetRed(GColor); G := GetGreen(GColor); B := GetBlue(GColor); if A = 0 then TempBmp.Canvas.Pixels[i, j] := $FF00D2 else TempBmp.Canvas.Pixels[i, j] := RGB(R, G, B); end; TempBmp.SaveToFile(SaveFilename); TempBmp.Free;end;
 
我是这样做的,但是等这个过程结束大概要执行将近1分钟左右,图片比较大1920x1280还是不理想,首先速度上无法接受另外,我的图片数据源是DIB格式的,有没有更直接的转换方法呢,请赐教procedure TForm1.btn6Click(Sender: TObject);var Gbmp:TGPBitmap;begin gbmp:=Tgpbitmap.Create('d:/abc24.bmp'); convertBmpPixelFormat(Gbmp,1); SaveGpBitMapToBmp(Gbmp,'d:/abc_GP1.bmp'); Gbmp.Free;end;
 
多人接受答案了。
 

Similar threads

后退
顶部