Q&A
HOME
Tips & Tech
Q&A
Discuss
Download
자유게시판
홍보 / 광고
구인 / 구직
LOGIN
회원가입
image를 압축하는 방법
화면의 캡쳐된 image를 압축하여 tcp/ip로 전송하고자 합니다.
image를 jpeg나 다른 format으로 압축하는 방법과 그 압축된 이미지를
다시 푸는 방법을 알고 싶습니다.
도움을 주십시요
1
COMMENTS
조규춘
•
2000.05.17 03:34
최희영 wrote:
> 화면의 캡쳐된 image를 압축하여 tcp/ip로 전송하고자 합니다.
> image를 jpeg나 다른 format으로 압축하는 방법과 그 압축된 이미지를
> 다시 푸는 방법을 알고 싶습니다.
> 도움을 주십시요
이게 도움이 될지 모르겠지만....
아래는 bitmap를 jpg로 바꾸는 겁니다.
var
Jpeg: TJpegImage;
begin
if OpenDialog1.Execute then
begin
Image1.Picture.Bitmap.LoadFromFile(OpenDialog1.FileName);
if SaveDialog1.Execute then
begin
Jpeg := TJpegImage.Create;
Jpeg.Assign(Image1.Picture.Bitmap);
Jpeg.SaveToFile(SaveDialog1.FileName);
Jpeg.Free;
end;
end;
end;
--------------------------------------------------------------------------------
아래는
256칼라 비트맵을 압축하는 겁니다.
unit Comp2;
{$IFNDEF WIN32}
Sorry, WIN 32 only!
{$ENDIF}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtDlgs, ExtCtrls, StdCtrls, Buttons, ComCtrls;
// declare own bitmap file record, specifically for 256 colour bitmaps
type
T256Palette = array [0..255] of TRGBQuad;
P256Bitmap = ^T256Bitmap;
T256Bitmap = packed record
b256File : TBitmapFileHeader;
b256Info : TBitmapInfoHeader;
b256Pal : T256Palette;
b256Data : record end;
end;
type
TBitmapCompForm = class(TForm)
GroupBox1: TGroupBox;
InBrowseBtn: TBitBtn;
InFilenameEdit: TEdit;
InFilesizeLabel: TLabel;
InScrollBox: TScrollBox;
InImage: TImage;
OpenPictureDialog: TOpenPictureDialog;
GroupBox2: TGroupBox;
OutFilenameEdit: TEdit;
OutBrowseBtn: TBitBtn;
SaveDialog: TSaveDialog;
OutScrollBox: TScrollBox;
OutImage: TImage;
CompressBtn: TBitBtn;
OutFilesizeLabel: TLabel;
CompUsingLabel: TLabel;
PaletteCheckBox: TCheckBox;
QualityTrackBar: TTrackBar;
QualityLabel: TLabel;
Label1: TLabel;
procedure InBrowseBtnClick(Sender: TObject);
procedure QualityTrackBarChange(Sender: TObject);
procedure OutBrowseBtnClick(Sender: TObject);
procedure OutFilenameEditChange(Sender: TObject);
procedure CompressBtnClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
InBitmap : P256Bitmap; // copy of bitmap file
InSize, // copy of filesize
InDataSize, // size of bitmap data
InColours : integer; // number of colours
procedure FreeStuff;
public
end;
var
BitmapCompForm: TBitmapCompForm;
implementation
{$R *.DFM}
//-- calls to video for windopws dll -------------------------------------------
type
PICInfo = ^TICInfo;
TICInfo = packed record
dwSize, // sizeof (TICInfo)
fccType, // compressor type eg vidc
fccHandler, // compressor subtype eg rle
dwFlags, // lo word is type specific
dwVersion, // version of driver
dwVersionICM : DWORD; // version of the ICM
szName : array [0..15] of wchar; // short name
szDescription : array [0..127] of wchar; // long name
szDriver : array [0..127] of wchar; // driver that contains the compressor
end;
const
ICMODE_COMPRESS = 1;
ICTYPE_VIDEO = ord ('v') +
ord ('i') shl 8 +
ord ('d') shl 16 +
ord ('c') shl 24;
type
TICHandle = THandle;
function ICLocate (fccType, fccHandler: DWORD; lpbiIn, lpbmOut : PBitmapInfoHeader; wFlags: word) : TICHandle;
stdcall; external 'msvfw32.dll' name 'ICLocate';
function ICGetInfo (Handle: TICHandle; var ICInfo: TICInfo; cb: DWORD): LRESULT;
stdcall; external 'msvfw32.dll' name 'ICGetInfo';
function ICImageCompress (Handle: TICHandle; uiFlags: UINT; lpbiIn: PBitmapInfo;
lpBits: pointer; lpbiOut: PBitmapInfo; lQuality: integer; plSize: PInteger): HBitmap;
stdcall; external 'msvfw32.dll' name 'ICImageCompress';
function ICClose (Handle: TICHandle): LRESULT;
stdcall; external 'msvfw32.dll' name 'ICClose';
//--- compressor form ----------------------------------------------------------
const
FSStr = 'File size: %d';
CUStr = 'Compressed using: %s';
BitmapSignature = $4D42;
procedure TBitmapCompForm.FormDestroy(Sender: TObject);
begin
FreeStuff
end;
procedure TBitmapCompForm.FreeStuff;
begin
if InSize <> 0 then
begin
FreeMem (InBitmap, InSize);
InBitmap := nil;
InSize := 0
end
end;
procedure TBitmapCompForm.InBrowseBtnClick(Sender: TObject);
var
Bitmap : TBitmap;
begin
with OpenPictureDialog do
if Execute then
begin
InFilesizeLabel.Caption := Format (FSStr, [0]);
InImage.Picture := nil;
InFilenameEdit.Text := '';
FreeStuff;
with TFileStream.Create (Filename, fmOpenRead) do
try
InSize := Size;
GetMem (InBitmap, InSize);
Read (InBitmap^, InSize);
with InBitmap^ do
if b256File.bfType = BitmapSignature then
if b256Info.biBitCount = 8 then
if b256Info.biCompression = BI_RGB then
begin
// Ok, we have a 256 colour, uncompressed bitmap
InFilenameEdit.Text := Filename;
// determine number of entries in palette
if b256Info.biClrUsed = 0 then
InColours := 256
else
InColours := b256Info.biClrUsed;
// determine size of data bits
with InBitmap^.b256Info do
if biSizeImage = 0 then
InDataSize := biWidth * biHeight
else
InDataSize := biSizeImage
end else
ShowMessage ('Bitmap already compressed')
else
ShowMessage ('Not a 256 colour bitmap')
else
ShowMessage ('Not a bitmap')
finally
Free
end;
// show the bitmap and file size
if InFileNameEdit.Text <> '' then
begin
Bitmap := TBitmap.Create;
try
Bitmap.LoadFromFile (InFilenameEdit.Text);
InImage.Picture.Bitmap := Bitmap
finally
Bitmap.Free
end;
InScrollBox.VertScrollBar.Range := InBitmap^.b256Info.biHeight;
InScrollBox.HorzScrollBar.Range := InBitmap^.b256Info.biWidth;
InFilesizeLabel.Caption := Format (FSStr, [InBitmap^.b256File.bfSize])
end
end
end;
procedure TBitmapCompForm.OutBrowseBtnClick(Sender: TObject);
begin
with SaveDialog do
if Execute then
OutFilenameEdit.Text := Filename
end;
//--- Palette Compression ------------------------------------------------------
// compress a 256 colour palette by removing unused entries
// returns new number of entries
function CompressPalette (var Pal: T256Palette; Data: pointer; DataSize: integer): word;
type
TPaletteUsed = packed record
Used : boolean;
NewEntry : byte;
end;
TPaletteUsedArray = array [0..255] of TPaletteUsed;
var
PUArray: TPaletteUsedArray;
Scan: PByte;
NewValue,
Loop: integer;
NewPal : T256Palette;
begin
// look through the bitmap data bytes looking for palette entries in use
fillchar (PUArray, sizeof (PUArray), 0);
Scan:= Data;
for Loop:= 1 to DataSize do
begin
PUArray[Scan^].Used := true;
inc (Scan)
end;
// go through palette and set new entry numbers for those in use
NewValue := 0;
for Loop:= 0 to 255 do
with PUArray[Loop] do
if Used then
begin
NewEntry := NewValue;
inc (NewValue);
end;
Result := NewValue; // return number in use
if NewValue = 256 then
exit; // QED
// go through bitmap data assigninging new palette numbers
Scan:= Data;
for Loop:= 1 to DataSize do
begin
Scan^ := PUArray[Scan^].NewEntry;
inc (Scan)
end;
// create a new palette and copy across only those entries in use
fillchar (NewPal, sizeof (T256Palette), 0);
for Loop := 0 to 255 do
with PUArray [Loop] do
if Used then
NewPal[NewEntry] := Pal [Loop];
// return the new palette
Pal := NewPal
end;
//--- try to compress input image -> output image ------------------------------
procedure TBitmapCompForm.CompressBtnClick(Sender: TObject);
var
Bitmap: TBitmap;
Handle: THandle;
CompressHandle: integer;
ICInfo: TICInfo;
OutBitmap,
InBitmapCopy : P256Bitmap;
CompressedStuff,
OutData,
InDataCopy : pointer;
OutSize,
OutColours : integer;
begin
// make an output bitmap file
GetMem (OutBitmap, sizeof (T256Bitmap));
try
// make a copy of the input file as we will play with the data
GetMem (InBitmapCopy, InSize);
try
Move (InBitmap^, InBitmapCopy^, InSize);
InDataCopy := pointer (integer(InBitmapCopy) + sizeof (TBitmapFileHeader) +
sizeof (TBitmapInfoHeader) + InColours * sizeof (TRGBQuad));
// crunch the palette
with InBitmapCopy^ do
if PaletteCheckBox.Checked then
OutColours := CompressPalette (b256Pal, InDataCopy, InDataSize)
else
OutColours := InColours;
// now copy the input file to fill in most of the output bitmap values
Move (InBitmapCopy^, OutBitmap^, sizeof (T256Bitmap));
// set the compression required
OutBitmap^.b256Info.biCompression := BI_RLE8;
// find a compressor
CompressHandle := ICLocate (ICTYPE_VIDEO, 0, @InBitmapCopy^.b256Info,
@OutBitmap.b256Info, ICMODE_COMPRESS);
try
fillchar (ICInfo, sizeof (TICInfo), 0);
ICInfo.dwSize := sizeof (TICInfo);
// get info on the compressor
ICGetInfo (CompressHandle, ICInfo, sizeof (TICInfo));
OutSize := 0; // best compression
// now compress the image
Handle := ICImageCompress (CompressHandle, 0, @InBitmapCopy^.b256Info,
InDataCopy, @OutBitmap^.b256Info, QualityTrackBar.Position*100, @OutSize);
finally
ICClose (CompressHandle)
end;
if Handle <> 0 then
begin
// get the compressed data
CompressedStuff := GlobalLock (Handle);
try
// modify the filesize and offset in case palette has shrunk
with OutBitmap^.b256File do
begin
bfOffBits := sizeof (TBitmapFileHeader) + sizeof(TBitmapInfoHeader) +
OutColours * sizeof (TRGBQuad);
bfSize := bfOffBits + OutSize
end;
// locate the data
OutData := pointer (integer(CompressedStuff) +
sizeof(TBitmapInfoHeader) + InColours * sizeof (TRGBQuad));
// modify the bitmap info header
with OutBitmap^.b256Info do
begin
biSizeImage := OutSize;
biClrUsed := OutColours;
biClrImportant := 0
end;
// save the bitmap to disc
with TFileStream.Create (OutFilenameEdit.Text, fmCreate) do
try
write (OutBitmap^, sizeof (TBitmapFileHeader) + sizeof (TBitmapInfoHeader));
write (InBitmapCopy^.b256Pal, OutColours*sizeof (TRGBQuad));
write (OutData^, OutSize)
finally
Free
end;
// view the result
Bitmap := TBitmap.Create;
try
Bitmap.LoadFromFile (OutFilenameEdit.Text);
OutImage.Picture.Bitmap := Bitmap
finally
Bitmap.Free
end;
// set the scrollbars and give some stats
with OutBitmap^ do
begin
OutScrollBox.VertScrollBar.Range := b256Info.biHeight;
OutScrollBox.HorzScrollBar.Range := b256Info.biWidth;
OutFileSizeLabel.Caption := Format (FSStr, [b256File.bfSize]);
CompUsingLabel.Caption := Format (CUStr, [WideCharToString (ICInfo.szDescription)])
end
// now tidy up
finally
GlobalUnlock (Handle)
end
end else
ShowMessage ('Bitmap could not be compressed')
finally
FreeMem (InBitmapCopy, InSize)
end
finally
FreeMem (OutBitmap, sizeof (T256Bitmap))
end
end;
procedure TBitmapCompForm.QualityTrackBarChange(Sender: TObject);
begin
QualityLabel.Caption := IntToStr (QualityTrackBar.Position)
end;
procedure TBitmapCompForm.OutFilenameEditChange(Sender: TObject);
begin
CompressBtn.Enabled := (InFilenameEdit.Text <> '') and
(OutFilenameEdit.Text <> '')
end;
end.
---------------------------------------------------------------------------
만약 필요하다면 소스 자체를 메일로 보내드리지요~! 푸힝
즐거운 하루 되시구요~! 규춘올림.
0
0
삭제
수정
댓글
(NOTICE) You must be
logged in
to comment on this post.
델초보
•
2000.05.17 10:35
3
COMMENTS
/
0
LIKES
윈도우에서여~~
타락천사
•
2000.05.17 19:27
안녕하세여.. 타락임다..^^ 그건 빈폼을 만들어서 빈폼의 함수마다 어떤 값을 보이게 하면 쉽게 실행순...
홍세비
•
2000.05.17 19:00
델초보 wrote: > 윈도우에서 프로그램을 실행할 때.. > 실행되는 경로(과정)이 알고 싶은데.. > 아시는 ...
nilriri
•
2000.05.17 18:40
showmessage(application.ExeName); 이렇게하면 실행파일의 경로명과 파일명을 알수 있습니다... 가...
초보
2000.05.17 09:56
0
COMMENTS
/
0
LIKES
급합니다 '프로그램 시작오류' 에러 왜 그러죠
그냥
2000.05.17 09:51
0
COMMENTS
/
0
LIKES
[답변]...
초보
2000.05.17 07:11
0
COMMENTS
/
0
LIKES
어떤 윈도우의 핸들은 잡았으나....
novice
•
2000.05.17 06:48
3
COMMENTS
/
0
LIKES
function에 관한 질문이있는데요..(초보라서)
최용일
•
2000.05.18 00:28
안녕하세요. 최용일입니다. 좀 이상한 질문이네요. 배열을 넘겨주어 값을 구한다고 했는데 코딩은 배열...
novice
•
2000.05.18 00:12
flash wrote: > novice wrote: > > 삼차원 array값을 function에 넘겨주어 값을 구해 오는 방법좀 가르쳐...
타락천사
•
2000.05.17 18:48
안녕하세여.. 타락임다..^^ 제 생각에는 삼차원 어레이를 전역변수로 쓰는것이 좋겠네여.. 함수 파라...
한호
2000.05.17 06:13
0
COMMENTS
/
0
LIKES
윈도우2000에서 작업해보신분들...
이병협
2000.05.17 05:43
0
COMMENTS
/
0
LIKES
application이 minimize될때 특정폼만 그대로 있게 할수는 없을까요?
최상열
•
2000.05.17 04:57
1
COMMENTS
/
0
LIKES
컴포넌트 고수분의 조언을 급히 구합니다..
최석기
•
2000.05.17 05:06
최상열 wrote: > 제가 컴포넌트를 등록해서 쓰려고 하는데 소스파일인 *.pas는 없고 *.dcu파일만 있습니다...
Macgyver
•
2000.05.17 04:25
1
COMMENTS
/
0
LIKES
델파이의 BDE ?
배재근
•
2000.05.18 00:19
Macgyver wrote: > > 델파이 5.0에서 DB Grid있잖아요 그걸루 사용자가 데이타를 입력[한번에 많게는 40...
어린왕자
•
2000.05.17 04:09
1
COMMENTS
/
0
LIKES
툴바에서 툴버튼 세개를 넣었는데요..그중 하나만 내려가게..막노동해야하나요?
홍세비
•
2000.05.17 04:23
어린왕자 wrote: > 안녕하세요..어린왕자입니다.. > 완전 초보질문..T.T > 툴바의 툴버튼 3개를 만들었...
힙합인
•
2000.05.17 03:36
1
COMMENTS
/
0
LIKES
이 에러메시지 어케 없앨수있어여? 가르쳐주세요
한차으히
•
2000.05.17 06:15
힙합인 wrote: > 에러1 > > ♥ 상세내용 참조 > ♥ 상세내용: > tblCommon: Field index out of range ...
Ghost Lee
2000.05.17 03:18
0
COMMENTS
/
0
LIKES
sqlDB
최희영
•
•
2000.05.17 03:17
1
COMMENTS
/
1
LIKES
image를 압축하는 방법
화면의 캡쳐된 image를 압축하여 tcp/ip로 전송하고자 합니다. image를 jpeg나 다른 format으로 압축하는 방법과 그 압축된 이미지를 다시 푸는 방법을 알고 싶습니다. 도움을 주십시요
조규춘
•
2000.05.17 03:34
최희영 wrote: > 화면의 캡쳐된 image를 압축하여 tcp/ip로 전송하고자 합니다. > image를 jpeg나 다른 f...
김문기
•
2000.05.17 03:10
1
COMMENTS
/
0
LIKES
record형에 point를 사용하는 방법???
타락천사
•
2000.05.17 18:46
안녕하세여.. 타락임다.. ^^ 당근 에러가 나져.. 이렇게 바꿔보세여.. type P_Item = ^T_Item; ...
최영국
2000.05.17 02:53
0
COMMENTS
/
0
LIKES
dialog box에 버튼삽입과 그 이벤트는 어떻게 추가할 수 있나요?
김문기
•
2000.05.17 01:57
2
COMMENTS
/
0
LIKES
다른 실행파일을 CALL할수 있는 방법 알려주시와요????
구창민
•
2000.05.17 02:06
김문기 wrote: > 델파이3.0을 사용하는 초보자 입니다. > > 프로그램에서 다른 프로그램을 실행하여야 ...
김문기
•
2000.05.17 02:58
구창민 wrote: > 김문기 wrote: > > 델파이3.0을 사용하는 초보자 입니다. > > > > 프로그램에서 다른...
울랄라
2000.05.17 01:56
0
COMMENTS
/
0
LIKES
일반어플리케이션을 웹버전으루...
잔상
2000.05.17 01:53
0
COMMENTS
/
0
LIKES
매크로 프로그램에서....
답좀 줘요
2000.05.17 01:38
0
COMMENTS
/
0
LIKES
3Tier DB에서 Data update ?
준희
•
2000.05.17 01:29
2
COMMENTS
/
0
LIKES
String Grid에서 Multi Select할 수 있는 방법좀....
구창민
•
2000.05.17 01:50
준희 wrote: > 안녕하세요. 델초보입니다. > > 즐거운 하루를 맞이하셨는지요... 다름이 아니라... > ...
준희
•
2000.05.17 02:02
안녕하세요.. 어떠한 범위를 정하는 것이 아니라 범위도 정할 수 있고 또한 한칸 건너뛰어서 선택할 수 ...
최희영
2000/05/17 03:17
Views
259
Likes
1
Comments
1
Reports
0
Tag List
수정
삭제
목록으로
한델 로그인 하기
로그인 상태 유지
아직 회원이 아니세요? 가입하세요!
암호를 잊어버리셨나요?
> 화면의 캡쳐된 image를 압축하여 tcp/ip로 전송하고자 합니다.
> image를 jpeg나 다른 format으로 압축하는 방법과 그 압축된 이미지를
> 다시 푸는 방법을 알고 싶습니다.
> 도움을 주십시요
이게 도움이 될지 모르겠지만....
아래는 bitmap를 jpg로 바꾸는 겁니다.
var
Jpeg: TJpegImage;
begin
if OpenDialog1.Execute then
begin
Image1.Picture.Bitmap.LoadFromFile(OpenDialog1.FileName);
if SaveDialog1.Execute then
begin
Jpeg := TJpegImage.Create;
Jpeg.Assign(Image1.Picture.Bitmap);
Jpeg.SaveToFile(SaveDialog1.FileName);
Jpeg.Free;
end;
end;
end;
--------------------------------------------------------------------------------
아래는
256칼라 비트맵을 압축하는 겁니다.
unit Comp2;
{$IFNDEF WIN32}
Sorry, WIN 32 only!
{$ENDIF}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtDlgs, ExtCtrls, StdCtrls, Buttons, ComCtrls;
// declare own bitmap file record, specifically for 256 colour bitmaps
type
T256Palette = array [0..255] of TRGBQuad;
P256Bitmap = ^T256Bitmap;
T256Bitmap = packed record
b256File : TBitmapFileHeader;
b256Info : TBitmapInfoHeader;
b256Pal : T256Palette;
b256Data : record end;
end;
type
TBitmapCompForm = class(TForm)
GroupBox1: TGroupBox;
InBrowseBtn: TBitBtn;
InFilenameEdit: TEdit;
InFilesizeLabel: TLabel;
InScrollBox: TScrollBox;
InImage: TImage;
OpenPictureDialog: TOpenPictureDialog;
GroupBox2: TGroupBox;
OutFilenameEdit: TEdit;
OutBrowseBtn: TBitBtn;
SaveDialog: TSaveDialog;
OutScrollBox: TScrollBox;
OutImage: TImage;
CompressBtn: TBitBtn;
OutFilesizeLabel: TLabel;
CompUsingLabel: TLabel;
PaletteCheckBox: TCheckBox;
QualityTrackBar: TTrackBar;
QualityLabel: TLabel;
Label1: TLabel;
procedure InBrowseBtnClick(Sender: TObject);
procedure QualityTrackBarChange(Sender: TObject);
procedure OutBrowseBtnClick(Sender: TObject);
procedure OutFilenameEditChange(Sender: TObject);
procedure CompressBtnClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
InBitmap : P256Bitmap; // copy of bitmap file
InSize, // copy of filesize
InDataSize, // size of bitmap data
InColours : integer; // number of colours
procedure FreeStuff;
public
end;
var
BitmapCompForm: TBitmapCompForm;
implementation
{$R *.DFM}
//-- calls to video for windopws dll -------------------------------------------
type
PICInfo = ^TICInfo;
TICInfo = packed record
dwSize, // sizeof (TICInfo)
fccType, // compressor type eg vidc
fccHandler, // compressor subtype eg rle
dwFlags, // lo word is type specific
dwVersion, // version of driver
dwVersionICM : DWORD; // version of the ICM
szName : array [0..15] of wchar; // short name
szDescription : array [0..127] of wchar; // long name
szDriver : array [0..127] of wchar; // driver that contains the compressor
end;
const
ICMODE_COMPRESS = 1;
ICTYPE_VIDEO = ord ('v') +
ord ('i') shl 8 +
ord ('d') shl 16 +
ord ('c') shl 24;
type
TICHandle = THandle;
function ICLocate (fccType, fccHandler: DWORD; lpbiIn, lpbmOut : PBitmapInfoHeader; wFlags: word) : TICHandle;
stdcall; external 'msvfw32.dll' name 'ICLocate';
function ICGetInfo (Handle: TICHandle; var ICInfo: TICInfo; cb: DWORD): LRESULT;
stdcall; external 'msvfw32.dll' name 'ICGetInfo';
function ICImageCompress (Handle: TICHandle; uiFlags: UINT; lpbiIn: PBitmapInfo;
lpBits: pointer; lpbiOut: PBitmapInfo; lQuality: integer; plSize: PInteger): HBitmap;
stdcall; external 'msvfw32.dll' name 'ICImageCompress';
function ICClose (Handle: TICHandle): LRESULT;
stdcall; external 'msvfw32.dll' name 'ICClose';
//--- compressor form ----------------------------------------------------------
const
FSStr = 'File size: %d';
CUStr = 'Compressed using: %s';
BitmapSignature = $4D42;
procedure TBitmapCompForm.FormDestroy(Sender: TObject);
begin
FreeStuff
end;
procedure TBitmapCompForm.FreeStuff;
begin
if InSize <> 0 then
begin
FreeMem (InBitmap, InSize);
InBitmap := nil;
InSize := 0
end
end;
procedure TBitmapCompForm.InBrowseBtnClick(Sender: TObject);
var
Bitmap : TBitmap;
begin
with OpenPictureDialog do
if Execute then
begin
InFilesizeLabel.Caption := Format (FSStr, [0]);
InImage.Picture := nil;
InFilenameEdit.Text := '';
FreeStuff;
with TFileStream.Create (Filename, fmOpenRead) do
try
InSize := Size;
GetMem (InBitmap, InSize);
Read (InBitmap^, InSize);
with InBitmap^ do
if b256File.bfType = BitmapSignature then
if b256Info.biBitCount = 8 then
if b256Info.biCompression = BI_RGB then
begin
// Ok, we have a 256 colour, uncompressed bitmap
InFilenameEdit.Text := Filename;
// determine number of entries in palette
if b256Info.biClrUsed = 0 then
InColours := 256
else
InColours := b256Info.biClrUsed;
// determine size of data bits
with InBitmap^.b256Info do
if biSizeImage = 0 then
InDataSize := biWidth * biHeight
else
InDataSize := biSizeImage
end else
ShowMessage ('Bitmap already compressed')
else
ShowMessage ('Not a 256 colour bitmap')
else
ShowMessage ('Not a bitmap')
finally
Free
end;
// show the bitmap and file size
if InFileNameEdit.Text <> '' then
begin
Bitmap := TBitmap.Create;
try
Bitmap.LoadFromFile (InFilenameEdit.Text);
InImage.Picture.Bitmap := Bitmap
finally
Bitmap.Free
end;
InScrollBox.VertScrollBar.Range := InBitmap^.b256Info.biHeight;
InScrollBox.HorzScrollBar.Range := InBitmap^.b256Info.biWidth;
InFilesizeLabel.Caption := Format (FSStr, [InBitmap^.b256File.bfSize])
end
end
end;
procedure TBitmapCompForm.OutBrowseBtnClick(Sender: TObject);
begin
with SaveDialog do
if Execute then
OutFilenameEdit.Text := Filename
end;
//--- Palette Compression ------------------------------------------------------
// compress a 256 colour palette by removing unused entries
// returns new number of entries
function CompressPalette (var Pal: T256Palette; Data: pointer; DataSize: integer): word;
type
TPaletteUsed = packed record
Used : boolean;
NewEntry : byte;
end;
TPaletteUsedArray = array [0..255] of TPaletteUsed;
var
PUArray: TPaletteUsedArray;
Scan: PByte;
NewValue,
Loop: integer;
NewPal : T256Palette;
begin
// look through the bitmap data bytes looking for palette entries in use
fillchar (PUArray, sizeof (PUArray), 0);
Scan:= Data;
for Loop:= 1 to DataSize do
begin
PUArray[Scan^].Used := true;
inc (Scan)
end;
// go through palette and set new entry numbers for those in use
NewValue := 0;
for Loop:= 0 to 255 do
with PUArray[Loop] do
if Used then
begin
NewEntry := NewValue;
inc (NewValue);
end;
Result := NewValue; // return number in use
if NewValue = 256 then
exit; // QED
// go through bitmap data assigninging new palette numbers
Scan:= Data;
for Loop:= 1 to DataSize do
begin
Scan^ := PUArray[Scan^].NewEntry;
inc (Scan)
end;
// create a new palette and copy across only those entries in use
fillchar (NewPal, sizeof (T256Palette), 0);
for Loop := 0 to 255 do
with PUArray [Loop] do
if Used then
NewPal[NewEntry] := Pal [Loop];
// return the new palette
Pal := NewPal
end;
//--- try to compress input image -> output image ------------------------------
procedure TBitmapCompForm.CompressBtnClick(Sender: TObject);
var
Bitmap: TBitmap;
Handle: THandle;
CompressHandle: integer;
ICInfo: TICInfo;
OutBitmap,
InBitmapCopy : P256Bitmap;
CompressedStuff,
OutData,
InDataCopy : pointer;
OutSize,
OutColours : integer;
begin
// make an output bitmap file
GetMem (OutBitmap, sizeof (T256Bitmap));
try
// make a copy of the input file as we will play with the data
GetMem (InBitmapCopy, InSize);
try
Move (InBitmap^, InBitmapCopy^, InSize);
InDataCopy := pointer (integer(InBitmapCopy) + sizeof (TBitmapFileHeader) +
sizeof (TBitmapInfoHeader) + InColours * sizeof (TRGBQuad));
// crunch the palette
with InBitmapCopy^ do
if PaletteCheckBox.Checked then
OutColours := CompressPalette (b256Pal, InDataCopy, InDataSize)
else
OutColours := InColours;
// now copy the input file to fill in most of the output bitmap values
Move (InBitmapCopy^, OutBitmap^, sizeof (T256Bitmap));
// set the compression required
OutBitmap^.b256Info.biCompression := BI_RLE8;
// find a compressor
CompressHandle := ICLocate (ICTYPE_VIDEO, 0, @InBitmapCopy^.b256Info,
@OutBitmap.b256Info, ICMODE_COMPRESS);
try
fillchar (ICInfo, sizeof (TICInfo), 0);
ICInfo.dwSize := sizeof (TICInfo);
// get info on the compressor
ICGetInfo (CompressHandle, ICInfo, sizeof (TICInfo));
OutSize := 0; // best compression
// now compress the image
Handle := ICImageCompress (CompressHandle, 0, @InBitmapCopy^.b256Info,
InDataCopy, @OutBitmap^.b256Info, QualityTrackBar.Position*100, @OutSize);
finally
ICClose (CompressHandle)
end;
if Handle <> 0 then
begin
// get the compressed data
CompressedStuff := GlobalLock (Handle);
try
// modify the filesize and offset in case palette has shrunk
with OutBitmap^.b256File do
begin
bfOffBits := sizeof (TBitmapFileHeader) + sizeof(TBitmapInfoHeader) +
OutColours * sizeof (TRGBQuad);
bfSize := bfOffBits + OutSize
end;
// locate the data
OutData := pointer (integer(CompressedStuff) +
sizeof(TBitmapInfoHeader) + InColours * sizeof (TRGBQuad));
// modify the bitmap info header
with OutBitmap^.b256Info do
begin
biSizeImage := OutSize;
biClrUsed := OutColours;
biClrImportant := 0
end;
// save the bitmap to disc
with TFileStream.Create (OutFilenameEdit.Text, fmCreate) do
try
write (OutBitmap^, sizeof (TBitmapFileHeader) + sizeof (TBitmapInfoHeader));
write (InBitmapCopy^.b256Pal, OutColours*sizeof (TRGBQuad));
write (OutData^, OutSize)
finally
Free
end;
// view the result
Bitmap := TBitmap.Create;
try
Bitmap.LoadFromFile (OutFilenameEdit.Text);
OutImage.Picture.Bitmap := Bitmap
finally
Bitmap.Free
end;
// set the scrollbars and give some stats
with OutBitmap^ do
begin
OutScrollBox.VertScrollBar.Range := b256Info.biHeight;
OutScrollBox.HorzScrollBar.Range := b256Info.biWidth;
OutFileSizeLabel.Caption := Format (FSStr, [b256File.bfSize]);
CompUsingLabel.Caption := Format (CUStr, [WideCharToString (ICInfo.szDescription)])
end
// now tidy up
finally
GlobalUnlock (Handle)
end
end else
ShowMessage ('Bitmap could not be compressed')
finally
FreeMem (InBitmapCopy, InSize)
end
finally
FreeMem (OutBitmap, sizeof (T256Bitmap))
end
end;
procedure TBitmapCompForm.QualityTrackBarChange(Sender: TObject);
begin
QualityLabel.Caption := IntToStr (QualityTrackBar.Position)
end;
procedure TBitmapCompForm.OutFilenameEditChange(Sender: TObject);
begin
CompressBtn.Enabled := (InFilenameEdit.Text <> '') and
(OutFilenameEdit.Text <> '')
end;
end.
---------------------------------------------------------------------------
만약 필요하다면 소스 자체를 메일로 보내드리지요~! 푸힝
즐거운 하루 되시구요~! 규춘올림.