본문 바로가기
delphi

JPEG/GIF/BMP/PNG/PCX 이미지 정보 얻기

by 천지조율 2024. 8. 2.

이미지 파일의 다양한 형식과 관련된 정보를 자동으로 추출할 수 있는 방법을 이해하는 것은 매우 중요합니다. 이를 통해 이미지 크기, 색상 깊이, 이미지 유형 등을 쉽게 파악할 수 있습니다. 이 글에서는 JPEG, GIF, BMP, PNG, PCX 이미지의 정보를 얻는 방법을 자세히 설명합니다.

이미지 정보 추출의 중요성

이미지 파일에서 정보를 추출하는 것은 여러 방면에서 유용합니다. 예를 들어, 웹 개발자는 웹사이트에 업로드된 이미지의 크기와 형식을 검사하여 적절한 포맷으로 변환할 수 있습니다. 또한, 데이터 분석가는 이미지 데이터의 특성을 파악하여 분석에 활용할 수 있습니다.

주요 이미지 형식 및 정보

여러 가지 이미지 형식들이 있으며, 각 형식은 고유한 특징을 가지고 있습니다. 여기서는 JPEG, GIF, BMP, PNG, PCX 이미지 형식의 정보를 추출하는 방법을 설명합니다.

JPEG 이미지 정보 추출

JPEG는 손실 압축을 사용하는 이미지 파일 포맷으로, 높은 압축률과 적절한 화질을 제공합니다.

procedure ReadJPEG;
var
    Pos: Integer;
    w: Word;
    b: Byte;
    Buffer: array[0..2] of Byte;
begin
    Pos :=0;
    // find beginning of JPEG stream
    While True do
    begin
        ImageFile.Position := Pos;
        ImageFile.ReadBuffer(Buffer, 3);
        if (Buffer[0] = $FF) and (Buffer[1] = $D8) and (Buffer[2] = $FF) then
            break;
        Pos := Pos + 1;
    end;

    Pos := Pos +1;
    // loop through each marker until we find the C0 marker (or C1 or C2) which has the image information
    While True do
    begin
        // find beginning of next marker
        While True do
        begin
            ImageFile.Position := Pos;
            ImageFile.ReadBuffer(Buffer, 2);
            if (Buffer[0] = $FF) and (Buffer[1] <> $FF) then
                break;
            Pos := Pos + 1;
        end;

        // exit the loop if we've found the correct marker
        b := Buffer[1];
        if (b = $C0) or (b = $C1) or (b = $c2) or (b = $C3) then
            break;

        // otherwise find position of next marker
        ImageFile.Position := Pos + 2;
        ImageFile.ReadBuffer(w, 2);
        Pos := Pos + Swap(w);
    end;

    FImageType := itJPEG;
    ImageFile.Position := Pos + 5;
    ImageFile.ReadBuffer(w, 2);
    FHeight := Swap(w);

    ImageFile.ReadBuffer(w, 2);
    FWidth := Swap(w);

    ImageFile.ReadBuffer(b, 1);
    FDepth := b * 8;
end;

GIF 이미지 정보 추출

GIF는 주로 애니메이션 이미지에 사용되는 포맷으로, 무손실 압축을 사용합니다.

procedure ReadGIF;
var
    b: Byte;
    w: Word;
begin
    FImageType := itGIF;
    ImageFile.Position := 6;

    ImageFile.ReadBuffer(w, 2);
    FWidth := w;

    ImageFile.ReadBuffer(w, 2);
    FHeight := w;

    ImageFile.ReadBuffer(b, 1);
    FDepth := (b and 7) + 1;
end;

BMP 이미지 정보 추출

BMP는 비트맵 이미지 파일 포맷으로, 일반적으로 압축되지 않은 형태로 저장됩니다.

procedure ReadBMP;
var
    b: Byte;
    w: Word;
begin
    FImageType := itBMP;
    ImageFile.Position := 18;
    ImageFile.ReadBuffer(w, 2);
    FWidth := w;

    ImageFile.Position := 22;
    ImageFile.ReadBuffer(w, 2);
    FHeight := w;

    ImageFile.Position := 28;
    ImageFile.ReadBuffer(b, 1);
    FDepth := b;
end;

PNG 이미지 정보 추출

PNG는 무손실 압축을 사용하는 이미지 포맷으로, 투명도 정보를 포함할 수 있습니다.

procedure ReadPNG;
var
    b: Byte;
    c: Byte;
    w: Word;
begin
    FImageType := itPNG;
    ImageFile.Position := 24;

    ImageFile.ReadBuffer(b, 1);
    ImageFile.ReadBuffer(c, 1);

    // color depth
    Case c Of
        0: FDepth := b;  // greyscale
        2: FDepth := b * 3; // RGB
        3: FDepth := 8; // Palette based
        4: FDepth := b * 2; // greyscale with alpha
        6: FDepth := b * 4; // RGB with alpha
    Else
        FImageType := itUnknown;
    End;

    If FImageType = itPNG Then
    begin
        ImageFile.Position := 18;
        ImageFile.ReadBuffer(w, 2);
        FWidth := Swap(w);
        ImageFile.Position := 22;
        ImageFile.ReadBuffer(w, 2);
        FHeight := Swap(w);
    end;
