DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: loong219
今日帖子: 23
在线用户: 7
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 tuao (tuao) ★☆☆☆☆ -
盒子活跃会员
2022/6/27 20:08:37
标题:
问:jpg转Tbitmap后,竖图变横图? 浏览:678
加入我的收藏
楼主: 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
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/6/27 22:37:15
3楼: 不可能旋转。程序又不知道你的图是横的还是竖的,它还帮你旋转?

另外,你怎么知道 LoadFromFile 以后发生了旋转?如何知道的?
----------------------------------------------
-
作者:
男 letianwuji (大器晚成) ▲▲▲▲△ -
注册会员
2022/6/27 23:38:54
4楼: 都不知道,你想干嘛?
3D随便旋转,Skia4D示例里面不错的。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
男 hz_2009 (盒子) ▲▲▲▲▲ -
注册会员
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;
----------------------------------------------
-
作者:
男 hz_2009 (盒子) ▲▲▲▲▲ -
注册会员
2022/6/28 8:02:06
6楼: 这么大的图片文件,读取就是慢。
----------------------------------------------
-
作者:
男 dbyoung (dbyoung) ★☆☆☆☆ -
普通会员
2022/6/28 8:34:26
7楼: https://github.com/dbyoung720/ImageGray.git

4096*4096 加载耗时180毫秒。我的机器测试结果。
----------------------------------------------
武汉天气不好
作者:
男 pp0123 (pp0123) ★☆☆☆☆ -
普通会员
2022/6/28 9:10:20
8楼: JPG 本身带有一个讯号, 代表图像以 0 90 180 270 度才是正确显示.
BMP 不知道有没有这样的讯号
部分图像颢示软有选项决定是否执行这讯号的意思 一般人不会注意到
而转换程序上也应判定这讯号作相应处理

这是附加方式的讯号, 可以没有的. 但存在就必须处理.
----------------------------------------------
-
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
2022/6/28 11:26:53
9楼: JPG有EXIT信息的,比如照相机和手机横着拍摄的,EXIT信息里面会记录照片的角度,比如90,270等。很多看图软件会根据这个修正把照片旋转到显示器的角度。
Delphi的图片加载仅仅是加载数据,并不负责旋转修正角度。

所以你看到的是旋转了的。

如果你要做看图软件,最好还是要加一道工序,根据EXIT修正角度。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/6/28 13:35:49
10楼: 开卷有益,看论坛可以学知识。以前还真不知道 JPG 有 EIXT。

总结一下:
1. Delphi 并没有旋转图片;
2. 楼主认为 Delphi 旋转了图片,是因为楼主用其它工具打开图片显示的时候,图片被工具旋转了,楼主以为那个旋转后的图片才是正常的,所以认为 Delphi 把图片旋转了;
3. 如果需要正确显示图片,需要额外处理 EXIT 的信息。
----------------------------------------------
-
作者:
男 pp0123 (pp0123) ★☆☆☆☆ -
普通会员
2022/6/28 14:54:49
11楼: EXIT 是附加的讯号, 查了一下原来各种格式的图像甚至影像都可以加载.
当然也可以不加载.

部分格式转换软件会忽略它当作不存在.
----------------------------------------------
-
作者:
男 sail2000 (小帆工作室) ★☆☆☆☆ -
盒子活跃会员
2022/6/28 20:11:10
0楼: 为什么要用 TPicture 而不用TJpegimage?
----------------------------------------------
delphi 是兴趣,和工作无关,即使它倒闭。
又不靠它 delphi 吃饭,怕甚?
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/6/28 21:49:40
12楼: 呃那个是:EXIF(Exchangeable image file)比较常见。
还有IPTC(International Press Telecommunications Council)之类。

一般就称为元数据。
时间/地点/机型/光圈/快门……各种非图片本身的附加信息……当然也包括正确的图片方向。
PS:所以网上发布照片,小心元数据泄漏隐私。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 dawnhawk (dawnhawk) ★☆☆☆☆ -
盒子活跃会员
2022/6/29 3:42:38
13楼: CCR-Exif控件: https://github.com/katalym/ccr-exif
----------------------------------------------
-
作者:
男 sail2000 (小帆工作室) ★☆☆☆☆ -
盒子活跃会员
2022/6/29 16:07:18
14楼: 楼主可以发你那张图片来给大家测试吗?
如果可以不要发图,发压缩包。
----------------------------------------------
delphi 是兴趣,和工作无关,即使它倒闭。
又不靠它 delphi 吃饭,怕甚?
作者:
男 dawnhawk (dawnhawk) ★☆☆☆☆ -
盒子活跃会员
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;
----------------------------------------------
-
作者:
男 dawnhawk (dawnhawk) ★☆☆☆☆ -
盒子活跃会员
2022/6/29 18:59:40
16楼: 读取不同的属性:
https://docs.microsoft.com/en-us/windows/win32/wic/-wic-native-image-format-metadata-queries
----------------------------------------------
-
作者:
男 dawnhawk (dawnhawk) ★☆☆☆☆ -
盒子活跃会员
2022/6/29 19:07:42
17楼: 附上测试图片,txt文件是 ExifTool 输出的信息。
旋转属性的名称是: Orientation
此帖子包含附件:dawnhawk_202262919739.zip 大小:720.5K
----------------------------------------------
-
作者:
男 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 (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
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v2.1 版权所有 页面执行62.5毫秒 RSS