导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
tuao (tuao)
★☆☆☆☆
-
盒子活跃会员
2022/6/27 20:08:37
标题:
问:jpg转Tbitmap后,竖图变横图?
浏览:1605
加入我的收藏
楼主:
jpg转Tbitmap后,竖图变横图? 本来是3000*4000的,转换后变4000*3000了。 pic := Tpicture.Create; bit := TBitmap.Create; bit.PixelFormat:=pf24bit; try text := shuiyintext; pic.LoadFromFile(newname + ExtractFileExt(OpenPic.FileName)); bit.Assign(pic.Graphic);//这步之后竖图就变成了横图 // bit.SetSize(pic.Width,pic.Height);使用canvas后也一样 // bit.Canvas.Draw(0,0,pic.Graphic); drawshuiying(Bit, text); pic.Graphic.Assign(bit); pic.SaveToFile(newname + ExtractFileExt(OpenPic.FileName)); image1.Picture.Assign(pic);
----------------------------------------------
tuao
作者:
tuao (tuao)
★☆☆☆☆
-
盒子活跃会员
2022/6/27 20:11:24
1楼:
顺便再请教一个问题: 上例中,执行到bit.assign(pic.graphic)时,需要约0.5到1秒的时间,有没有可以提高速度的方法?
----------------------------------------------
tuao
作者:
tuao (tuao)
★☆☆☆☆
-
盒子活跃会员
2022/6/27 21:11:56
2楼:
错了,不是bit.Assign(pic.Graphic)旋转了图像,而是pic.LoadFromFile后就自动旋转了图像。在delphi的image组件的属性编辑器中调入也是会自动旋转,而如果本身就是横图则不旋转。 不知有什么方法不让它自动旋转?
----------------------------------------------
tuao
作者:
2022/6/27 22:37:15
3楼:
不可能旋转。程序又不知道你的图是横的还是竖的,它还帮你旋转? 另外,你怎么知道 LoadFromFile 以后发生了旋转?如何知道的?
----------------------------------------------
-
作者:
2022/6/27 23:38:54
4楼:
都不知道,你想干嘛? 3D随便旋转,Skia4D示例里面不错的。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2022/6/28 8:01:26
5楼:
TJPEGImage *jpg; jpg = new TJPEGImage; if (!jpg) return 0; Graphics::TBitmap *bmp; bmp = new Graphics::TBitmap; if (!bmp) { delete jpg; return 0; } jpg->LoadFromFile(AnsiString(filename)); bmp->Assign(jpg); if (bmp->PixelFormat < pf24bit) bmp->PixelFormat = pf24bit; AnsiString file; file = ChangeFileExt(AnsiString(filename), ".BMP"); bmp->SaveToFile(file); delete jpg; delete bmp;
----------------------------------------------
-
作者:
2022/6/28 8:02:06
6楼:
这么大的图片文件,读取就是慢。
----------------------------------------------
-
作者:
2022/6/28 9:10:20
8楼:
JPG 本身带有一个讯号, 代表图像以 0 90 180 270 度才是正确显示. BMP 不知道有没有这样的讯号 部分图像颢示软有选项决定是否执行这讯号的意思 一般人不会注意到 而转换程序上也应判定这讯号作相应处理 这是附加方式的讯号, 可以没有的. 但存在就必须处理.
----------------------------------------------
-
作者:
2022/6/28 11:26:53
9楼:
JPG有EXIT信息的,比如照相机和手机横着拍摄的,EXIT信息里面会记录照片的角度,比如90,270等。很多看图软件会根据这个修正把照片旋转到显示器的角度。 Delphi的图片加载仅仅是加载数据,并不负责旋转修正角度。 所以你看到的是旋转了的。 如果你要做看图软件,最好还是要加一道工序,根据EXIT修正角度。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2022/6/28 13:35:49
10楼:
开卷有益,看论坛可以学知识。以前还真不知道 JPG 有 EIXT。 总结一下: 1. Delphi 并没有旋转图片; 2. 楼主认为 Delphi 旋转了图片,是因为楼主用其它工具打开图片显示的时候,图片被工具旋转了,楼主以为那个旋转后的图片才是正常的,所以认为 Delphi 把图片旋转了; 3. 如果需要正确显示图片,需要额外处理 EXIT 的信息。
----------------------------------------------
-
作者:
2022/6/28 14:54:49
11楼:
EXIT 是附加的讯号, 查了一下原来各种格式的图像甚至影像都可以加载. 当然也可以不加载. 部分格式转换软件会忽略它当作不存在.
----------------------------------------------
-
作者:
2022/6/28 20:11:10
0楼:
为什么要用 TPicture 而不用TJpegimage?
----------------------------------------------
delphi 是兴趣,和工作无关,即使它倒闭。又不靠它 delphi 吃饭,怕甚?
作者:
2022/6/28 21:49:40
12楼:
呃那个是:EXIF(Exchangeable image file)比较常见。 还有IPTC(International Press Telecommunications Council)之类。 一般就称为元数据。 时间/地点/机型/光圈/快门……各种非图片本身的附加信息……当然也包括正确的图片方向。 PS:所以网上发布照片,小心元数据泄漏隐私。
----------------------------------------------
Bye bye DDRFAN...
作者:
2022/6/29 3:42:38
13楼:
CCR-Exif控件: https://github.com/katalym/ccr-exif
----------------------------------------------
-
作者:
2022/6/29 16:07:18
14楼:
楼主可以发你那张图片来给大家测试吗? 如果可以不要发图,发压缩包。
----------------------------------------------
delphi 是兴趣,和工作无关,即使它倒闭。又不靠它 delphi 吃饭,怕甚?
作者:
2022/6/29 18:54:10
15楼:
使用TWicImage读取: uses Windows, ActiveX, Graphics, Classes, Types; var FWidth, FHeight, FOrientation: Cardinal; FBitmap: Graphics.TBitmap; FImagingFactory: IWICImagingFactory; FWicBitmap: IWICBitmap; // Value := TStream.LoadFrom(jpgFile); procedure TNativeWIC.SetStream(Value: TStream); var hr: integer; Adapter: IStream; WicBmpDecoder : IWICBitmapDecoder; frameDecode : IWICBitmapFrameDecode; mdReader : IWICMetadataQueryReader; prop: PROPVARIANT; begin FWicBitmap := nil; // FWicBitmap: IWICBitmap; FOrientation := 0; // 旋转角度: 0 - 0,3 - 180,6 - 90, 8 - 270 FWidth := 0; // 图形宽度 FHeight := 0; // 图像高度 Value.Position := 0; Adapter := TStreamAdapter.Create(Value); hr := FImagingFactory.CreateDecoderFromStream(Adapter, GUID_NULL, WICDecodeMetadataCacheOnDemand, WicBmpDecoder); // 通过TStream创建Decoder if hr = S_OK then hr := WicBmpDecoder.GetFrame(0, frameDecode); if hr = S_OK then begin // 读取EXIF数据里的旋转参数 if frameDecode.GetMetadataQueryReader(mdReader) = S_OK then begin ZeroMemory(@prop, sizeof(prop)); if mdReader.GetMetaDataByName('/app1/ifd/{uint=274}', prop) = S_OK then FOrientation := prop.iVal; end; // 创建IWicBitmap对象 hr := FImagingFactory.CreateBitmapFromSource(frameDecode, WICBitmapCacheOnLoad, FWicBitmap); end; if hr = S_OK then // 原始图片尺寸 FWicBitmap.GetSize(FWidth, FHeight); end;
----------------------------------------------
-
作者:
2022/6/29 18:59:40
16楼:
读取不同的属性: https://docs.microsoft.com/en-us/windows/win32/wic/-wic-native-image-format-metadata-queries
----------------------------------------------
-
作者:
2022/6/29 19:07:42
17楼:
附上测试图片,txt文件是 ExifTool 输出的信息。 旋转属性的名称是: Orientation
----------------------------------------------
-
作者:
tuao (tuao)
★☆☆☆☆
-
盒子活跃会员
2022/6/29 21:24:49
18楼:
感谢楼上诸位热心回复。 我的需求很简单,就是打开一张图片(可能是jpg,bmp,png格式),然后转换为bitmap,在上面(左上或左下或右上或右下)画上特定的水印文字,再保存为另一个文件。 发生坚图变横图的那张图片,确实是用手机坚着拍的。在资源管理器里大图预览时是坚向的,我就认为原图就是坚向的。 通过上面各位的回复,确实长知识了,看来,手机竖着拍的,也只是横拍的旋转90度而已。
----------------------------------------------
tuao
作者:
tuao (tuao)
★☆☆☆☆
-
盒子活跃会员
2022/7/11 19:42:49
19楼:
最后使用GDI+完成了,而且没有使用类似bit.assign(pic.graphic)的复制操作,速度上快很多。
----------------------------------------------
tuao
作者:
szlbz (秋风)
★☆☆☆☆
-
盒子活跃会员
2022/7/12 8:56:18
20楼:
问题解决后最好公布解决方法供大家学习,谢谢。
----------------------------------------------
-
作者:
tuao (tuao)
★☆☆☆☆
-
盒子活跃会员
2022/7/12 21:17:47
21楼:
代码写得不好,不要辣了大神的眼睛。 function getrotate(image: TGPImage): UINT; var buf: PPropertyItem; size: uint; begin size := image.GetPropertyItemSize(PropertyTagOrientation); GetMem(buf, size); image.GetPropertyItem(PropertyTagOrientation, size, buf); result := PUINT(buf^.value)^; FreeMem(buf); end; function TmainForm.drawshuiying(img: TGPImage; s: string; rotate: uint): Boolean; var Graphics: TGPGraphics; rectf: TGPrectF; sb: TGPSolidBrush; fontFamily: TGPFontFamily; font: TGPFont; strFormat: TGPStringFormat; r, g, b: byte; procedure Tcolor2RGB(color: TColor; var r, g, b: byte); begin r := color and $FF; g := (color and $FF00) shr 8; b := (color and $FF0000) shr 16; end; begin result := false; strFormat := TGPStringFormat.Create(); case setform.posRadio.ItemIndex of 0: //左上角 begin strFormat.SetAlignment(StringAlignment.StringAlignmentNear); strFormat.SetLineAlignment(StringAlignment.StringAlignmentNear); end; 1: //右上角 begin strFormat.SetAlignment(StringAlignment.StringAlignmentfar); strFormat.SetLineAlignment(StringAlignment.StringAlignmentNear); end; 2: //左下角 begin strFormat.SetAlignment(StringAlignment.StringAlignmentNear); strFormat.SetLineAlignment(StringAlignment.StringAlignmentFar); end; 3: //右下角 begin strFormat.SetAlignment(StringAlignment.StringAlignmentFar); strFormat.SetLineAlignment(StringAlignment.StringAlignmentFar); end; 4: //上居中 begin strFormat.SetAlignment(StringAlignment.StringAlignmentCenter); strFormat.SetLineAlignment(StringAlignment.StringAlignmentNear); end; 5: //下居中 begin strFormat.SetAlignment(StringAlignment.StringAlignmentCenter); strFormat.SetLineAlignment(StringAlignment.StringAlignmentFar); end; end; case rotate of 3: img.RotateFlip(TRotateFlipType.Rotate180FlipNone); 6: img.RotateFlip(TRotateFlipType.Rotate90FlipNone); 8: img.RotateFlip(TRotateFlipType.Rotate270FlipNone); end; rectf := makerect(5.0, 5.0, img.GetWidth - 5.0, img.GetHeight - 5.0); Graphics := TGPGraphics.Create(img); Tcolor2RGB(setform.fontColor.Selected, r, g, b); sb := TGPSolidBrush.Create(makeColor(r, g, b)); fontFamily := TGPFontFamily.Create(setform.fontname.Text); font := TGPFont.Create(fontFamily, setform.fontsize.Value, FontStyleRegular, UnitPixel); {参数 3 参考: 文本样式类型表; 参数 4 参考: 坐标单位类型表} Graphics.DrawString(s, -1, font, rectf, strFormat, sb); case rotate of 3: img.RotateFlip(TRotateFlipType.Rotate180FlipNone); 6: img.RotateFlip(TRotateFlipType.Rotate270FlipNone); 8: img.RotateFlip(TRotateFlipType.Rotate90FlipNone); end; result := True; sb.free; Graphics.free; font.free; fontFamily.free; end; procedure TmainForm.renameAndshuiying(picfile :string); var newname, text: string; img: TGPImage; jpegguid: TGUID; rotate: UINT; paras: TEncoderParameters; Quality: integer; begin text := shuiyintext; img := TGPImage.Create(picfile); rotate := getrotate(img); //获取旋转数据 if drawshuiying(img, text, rotate) then begin //setrotate(img,rotate); GetEncoderClsid('image/jpeg', jpegguid); paras.Count := 1; paras.Parameter[0].Guid := EncoderQuality; paras.Parameter[0].Type_ := EncoderParameterValueTypeLong; paras.Parameter[0].NumberOfValues := 1; Quality := 80; paras.Parameter[0].Value := @Quality; img.Save(newname + ExtractFileExt(picfile), jpegguid, @paras); img.free; ShowMessage('改名成功。添加水印成功。' + #10#13 + '原文件名:' + picfile + #10#13 + '新文件名:' + newname + ExtractFileExt(picfile), [tfUseHiconMain]); end;
----------------------------------------------
tuao