JPG 彩色转黑白灰度(100分)

  • 主题发起人 主题发起人 tuti
  • 开始时间 开始时间
T

tuti

Unregistered / Unconfirmed
GUEST, unregistred user!
在下有一图象处理问题,需要把彩色的jpg图片,通过程序控制转化成黑白灰度表示,
以便于打印输出。如建议装个黑白打印机或者拿Acdsee转化一下就不必要了-_-!。
小可对图象处理方面不熟悉,请大虾们赐教,还请告之进行图象编程
处理,都有些什么网络资源或者书籍可以参考。
另一问题,在大富翁下载了一个 EnvisionImage 控件,安装了其中MyEnvision.dpk,
只生成了ImageScrollBox一个控件,也无法调通DEMO样例。
提示 [Fatal Error] DemoForm.pas(9): File not found: 'DsgnIntf.dcu'
不知道是什么原因 -_-!
 
好几种算法
最简单的一种是
r:=(r+g+b)/3;
g:=(r+g+b)/3;
b:=(r+g+b)/3;

 
有现成的算法fastlib
 
Var BitMap:TBitmap;
begin
TJPEGImage(Image1.Picture.Graphic).Grayscale:=True;
Image1.Picture.SaveToFile('C:/aa.JPG');
BitMap:=TBitmap.Create;
try
With BitMap do
begin
Width:=Image1.Picture.Width;
Height:=Image1.Picture.Height;
Canvas.Draw(0,0,Image1.Picture.Graphic);
end;
TJPEGImage(Image1.Picture.Graphic).Assign(BitMap);
TJPEGImage(Image1.Picture.Graphic).CompressionQuality:=10;
TJPEGImage(Image1.Picture.Graphic).Compress;
TJPEGImage(Image1.Picture.Graphic).SaveToFile('C:/a.JPG');
finally
BitMap.Free;
end;
 
aizb的方法可行,也可以用windows的剪切板实现。
 
r*0.3+g*0.59+b*0.11
 
把颜色值转换为灰度值


CoDelphi.com

 摘 要:如何把颜色值转换为灰度值?
 关键字:颜色 灰色 灰度
 类 别:图形
--------------------------------------------------------------------------------



逐个像素转换。

function RgbToGray(Source: TColor) : TColor;
var Target: Byte;
begin
Target := Round((0.30 * GetRValue(Source)) +
(0.59 * GetGValue(Source)) +
(0.11 * GetBValue(Source)));
Result := RGB(Target, Target, Target);
end;


如何把图片转换为灰度图片
 关键字:颜色 灰度 转换
 类 别:图形
--------------------------------------------------------------------------------


procedure TForm1.Button1Click(Sender: TObject);
var
lo:tbitmap;
i,j:integer;
kl:longint;
rr,gg,bb:byte;
res:byte;
begin
lo:=tbitmap.create;
lo.Width:=image1.Width;
lo.height:=image1.height;
ProgressBar1.Max:=image1.Width+1;
for i:=0 to image1.Width+1 do
begin
for j:=0 to image1.height+1 do
begin
kl:=ColorToRGB(image1.Canvas.Pixels[i,j]);
rr:=byte(kl);
gg:=byte(kl shr 8);
bb:=byte(kl shr 8);
res:=(rr+gg+bb) div 3;
lo.Canvas.Pixels[i,j]:=rgb(res,res,res);
end;
ProgressBar1.Position:=i;
end;//for do
image1.Canvas.Draw(0,0,lo);
lo.free;
end;





怎样将一幅图片转化成灰度图? (100分)
分类:图形图象 windy (1999-8-17 18:04:20)
如何将一幅图片转化成灰度图,我用的方法是提取图片的每一个象素然后改变
他的值,但是非常的慢,希望寻求一种高效率的方法,并具体一点,多谢!


Another_eYes (1999-8-17 19:07:04)
改变palette的颜色值.
然后将图片格式转成pf8bit.


DancingAgain (1999-8-17 19:22:00)
将一幅图片转化成灰度图,具体来说应该分为以下几步:
1.提取图片的每一个象素的值,然后建立三个数据表,1->G 2->R 3->B.
2.为每一种颜色值建立一附图.
方法如下:
若源图一点为 (R100,G200,B210),这相应的三附图的点颜色为1_(100,100,100), 2_(200,200,200),3_(210,210,210).
3. 你说希望寻求一种高效率的方法,但我个人认为什么方法可能都需要提取图片的每一个象素,你也不可能只是要将一幅图片转化成灰度图(否则这可用专门的software),往后来还是要知道每一个象素的数据.我做过这个程序,速度还可以(在386上).


