Amiga C

19. Bölüm

Cenker Özkurt

Geçen ayki örneklerimizin benzerlerine bu ay da devam ediyoruz. Hatırlarsanız sizlere bu ayki yazımızda, Amiga C'de pratik olarak nasıl resim yükleneceğini gösterecektim. Şimdi Amiga'da, resim yükleme olayını bir inceleyelim.

Her Amiga kullanıcısının bildiği gibi Amiga'nın grafik özelliği diğer kişisel bilgisayarlara göre oldukça iyidir. Oynadığınız oyunların grafikleri (ve hızları) buna yeterli bir örnektir sanırım. Ayrıca Amiga'da oldukça iyi grafik çizim programları da mevcut. Bunların başında tabii ki Deluxe Paint geliyor. Acaba biz Deluxe Paint ya da buna benzer bir çizim programında hazırladığımız bir resmi, oyunlarda olduğu gibi ekranımıza istediğimiz gibi getiremez miyiz? Tabii ki getirebiliriz. Aşağıda vermiş olduğum program ile bu mümkün. Aslında Amiga için bu iş oldukça basit bir hale geldi. Özellikle Amos Basic çıktığından bu yana hiçbir enterasanlığı kalmadı diyebilirim. Fakat Amiga C'de ekrana bir resim taşımanın çok püf noktası var. Çünkü ekrana gelen resminizi istediğiniz gibi kontrol etmek size kalıyor. C'de, yüklemek istediğiniz resmin boyutuyla ve renkleriyle istediğiniz gibi oynayabilirsiniz. Hem de resim ekrana gelmeden! Tabii ki size bunu sağlayan bir sistemle, yani IFF (Interchange Format File) sistemiyle. Bu sistemi Electronic Arts firması geliştirmiştir. Zaten Deluxe Paint çizim programı da aynı firmanın ürünüdür. Biraz daha derinlere inelim ve IFF formatının ne olduğunu görelim.

IFF formatının yapı taşı ILBM structure yapısıdır. Bu yapı içerisinde yüklenecek olan resmin bütün özellikleri saklıdır. Bir IFF resmi yüklenirken ilk olarak o resmin Header (başlık) kısmı yüklenir. Bu kısımda çeşitli kısaltmalar ve bu kısaltmaların yanında da uzunluklar saklıdır. Bu bilgiler ILBM structure yapısına aktarılır. Daha sonra resmin esas kısmı yüklenir ve ekrana getirilir.

IFF resim yükleme C dilinde de aynı kademelerden geçmektedir. Şimdi C dilinde IFF kullanabilmemiz için gerekli olan programları bir öğrenelim.

Biz, C'de IFF yükleme işlemini bir program yardımıyla gerçekleştiriyoruz. Tabii eğer siz isterseniz kendiniz de yazabilirsiniz. Ben yazdım. Fakat bence Amerika'yı yeniden keşfetmeye hiç gerek yok. Ne olduğunu öğrenmeniz şimdilik yeterli. Kullanacağımız bu yardımcı program Aztec C V3.6A veya Aztec C V5.0A derleyicilerinin ikinci disketlerindeki 'iff' dosyası içerisinde bulunuyor. Bu dosyanın içerisinde şimdilik bizi ilgilendiren iki dosya var. Bunlar:
JIFF.H: Bu dosyayı derleyicinizdeki 'include' dosyası içine kopyalayın. Jiff.h içerisinde ILBM yapısı ve bazı macrolar tanımlanıyor.
JIFF.O: Bu dosyayı da derleyicinizdeki 'lib' dosyası içine kopyalayın. Jiff.o object dosyası içerisinde ise IFF yüklerken kullanacağınız komutların object halleri bulunuyor. İsterseniz bu komutların kendisini, disketinizdeki iff dosyası içerisindeki jiff.c'ye bakarak görebilirsiniz.

Kopyalama işlemleri de bittikten sonra artık IFF yükleyebilen programlar hazırlayabilirsiniz.