end;

PCX 이미지 정보 추출

PCX는 과거에 많이 사용되던 비트맵 형식의 파일 포맷입니다.

procedure ReadPCX;
var
    b1: Byte;
    b2: Byte;
    X1: Word;
    X2: Word;
    Y1: Word;
    Y2: Word;
begin
    FImageType := itPCX;
    ImageFile.Position := 3;
    ImageFile.ReadBuffer(b1, 1);
    ImageFile.ReadBuffer(X1, 2);
    ImageFile.ReadBuffer(Y1, 2);
    ImageFile.ReadBuffer(X2, 2);
    ImageFile.ReadBuffer(Y2, 2);
    ImageFile.Position := 65;
    ImageFile.ReadBuffer(b2, 1);

    FWidth := (X2 - X1) + 1;
    FHeight := (Y2 - Y1) + 1;
    FDepth := b1 * b2;
end;

TDCImageInfo 클래스 사용법

이제, 위에서 설명한 메서드를 포함하여 TDCImageInfo 클래스를 작성하고 이를 이용해 이미지 정보를 추출하는 방법을 설명합니다.

클래스 선언 및 구현

unit DCImageInfo;

interface
uses SysUtils, Classes;

const
TIFF_WIDTH = 256;
TIFF_HEIGHT = 257;
TIFF_BITSPERSAMPLE = 258;
TIFF_BYTE = 1;
TIFF_WORD = 3;
TIFF_DWORD = 4;

type
    TImageType = (itUnknown, itGIF, itJPEG, itPNG, itBMP, itPCX, itTIFF);

type
    TDCImageInfo = Class(TObject)
    private
        ImageFile: TFileStream;
        FWidth: integer;
        FHeight: integer;
        FDepth: integer;
        FImageType: TImageType;
        FFileSize: integer;
        procedure ReadPNG;
        procedure ReadGIF;
        procedure ReadBMP;
        procedure ReadPCX;
        procedure ReadLETIFF;
        procedure ReadBETIFF;
        procedure ReadJPEG;
        procedure ResetValues;
        function Swap32(Value: Integer): Integer;
    public
        property Width: integer read FWidth;
        property Height: integer read FHeight;
        property Depth: integer read FDepth;
        property ImageType: TImageType read FImageType;
        property FileSize: integer read FFileSize;
        procedure ReadFile(const FileName: String);
    end;

implementation

procedure TDCImageInfo.ReadFile(const FileName: String);
var
    Buffer: array[0..2] of Byte;
begin
    ResetValues;
    Try
        ImageFile := TFileStream.Create(FileName, fmOpenRead);
    Except;
        Exit;
    End;
    FFileSize := ImageFile.Size;
    Try
        ImageFile.ReadBuffer(Buffer, 3);
    Except;
        ImageFile.Free;
        Exit;
    End;
    if (Buffer[0] = 137) and (Buffer[1] = 80) and (Buffer[2] = 78) Then
        Try ReadPNG; Except ResetValues; End;
    if (Buffer[0] = 71) and (Buffer[1] = 73) and (Buffer[2] = 70) Then
        Try ReadGIF; Except ResetValues; End;
    if (Buffer[0] = 66) and (Buffer[1] = 77) Then
        Try ReadBMP; Except ResetValues; End;
    if (Buffer[0] = 10) Then
        Try ReadPCX; Except ResetValues; End;
    if (Buffer[0] = 73) and (Buffer[1] = 73) and (Buffer[2] = 42) Then
        Try ReadLETIFF; Except ResetValues; End;
    if (Buffer[0] = 77) and (Buffer[1] = 77) and (Buffer[2] = 42) Then
        Try ReadBETIFF; Except ResetValues; End;
    if (Buffer[0] = 255) and (Buffer[1] = 216) and (Buffer[2] = 255) Then
        Try ReadJPEG; Except ResetValues; End;
    ImageFile.Free;
end;

procedure TDCImageInfo.ResetValues;
begin
    FWidth := 0;
    FHeight := 0;
    FDepth := 0;
    FImageType := itUnknown;
    FFileSize := 0;
end;

function TDCImageInfo.Swap32(Value: Integer): Integer;
asm
    BSWAP EAX
end;

사용 예시

procedure TForm1.Button1Click(Sender: TObject);
var
    ImageInfo: TDCImageInfo;
begin
    ImageInfo := TDCImageInfo.Create;
    ImageInfo.ReadFile('C:\Path\To\Your\Image.jpg');
    ShowMessage('Image Width: ' + IntToStr(ImageInfo.Width) +
                ' Height: ' + IntToStr(ImageInfo.Height) +
                ' Depth: ' + IntToStr(ImageInfo.Depth));
    ImageInfo.Free;
end;

결론

위의 방법들을 통해 JPEG, GIF, BMP, PNG, PCX 이미지 파일의 정보를 효과적으로 추출할 수 있습니다. 각 파일 형식에 맞는 메서드를 사용하여 이미지를 분석하고, 필요한 데이터를 얻을 수 있습니다. 이러한 접근 방식은 이미지 파일의 관리와 분석에 매우 유용합니다.