上面是基于图片在屏幕上的方法,如果你的图片是文件就简单多了,在读文件时只分别读RGB,再写屏就可以了.




Another_eYes (1999-8-17 19:57:10)
改palette最快, 灰度只有256阶, 用256色位图, 改掉palette就改变全图了.(只要循环256次).


onedolph (1999-8-17 21:05:37)
你看这样行不行,速度比不上Another_eYes的方法快.但可以满足我的要求.



type
TFColor = record
b,g,r:Byte
end;

PFColor =^TFColor;

procedure Gray(srcBmp,DstBmp:TBitMap);
var
x,y: Integer;
Gr: Byte;
incRow,Gap: integer;
DstTmp,SrcTmp: PFColor;
SrcBmInfo,DstBmInfo: TBitmapInfo;
SrcBmHeader,DstBmHeader: TBitmapInfoHeader;
width,height,Size: integer;
SrcBits,DstBits: pointer;
mDC: Integer;
begin
Width:=SrcBmp.Width;
Height:=SrcBmp.Height;
Size:=((Width*3)+(Width mod 4))*Height;
incRow:=((Width*3)+(Width mod 4));
Gap:=Width mod 4;
DstBmp.Assign(SrcBmp);//这句可要可不要,看情况定
getMem(srcBits,size);
getMem(DstBits,size);
with SrcbmHeader do begin
biSize:=SizeOf(SrcbmHeader);
biWidth:=Width;
biHeight:=-Height;
biPlanes:=1;
biBitCount:=24;
biCompression:=BI_RGB;
end;
SrcbmInfo.bmiHeader:=srcbmHeader;

with DstbmHeader do begin
biSize:=SizeOf(DstbmHeader);
biWidth:=Width;
biHeight:=-Height;
biPlanes:=1;
biBitCount:=24;
biCompression:=BI_RGB;
end;
DstbmInfo.bmiHeader:=DstbmHeader;

try
mDC:=GetDC(0);
GetDIBits(mDC,srcBmp.Handle,0,Height,srcBits,srcbmInfo,DIB_RGB_COLORS);

DstTmp:=DstBits;
for y:=0 to Height-1 do begin
for x:=0 to Width-1 do begin
SrcTmp:=pointer(integer(SrcBits)+(y*IncRow+x*3));
Gr := HiByte(SrcTmp^.r * 77 + SrcTmp^.g * 151 + SrcTmp^.b * 28);
DstTmp^.r:=Gr;
DstTmp^.g:=Gr;
DstTmp^.b:=Gr;
Inc(DstTmp);
end;
DstTmp:=Pointer(Integer(DstTmp)+Gap);
end;
SetDIBits(mDC,DstBmp.Handle,0,Height,DstBits,DstbmInfo,DIB_RGB_COLORS);
ReleaseDC(0,mDC);
finally
freemem(SrcBits);
freemem(DstBits);
end;
end;

其中GetDIBBits和SetDIBBits函数可以看API帮助.这个方法与显存有关,
如果你的显存不够大,大图象就处理不,600X600的图象需要
600x600x3=1080000Bytes的显存.


Another_eYes (1999-8-17 21:49:21)
DIB不是device independant bitmap吗?
和设备无关的, 在内存中.
DDB才和显存有关.
不用palette的话:
onedolphi的程序稍微修改了一下:
procedure Gray(bmp: TBitmap);
var
p: PByteArray;
w: Integer;
i, j: Integer;
begin
bmp.pixelformat := pf24bit;
for i := 0 to bmp.height - 1 do
begin
p := bmp.scanline;
j := 0;
while j < (bmp.width-1) * 3 do
begin
w :=(p[j] * 28 + p[j+1] * 151 + p[j+2]*77);
w := w shr 8;
p[j] := byte(w);
p[j+1] := byte(w);
p[j+2] := byte(w);
inc(j, 3)
end;
end;
end;

速度也够快了(800*600 < 0.5s).
 
DsgnIntf.dcu缺省是没有的,