Şimdi aşağıda vermiş olduğum programı yazarak kaydedin ve compile işlemlerini şöyle yapın;

CC +L prog.c 
LN prog.o jiff.o -LC32
Link işlemi sırasında jiff.o objesini de ekliyoruz. Böylece IFF komutları, biz yazmışız gibi ana programımıza bağlanıyor ve tek parça bir program ortaya çıkıyor. Bundan sonra artık program ismimizi yazarak çalışmasını görebiliriz.

Sıra geldi program listemizi açıklamaya. İlk olarak listemizi bir gözden geçirelim;

/* Programming by CENKER OZKURT */
#include <stdio.h>
#include <exec/types.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <jiff.h> /*ILBM yapısı bu dosya içinde tanımlanıyor.*/
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct BitMap *bm;
struct RastPort *rp;
struct ViewPort *vp;
struct Screen *scr;
struct ILBM_info *info; /* IFF yapısı */

struct NewScreen sc={
	0,			/* LeftEdge */
	0,			/* TopEdge */
	320,			/* Width */
	256,			/* Height */
	5,			/* Depth */
	0,			/* DetailPen */
	1,			/* BlockPen */
	NULL,			/* ViewModes */
	CUSTOMSCREEN,		/* Type */
	NULL,			/* Font */
	"Amiga Dunyasi",	/* Default Title */
	NULL,			/* Gadgets */
	NULL,			/* CustomBitMap */
};

char name[30]; 
UBYTE *m=0xbfe001;

main()
{
printf("Gormek istediginiz resmin ismini giriniz ?\n");
scanf("%s",name);

if(open_all()==0) {
  printf("open error!\n");
  return(0);
}

if(load()==0) {
  Move(rp,0,100);
  Text(rp,"Resim bulunamadi!",17);
}

while(*m!=188);

close_all(); 
return(1);
}

palettes() /* resmin renk paleti */
{
int i,r,g,b;

for(i=0;i<=15;i++)
{
  r=info->cmap[3*i]/16;
  g=info->cmap[(3*i)+1]/16;
  b=info->cmap[(3*i)+2]/16;
  SetRGB4(vp,i,r,g,b);
}
}
 
load() /* Iff yükleme rutini */
{
info=read_iff(name,0);
if(info==NULL) return(0);
BltBitMapRastPort(&info->bitmap,0,0,rp,0,0,320,256,0xc0);
free_planes(&info->bitmap);
palettes();
return(1);
}

open_all()
{
IntuitionBase=(struct IntuitionBase*) OpenLibrary("intuition.library",0); 
if(IntuitionBase==NULL) {
  printf("Intuition error!\n");
  return(0); 
}
GfxBase=(struct GfxBase *) OpenLibrary("graphics.library",0); 
if(GfxBase==NULL) {
  printf("graphics error!\n");
  CloseLibrary(GfxBase);
  return(0); 
}
scr=(struct Screen *) OpenScreen(&sc); 
if(scr==NULL) {
  printf("screen error!\n");
  CloseLibrary(GfxBase);
  CloseLibrary(IntuitionBase);
  return(0);
}
rp=&scr->RastPort; 
vp=&scr->ViewPort; 
bm=&scr->BitMap; 
return(1);
}

close_all()
{
CloseScreen(scr); 
CloseLibrary(GfxBase); 
CloseLibrary(IntuitionBase);
}
#include <jiff.h> satırında, Iff içerisinde kullanılan macrolar ve Iff structure yapısı tanımlanıyor. Bu yapı ILBM_info değişkeni olarak kullanılıyor. Yapı içerisindeki değişkenler ise aşağıdaki gibi isimlendirilmiş:
struct BitMapHeader
  {
  UWORD w,h;
  UWORD x,y;
  UBYTE nPlanes;
  UBYTE masking;
  UBYTE compression;
  UBYTE pad1;
  UWORD transparentColor;
  UBYTE xAspect,yAspect;
  WORD pageWidth,pageHeight;
  };

