Yksinkertainen sulatusefekti. Perustuu tuliefektin blur filtteriin. Sisällytin tähän kaksi efektin versiota. Toisessa sulatus on jatkuvaa ja toisessa se tapahtuu vain kerran.
tarvitsee SDL -kirjastot.
Linkki valmiiseen exeen molemmista efekteistä: http://koti.mbnet.fi/peku1/melter.zip
#include "SDL.h"
#include <stdlib.h>
enum {
SCREENWIDTH = 640,
SCREENHEIGHT = 480,
SCREENBPP = 32,
SCREENFLAGS = SDL_ANYFORMAT
};
SDL_Surface* pkuva;
Uint32 buffer[SCREENWIDTH][SCREENHEIGHT]; // puskuri 1
Uint32 buffer2[SCREENWIDTH][SCREENHEIGHT]; // puskuri 2
/*
* Pikseli kohdasta x ja y
*/
Uint32 _fastcall getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 *)p;
default:
return 0; /* shouldn't happen, but avoids warnings */
}
}
void DrawScene(SDL_Surface* surface, SDL_Event* event)
{
// Lukitse pinta, jotta voimme käsitellä pikseleitä suoraan
if ( SDL_MUSTLOCK(surface) ) {
if ( SDL_LockSurface(surface) < 0 ) {
fprintf(stderr, "Can't lock the screen: %s\n", SDL_GetError());
return;
}
}
// KOMMENTOI TÄMÄ, JOS HALUAT KOKEILLA Melter2:N KÄÄNTÖÄ
// haetaan 10 pikselin pituisia viivoja kuvasta 600 kappaletta
for (int i=0; i<600; i++)
{
int xrand, yrand;
xrand = rand() % (SCREENWIDTH - 10);
yrand = rand() % (SCREENHEIGHT - 1);
for (int x=0; x<10; x++)
{
buffer[xrand + x][yrand] = getpixel(pkuva, xrand + x, yrand);
}
}
Uint32 c1, c2, c3, c4;
unsigned int cfr, cfg, cfb;
int siirto;
// käydään koko ruutu läpi
for (int x=1;x<SCREENWIDTH-1;x++)
{
siirto = (int)rand() % 6;
for (int y=1;y<SCREENHEIGHT-siirto;y++)
{
// ympäröivien pikselien keskiarvo
c1 = buffer[x+1][y];
c2 = buffer[x-1][y];
c3 = buffer[x][y+1];
c4 = buffer[x][y-1];
// funktiot, jotka ottavat jokaisen komponentin värin keskiarvon
cfr = (((c1 >> 16) & 0xff) + ((c2 >> 16) & 0xff) + ((c3 >> 16) & 0xff) + ((c4 >> 16) & 0xff)) / 4;
cfg = (((c1 >> 8) & 0xff) + ((c2 >> 8) & 0xff) + ((c3 >> 8) & 0xff) + ((c4 >> 8) & 0xff)) / 4;
cfb = ((c1 & 0xff) + (c2 & 0xff) + (c3 & 0xff) + (c4 & 0xff)) / 4;
// kootaan taas yhteen
buffer2[x][y+siirto] = cfr << 16 | cfg << 8 | cfb;
}
}
// piirretään ruudulle
for (int x=1;x<SCREENWIDTH-1;x++)
for (int y=1;y<SCREENHEIGHT-1;y++)
{
// pointteri oikeaan pikseliin
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * 4; // 4 * 8 = 32(tavut->bitit)
// pikseli ruudulle
*(Uint32 *)p = buffer2[x][y];
// vaihdetaan bufferit
buffer[x][y] = buffer2[x][y];
}
// poistetaan lukitus
if ( SDL_MUSTLOCK(surface) ) {
SDL_UnlockSurface(surface);
}
//päivitä pinta
SDL_UpdateRect(surface, 0, 0, 0, 0);
}
int main(int argc, char* argv[])
{
//initialize systems
SDL_Init(SDL_INIT_VIDEO);
//set our at exit function
atexit(SDL_Quit);
//create a window
SDL_Surface* pSurface = SDL_SetVideoMode ( SCREENWIDTH, SCREENHEIGHT, SCREENBPP, SCREENFLAGS );
pkuva = SDL_LoadBMP("kuva.bmp");
// OTA TÄMÄ POIS KOMMENTEISTA, JOS HALUAT KOKEILLA Melter2:STA
/*for (int x=0;x<=SCREENWIDTH-1;x++)
for (int y=0;y<=SCREENHEIGHT-1;y++)
buffer[x][y] = getpixel(pkuva, x, y);*/
// normi sdl-looppi
SDL_Event event;
for (;;)
{
if ( SDL_PollEvent ( &event ) )
{
if ( event.type == SDL_QUIT ) break;
}
DrawScene(pSurface, &event);
}
// vapautellaan
SDL_FreeSurface(pSurface);
SDL_FreeSurface(pkuva);
return(0);
}Ihan hieno efekti.
// haetaan 10 pikselin pituisia viivoja kuvasta 400 kappaletta
for (int i=0; i<400; i++)
{
for (int x=0; x<10; x++)
{
int xrand, yrand;
xrand = rand() % (SCREENWIDTH - 10) + x;
yrand = rand() % (SCREENHEIGHT - 1);
buffer[xrand][yrand] = getpixel(pkuva, xrand, yrand);
}
}Tuossa on kuitenkin joko kommentissa tai koodissa vikaa. Pisteet ei takuulla osu samalle viivalle, jos kutsut jokaiselle pisteelle uudelleen rand() funkiota :)
Olenpas ollut ajattelematon!
Korjaan tuon heti!
Edit: Sekä koodi, että binaari on nyt päivitetty
Ihan hieno.
Koska (SCREENWIDTH - 1) on nähdäkseni reunimmainen pikseli, pitäisi siinä "// käydään koko ruutu läpi" -kohdassa varmaankin olla (SCREENWIDTH - 2).
for (int x = 1; x <= SCREENWIDTH - 1; x++)
=>
for (int x = 1; x <= SCREENWIDTH - 2; x++)
=> Vielä helpompi näin kokonaisluvuilla mutta täysin samoin toimiva
for (int x = 1; x < SCREENWIDTH - 1; x++)
Lisäksi kriittinen huomautus koodin ulkoasusta: Noihin looppeihin voisi jättää välejä, niinkuin minulla tuossa yllä; OnHyvinVaivalloistaLukeaNoitaPutkeenKirjoitettujaLooppejaKutenEsimerkiksi "for (int x=1;x<=SCREENWIDTH-1;x++)" :D
eniten kyllä huolestuttaa toi kuvan koira, jonka päähän on tungettu laskettelulasit (mitä luultavammin ilman lupaa!) pipokin sillä on.
Hihii, tuo koira on söpö nuo lasit päässä ^^
Hieno efekti. Pitää mun varmaankin vaihtaa vb c++:ssaan jos sillä tollasta saa aikaan.
Wanha kuva :D Hieno efekti.
Se vinee Dll-tiedoston puuttmisesta... (MSVCR70)
http://www.dll-files.com täältä saat :)
Tuo on kyllä ihan perus dll-tiedostoja, jotka kannattaa hankkia. Yleensä ne laitetaan mukaan pakettiin isommissa ohjelmissa, mutta jätin tuon pois tilan säästämiseksi.
Aihe on jo aika vanha, joten et voi enää vastata siihen.