获得JPEG分辨率而不解码图像

WeG*_*ars 6 delphi jpeg

我试图在不解码文件的情况下获得JPEG图像的分辨率.我从互联网上得到了几个样本但没有一个正常工作.这似乎是这种方式,因为许多 JPEG文件不是标准的,但任何图形应用程序(Irfan,PSP,Firefox等)都可以打开它们.

JPEG的标题应该是:

typedef struct _JFIFHeader
{
  BYTE SOI[2];          /* 00h  Start of Image Marker     */
  BYTE APP0[2];         /* 02h  Application Use Marker    */
  BYTE Length[2];       /* 04h  Length of APP0 Field      */
  BYTE Identifier[5];   /* 06h  "JFIF" (zero terminated) Id String */
  BYTE Version[2];      /* 07h  JFIF Format Revision      */
  BYTE Units;           /* 09h  Units used for Resolution */
  BYTE Xdensity[2];     /* 0Ah  Horizontal Resolution     */
  BYTE Ydensity[2];     /* 0Ch  Vertical Resolution       */
  BYTE XThumbnail;      /* 0Eh  Horizontal Pixel Count    */
  BYTE YThumbnail;      /* 0Fh  Vertical Pixel Count      */
} JFIFHEAD;
Run Code Online (Sandbox Code Playgroud)

但是,当我查看其中一个非标准文件时,Xdensity和Ydensity字段是错误的.但同样,所有图形应用程序都可以读取此非标准文件.

有人知道一段可以实际读取所有JPEG文件的Delphi代码吗?


Delphi 7,Win 7 32位

Tay*_*ird 15

我不知道所有JPEG文件,但您需要处理JPEG 的两种常见文件格式.由于JPEG是一种压缩方法而不是文件格式,因此世界各地开发了一些将JPEG图像数据存储在文件中的方法.你最有可能遇到的两个是JFIF和EXIF.上面的代码涵盖了JFIF,但不处理EXIF.这两个很大程度上是不兼容的,但都是JPEG,所以如果你使用标题信息,你需要检测和处理它们,因为它们是推迟的.

以解决方式为例.EXIF的字段是x分辨率y分辨率,与X/Y密度方法相比.

我会:

  1. 对这两种格式(JFIF和EXIF)进行一些阅读.我发现维基百科是一个很好的开始这个参考的地方(对于我已经完成的一些过去的项目),但是很可能也有关于这个主题的一些很好的信息.

    JFIF:http: //en.wikipedia.org/wiki/JPEG_File_Interchange_Format

    EXIF:http: //en.wikipedia.org/wiki/Exif

  2. 编写代码以使用起始标头检测格式

  3. 独立处理每种格式

  4. 包裹整个东西,这样你就可以在它上面扔一个JPEG并获得密度.这也将为您提供一个很好的位置来折腾其他帮助代码来处理JPEG处理的"有趣"世界


Arn*_*hez 10

以下是一些可以帮助您获取所需数据的代码:

function GetJpegSize(jpeg: TMemoryStream; out width, height, BitDepth: integer): boolean;
var n: integer;
    b: byte;
    w: Word;
begin
  result := false;
  n := jpeg.Size-8;
  jpeg.Position := 0;
  if n<=0 then
    exit;
  jpeg.Read(w,2);
  if w<>$D8FF then
    exit; // invalid format
  jpeg.Read(b,1);
  while (jpeg.Position<n) and (b=$FF) do begin
    jpeg.Read(b,1);
    case b of
      $C0..$C3: begin
        jpeg.Seek(3,soFromCurrent);
        jpeg.Read(w,2);
        height := swap(w);
        jpeg.Read(w,2);
        width := swap(w);
        jpeg.Read(b,1);
        BitDepth := b*8;
        Result := true; // JPEG format OK
        exit;
      end;
      $FF:
        jpeg.Read(b,1);
      $D0..$D9, $01: begin
        jpeg.Seek(1,soFromCurrent);
        jpeg.Read(b,1);
      end;
      else begin
        jpeg.Read(w,2);
        jpeg.Seek(swap(w)-2, soFromCurrent);
        jpeg.Read(b,1);
      end;
    end;
  end;
end;
Run Code Online (Sandbox Code Playgroud)