structILBM info
  {
  struct BitMapHeader header;
  UBYTE cmap[MAXCOL*3];
  struct BitMap bitmap;
  };
ILBM_info esas yapıyı oluşturuyor. BitMapHeader ise önceden tanımlanıyor ve içerisinde resmin bilgilerini saklıyor. ILBM_info içerisindeki 'cmap' değişkeninde ise resmin paleti RGB değerleri olarak WORD tipinde saklı. Daha sonra resim datalarının saklandığı bitmap adresleri, BitMap değişkeninde bulunuyor. Aynı zamanda BitMap, ekrana taşırken kullandığımız kaynak değişken özelliğini taşıyor. Main içerisindeki satırlarda ise,
main()
{
printf("Gormek istediginiz resmin ismini giriniz ?\n"); 
scanf("%s",name);
Yüklemek istediğimiz resmin ismi soruluyor ve 'name' değişkenine atılıyor, 'name' değişkeni global olarak önceden tanımlanmıştı.
if(open_all()==0) {
  printf("open error!\n");
  return(0);
}
Open_all() bizim hazırladığımız bir rutin. Bu rutinde library'ler ve ekranımız hazırlanıyor. Eğer hazırlık sırasında bir hata oluşursa, open_all() rutini '0' değeri ile dönerek programdan çıkıyor. Biz de bu değeri kontrol ediyor ve '0' ise 'open error!' mesajı vererek ana programımızdan çıkıyoruz.
if(load()==0) {
  Move(rp,0,100);
  Text(rp,"Resim bulunamadi!",17);
}
Load() rutini de aynı şekilde önceden hazırlamış olduğumuz bir IFF yükleme rutini. Yükleme sırasında bir hata oluşursa yine hatayı kontrol ederek programdan çıkıyoruz.

Ana program içerisinden load() rutinini de çağırdıktan ve resim yüklendikten sonra, sol tuşa basılmışsa programdan close_all() rutini ile çıkıyoruz. Alt rutinler ise şöyle çalışıyor;

load() /* Iff yükleme rutini */
{
info=read_iff(name,0);
if(info==NULL) return(0);
BltBitMapRastPort(&info->bitmap,0,0,rp,0,0,320,256,0xc0);
free_planes(&info->bitmap);
palettes();
return(1);
}
Burada,
info=read_iff(name,0);
satırında yükleme işlemi başlıyor. İşlem bittikten sonra hafızada bir BitMap açılıyor ve esas resim burada saklanıyor. Daha sonra bu resmi,
BltBitMapRastPort(&info->bitmap,0,0,rp,0,0,320,256,0xc0); 
blitter komutu ile ekranımıza taşıyoruz. Tabii ki sonradan otomatik olarak açılmış olan BitMap ekranımızı,
free_planes(&info->bitmap);
satırındaki free_planes() IFF komutu ile kapıyoruz. Ve böylece IFF yükleme işlemi burada sona eriyor. Daha sonra palettes() alt rutinimiz dallanıyoruz,
palettes() /* resmin renk paleti */
{
int i,r,g,b;

for(i=0;i<=15;i++)
{
  r=info->cmap[3*i]/16; 
  g=info->cmap[(3*i)+1]/16; 
  b=info->cmap[(3*i)+2]/16;
  SetRGB4(vp,i,r,g,b);
}
}
Burada RGB değerleri 'info' değişkeni içerisindeki 'cmap' değişkeninde sırası ile R,G,B ve WORD olarak saklanıyor. Bu değerleri SetRGB4() fonksiyonu ile ekran'a atıyoruz. Ve böylece resmin tamamı orijinal özellikleri ile ekrana geliyor.

Ve bu ayki zorlu yolculuğumuz da böylece sona eriyor. Bu sayede artık siz de rahatlıkla resim show programları hazırlayabilirsiniz. Gelecek ay C'de sprite denemeleri üzerinde çalışacağız. Bir ay sonra buluşmak üzere hoşçakalın !...