你可以的delphi5目录中查找dsgnintf.pas(当然是用windows的
查找功能了), 找到后将此文件拷到delphi5/lib目录就行了
如果是delphi6, 可以查找C:/Program Files/Borland/Delphi6/Source/ToolsAPI/DesignIntf.pas
将此文件改名为dsgnintf.pas, 并打开它将其单元名也改为Dsgnintf再拷到delphi6/lib就行了

——————————————————————————————
调用方法:
EffectGreyScale(Image1.Picture.Bitmap,TempBmp,nil);
Image1.Picture.Bitmap.Assign(TempBMP);
// -----------------------------------------------------------------------------
// Greyscale Bitmap
// Parameter:
// SrcBitmap : Bitmap to be processed
// DestBitmap : Result
// EffectCallBack : CallBack for user interface
// -----------------------------------------------------------------------------
procedure EffectGreyScale(SrcBitmap,DestBitmap:TBitmap;const EffectCallBack:TEffectCallBack);stdcall;
var Row,Col :Integer;
SrcRow,DestRow :pRGBArray;
begin
SetBitmapsEql(SrcBitmap,DestBitmap);
for Row:=0 to DestBitmap.Height-1 do
begin

if Assigned(EffectCallBack) then EffectCallBack(0,100,Round((Row/SrcBitmap.Height)*100));

SrcRow:=SrcBitmap.ScanLine[Row];
DestRow:=DestBitmap.ScanLine[Row];
for Col:=0 to DestBitmap.Width-1 do WITH DestRow[Col] do
begin
rgbtBlue:=RgbLightness(SrcRow[Col]);
rgbtGreen:=RgbLightness(SrcRow[Col]);
rgbtRed:=RgbLightness(SrcRow[Col]);
end;
end;
end;

// -----------------------------------------------------------------------------
// RGBLightness
// -----------------------------------------------------------------------------
function RGBLightness(const RGB: TRGBTriple): INTEGER;
var
min: INTEGER;
max: INTEGER;
begin
with RGB DO
MinMaxInt3(rgbtRed, rgbtGreen, rgbtBlue, min, max);
RESULT := (min + max) div 2
end ;

至于JPG如何转成biptmap, 就不用我讲了吧, 你可以在本论坛搜索的
 
还有更简单的代码:
procedure TFormMain.mnuColorToGrayClick(Sender: TObject);
var
bmp : Tbitmap;
X, Y: Integer;
I, nGray ,nTemp : Byte;
ColorTable: array[0..255] of TRGBColor;
pRGB: PRGBColor;
begin
bmp := TBitmap.Create;
bmp.Assign(image1.Picture.Graphic);

for Y := 0 to Bmp.Height - 1 do
begin
pRGB := Bmp.ScanLine[Y];
for X := 0 to Bmp.Width - 1 do
begin
// nGray :=(pRGB.R+pRGB.G+pRGB.B) div 3 ; // 变灰度算法1
nGray := Round((0.30 * pRGB.R) + (0.59 * pRGB.G) + (0.11 * pRGB.B)); // 变灰度算法2
pRGB.R := nGray;
pRGB.G := nGray;
pRGB.B := nGray;

Inc(pRGB);
end;
end;

image1.Picture.Graphic.Assign(bmp);
image1.Refresh;

bmp.Free; //释放空间,其实是全局变量更快
end;
 
还有速度慢的代码:
procedure TfrmColor.Button1Click(Sender: TObject);
var
i,j,k : integer;
Source : DWORD;
begin
for i := 0 to min(328 ,Image1.Picture.Width) do
for j :=0 to min(328 ,Image1.Picture.Height) do
begin
// k := GetRValue(ColorToRGB(Image1.Canvas.Pixels[i,j]))+GetGValue(ColorToRGB(Image1.Canvas.Pixels[i,j]))+GetBValue(ColorToRGB(Image1.Canvas.Pixels[i,j]));
// k := k div 3;
Source := ColorToRGB(Image1.Canvas.Pixels[i,j]);
k := Round((0.30 * GetRValue(Source)) +
(0.59 * GetGValue(Source)) +
(0.11 * GetBValue(Source)));
Canvas.Pixels[i+320,j] := RGB(k,k,k);
end;
end;
 
D6下有这个例子
 
多人接受答案了。
 
后退
顶部