This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenkernel/intern/image.c
Kent Mein 3f2f1571e5 added the following to configure.ac
+case "$target" in
+  *sparc* )
+        AC_DEFINE(SUN_OGL_NO_VERTEX_MACROS,1,[Fix for Sun's GL])
+  ;;
+esac
+

Also added the include to the above .c files.
I'm going to add it to everything in source just haven't gotten that far yet.

Kent
2002-11-25 10:13:52 +00:00

1491 lines
31 KiB
C

/* image.c MIX MODEL
*
* maart 95
*
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <math.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <io.h>
#endif
#include "MEM_guardedalloc.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "DNA_texture_types.h"
#include "DNA_image_types.h"
#include "DNA_packedFile_types.h"
#include "BLI_blenlib.h"
#include "BKE_bad_level_calls.h"
#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_image.h"
#include "BKE_bmfont.h"
#include "BKE_screen.h"
#include "BKE_texture.h"
#include "BKE_packedFile.h"
#include "BKE_library.h"
void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2);
void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2);
float square_rctf(rctf *rf);
float clipx_rctf(rctf *rf, float x1, float x2);
float clipy_rctf(rctf *rf, float y1, float y2);
void boxsample(struct ImBuf *ibuf,
float minx, float miny, float maxx, float maxy,
float *rcol, float *gcol, float *bcol, float *acol);
void boxsampleclip(struct ImBuf *ibuf, rctf *rf, float *rcol,
float *gcol, float *bcol, float *acol);
void filtersample(struct ImBuf *ibuf,
float fx, float fy,
float *rcol, float *gcol, float *bcol, float *acol);
/* If defined: check arguments on call */
/* #define IMAGE_C_ARG_CHECK */
/* Communicate with texture channels. */
extern float Tin, Tr, Tg, Tb, Ta;
int Talpha;
int imaprepeat, imapextend;
/*
*
* Talpha==TRUE betekent: lees alpha uit plaatje. Dit betekent niet dat Ta
* niet gebruikt moet worden, hier kan info over rand van image in staan!
*
*/
void free_image_buffers(Image *ima)
{
int a;
if(ima->ibuf) {
if (ima->ibuf->userdata) {
MEM_freeN(ima->ibuf->userdata);
ima->ibuf->userdata = 0;
}
IMB_freeImBuf(ima->ibuf);
ima->ibuf= 0;
}
if(ima->anim) IMB_free_anim(ima->anim);
ima->anim= 0;
for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
ima->mipmap[a]= 0;
}
free_realtime_image(ima);
}
void free_image(Image *ima)
{
free_image_buffers(ima);
if (ima->packedfile) {
freePackedFile(ima->packedfile);
ima->packedfile = NULL;
}
}
Image *add_image(char *name)
{
Image *ima;
int file, len;
char *libname, str[256], strtest[256];
strcpy(str, name);
BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
file= open(str, O_BINARY|O_RDONLY);
if(file== -1) return 0;
close(file);
/* eerst zoeken naar eenzelfde ima */
ima= G.main->image.first;
while(ima) {
strcpy(strtest, ima->name);
BLI_convertstringcode(strtest, G.sce, G.scene->r.cfra);
if( strcmp(strtest, str)==0 ) {
if(ima->anim==0 || ima->id.us==0) {
strcpy(ima->name, name); /* for stringcode */
ima->id.us++;
ima->ok= 1;
return ima;
}
}
ima= ima->id.next;
}
len= strlen(name);
while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--;
libname= name+len;
ima= alloc_libblock(&G.main->image, ID_IM, libname);
strcpy(ima->name, name);
ima->ok= 1;
ima->xrep= ima->yrep= 1;
return ima;
}
void free_unused_animimages()
{
Image *ima, *nima;
ima= G.main->image.first;
while(ima) {
nima= ima->id.next;
if(ima->id.us==0) {
if(ima->flag & IMA_FROMANIM) free_libblock(&G.main->image, ima);
}
ima= nima;
}
}
/* *********** LEZEN EN SCHRIJVEN ************** */
void makepicstring(char *string, int frame)
{
short i,len;
char num[10], *extension;
if (string==0) return;
extension= "";
strcpy(string, G.scene->r.pic);
BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
len= strlen(string);
/* kan ook: sprintf(num, "%04d", frame); */
i=4-sprintf(num,"%d",frame);
for(;i>0;i--){
string[len]='0';
len++;
}
string[len]=0;
strcat(string,num);
if(G.scene->r.imtype== R_IRIS) {
extension= ".rgb";
}
else if(G.scene->r.imtype==R_IRIZ) {
extension= ".rgb";
}
else if(G.scene->r.imtype==R_PNG) {
extension= ".png";
}
else if(G.scene->r.imtype==R_TARGA) {
extension= ".tga";
}
else if(G.scene->r.imtype==R_RAWTGA) {
extension= ".tga";
}
else if(G.scene->r.imtype==R_JPEG90) {
extension= ".jpg";
}
if(G.scene->r.scemode & R_EXTENSION) strcat(string, extension);
}
/* ******** IMAGWRAPPING INIT ************* */
void converttopremul(struct ImBuf *ibuf)
{
int x, y, val;
char *cp;
if(ibuf==0) return;
if(ibuf->depth==24) { /* alpha op 255 zetten */
cp= (char *)(ibuf->rect);
for(y=0; y<ibuf->y; y++) {
for(x=0; x<ibuf->x; x++, cp+=4) {
cp[3]= 255;
}
}
return;
}
cp= (char *)(ibuf->rect);
for(y=0; y<ibuf->y; y++) {
for(x=0; x<ibuf->x; x++, cp+=4) {
if(cp[3]==0) {
cp[0]= cp[1]= cp[2]= 0;
}
else if(cp[3]!=255) {
val= cp[3];
cp[0]= (cp[0]*val)>>8;
cp[1]= (cp[1]*val)>>8;
cp[2]= (cp[2]*val)>>8;
}
}
}
}
void makemipmap(Image *ima)
{
struct ImBuf *ibuf;
int minsize, curmap=0;
ibuf= ima->ibuf;
minsize= MIN2(ibuf->x, ibuf->y);
while(minsize>3 && curmap<BLI_ARRAY_NELEMS(ima->mipmap)) {
ibuf= IMB_dupImBuf(ibuf);
IMB_filter(ibuf);
ima->mipmap[curmap]= (struct ImBuf *)IMB_onehalf(ibuf);
IMB_freeImBuf(ibuf);
ibuf= ima->mipmap[curmap];
curmap++;
minsize= MIN2(ibuf->x, ibuf->y);
}
}
struct anim *openanim(char * name, int flags)
{
struct anim * anim;
struct ImBuf * ibuf;
anim = IMB_open_anim(name, flags);
if (anim == 0) return(0);
ibuf = IMB_anim_absolute(anim, 0);
if (ibuf == 0) {
printf("anim_absolute 0 failed\n");
IMB_free_anim(anim);
return(0);
}
IMB_freeImBuf(ibuf);
return(anim);
}
int calcimanr(int cfra, Tex *tex)
{
int imanr, len, a, fra, dur;
/* hier (+fie_ima/2-1) zorgt ervoor dat correct wordt gedeeld */
if(tex->frames==0) return 1;
cfra= cfra-tex->sfra+1;
/* cyclic */
if(tex->len==0) len= (tex->fie_ima*tex->frames)/2;
else len= tex->len;
if(tex->imaflag & TEX_ANIMCYCLIC) {
cfra= ( (cfra) % len );
if(cfra < 0) cfra+= len;
if(cfra==0) cfra= len;
}
if(cfra<1) cfra= 1;
else if(cfra>len) cfra= len;
/* omzetten current frame naar current field */
cfra= 2*(cfra);
if(R.flag & R_SEC_FIELD) cfra++;
/* transformeren naar images space */
imanr= (cfra+tex->fie_ima-2)/tex->fie_ima;
if(imanr>tex->frames) imanr= tex->frames;
imanr+= tex->offset;
/* zijn er plaatjes die langer duren? */
for(a=0; a<4; a++) {
if(tex->fradur[a][0]) {
fra= tex->fradur[a][0];
dur= tex->fradur[a][1]-1;
while(dur>0 && imanr>fra) {
imanr--;
dur--;
}
}
}
return imanr;
}
void do_laseroptics_patch(ImBuf *ibuf)
{
char *rt;
float fac;
int a, val;
rt= (char *)ibuf->rect;
a= ibuf->x*ibuf->y;
if(ibuf->flags & IB_fields) a+= a;
while(a--) {
fac= (rt[1]+rt[2]+rt[3])/765.0f;
val= (int)((255.0/0.8)*(fac-0.1));
if(val<0) val= 0; else if(val>255) val= 255;
rt[0]= rt[1]= rt[2]= rt[3]= val;
rt+= 4;
}
}
void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */
{
struct ImBuf * tbuf1, * tbuf2;
if (ibuf == 0) return;
if (ibuf->flags & IB_fields) return;
ibuf->flags |= IB_fields;
if (ibuf->rect) {
/* kopieen aanmaken */
tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0);
tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0);
ibuf->x *= 2;
/* These rectop calls are broken!!! I added a trailing 0 arg... */
IMB_rectop(tbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
IMB_rectop(tbuf2, ibuf, 0, 0, tbuf2->x, 0, 32767, 32767, IMB_rectcpy, 0);
ibuf->x /= 2;
IMB_rectop(ibuf, tbuf1, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
IMB_rectop(ibuf, tbuf2, 0, tbuf2->y, 0, 0, 32767, 32767, IMB_rectcpy, 0);
IMB_freeImBuf(tbuf1);
IMB_freeImBuf(tbuf2);
}
ibuf->y /= 2;
}
void de_interlace_st(struct ImBuf *ibuf) /* standard fields */
{
struct ImBuf * tbuf1, * tbuf2;
if (ibuf == 0) return;
if (ibuf->flags & IB_fields) return;
ibuf->flags |= IB_fields;
if (ibuf->rect) {
/* kopieen aanmaken */
tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0);
tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0);
ibuf->x *= 2;
/* These are brolenm as well... */
IMB_rectop(tbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
IMB_rectop(tbuf2, ibuf, 0, 0, tbuf2->x, 0, 32767, 32767, IMB_rectcpy, 0);
ibuf->x /= 2;
IMB_rectop(ibuf, tbuf2, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0);
IMB_rectop(ibuf, tbuf1, 0, tbuf2->y, 0, 0, 32767, 32767, IMB_rectcpy, 0);
IMB_freeImBuf(tbuf1);
IMB_freeImBuf(tbuf2);
}
ibuf->y /= 2;
}
/*
load_image handles reading the image from disk or from the packedfile.
*/
void load_image(Image * ima, int flags, char *relabase, int framenum)
{
char name[FILE_MAXDIR + FILE_MAXFILE];
if (ima->ibuf == NULL) {
// is there a PackedFile with this image ?;
if (ima->packedfile) {
ima->ibuf = IMB_ibImageFromMemory((int *) ima->packedfile->data, ima->packedfile->size, flags);
} else {
strcpy(name, ima->name);
BLI_convertstringcode(name, relabase, framenum);
ima->ibuf = IMB_loadiffname(name , flags);
}
// check if the image is a font image...
// printf("Checking for font\n");
if (ima->ibuf) {
detectBitmapFont(ima->ibuf);
}
}
}
void ima_ibuf_is_nul(Tex *tex)
{
void (*de_interlacefunc)(struct ImBuf *ibuf);
Image *ima;
int a, fra;
char str[FILE_MAXDIR+FILE_MAXFILE], *cp;
ima= tex->ima;
if(ima==0) return;
waitcursor(1);
strcpy(str, ima->name);
BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
if(tex->imaflag & TEX_STD_FIELD) de_interlacefunc= de_interlace_st;
else de_interlacefunc= de_interlace_ng;
if(tex->imaflag & TEX_ANIM5) {
if(ima->anim==0) ima->anim = openanim(str, IB_cmap | IB_rect);
if (ima->anim) {
ima->lastquality= R.osa;
fra= ima->lastframe-1;
if(fra<0) fra= 0;
ima->ibuf = IMB_anim_absolute(ima->anim, fra);
/* patch ivm textbutton met naam ima (B_NAMEIMA) */
if(ima->ibuf) {
strcpy(ima->ibuf->name, ima->name);
if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf);
}
}
else error("Not an anim");
} else {
// create a packedfile for this image when autopack is on
// for performance (IMB_loadiffname uses mmap) we don't do this by default
if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) {
ima->packedfile = newPackedFile(str);
}
load_image(ima, IB_rect, G.sce, G.scene->r.cfra);
if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf);
ima->lastquality= R.osa;
}
if(ima->ibuf) {
/* stringcodes ook in ibuf. ibuf->name wordt als 'undo' gebruikt (buttons.c) */
strcpy(ima->ibuf->name, ima->name);
if(ima->ibuf->cmap) {
if(tex->imaflag & TEX_ANIM5) {
if(tex->imaflag & TEX_MORKPATCH) {
/**** PATCH OM KLEUR 2 GOED TE KUNNEN ZETTEN MORKRAMIA */
if(ima->ibuf->maxcol > 4) {
cp= (char *)(ima->ibuf->cmap+2);
cp[0]= 0x80;
}
}
IMB_applycmap(ima->ibuf);
IMB_convert_rgba_to_abgr(ima->ibuf->x*ima->ibuf->y, ima->ibuf->rect);
}
converttopremul(ima->ibuf);
}
if(R.osa) {
if(tex->imaflag & TEX_ANTISCALE) {
IMB_clever_double(ima->ibuf);
IMB_antialias(ima->ibuf);
}
else if(tex->imaflag & TEX_ANTIALI) IMB_antialias(ima->ibuf);
}
if(tex->imaflag & TEX_LASOPPATCH) {
do_laseroptics_patch(ima->ibuf);
}
}
if(ima->ibuf==0) ima->ok= 0;
for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
ima->mipmap[a]= 0;
}
if((R.flag & R_RENDERING)==0) waitcursor(0);
}
/* *********** IMAGEWRAPPING ****************** */
int imagewrap(Tex *tex, float *texvec)
{
Image *ima;
struct ImBuf *ibuf;
float fx, fy, val1, val2, val3;
int ofs, x, y;
char *rect;
ima= tex->ima;
if(ima==0 || ima->ok== 0) {
Tin= Ta= Tr= Tg= Tb= 0.0;
return 0;
}
if(ima->ibuf==0) ima_ibuf_is_nul(tex);
if (ima->ok) {
ibuf = ima->ibuf;
if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
ibuf->rect+= (ibuf->x*ibuf->y);
}
if(tex->imaflag & TEX_IMAROT) {
fy= texvec[0];
fx= texvec[1];
}
else {
fx= texvec[0];
fy= texvec[1];
}
x = (int)(fx*ibuf->x);
y = (int)(fy*ibuf->y);
if(tex->extend == TEX_CLIPCUBE) {
if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0 || texvec[2]>1.0) {
Tin= 0;
return 0;
}
}
else if(tex->extend == TEX_CLIP) {
if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) {
Tin= 0;
return 0;
}
}
else {
if(tex->extend==TEX_EXTEND) {
if(x>=ibuf->x) x = ibuf->x-1;
else if(x<0) x= 0;
}
else {
x= x % ibuf->x;
if(x<0) x+= ibuf->x;
}
if(tex->extend==TEX_EXTEND) {
if(y>=ibuf->y) y = ibuf->y-1;
else if(y<0) y= 0;
}
else {
y= y % ibuf->y;
if(y<0) y+= ibuf->y;
}
}
ofs = y * ibuf->x + x;
rect = (char *)( ibuf->rect+ ofs);
Talpha= 0;
if(tex->imaflag & TEX_USEALPHA) {
if(tex->imaflag & TEX_CALCALPHA);
else Talpha= 1;
}
Tr = ((float)rect[0])/255.0f;
Tg = ((float)rect[1])/255.0f;
Tb = ((float)rect[2])/255.0f;
if(tex->nor) {
/* bump: drie samples nemen */
val1= Tr+Tg+Tb;
if(x<ibuf->x-1) {
rect+=4;
val2= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
rect-=4;
}
else val2= val1;
if(y<ibuf->y-1) {
rect+= 4*ibuf->x;
val3= ((float)(rect[0]+rect[1]+rect[2]))/255.0f;
}
else val3= val1;
/* niet x en y verwisselen! */
tex->nor[0]= (val1-val2);
tex->nor[1]= (val1-val3);
}
BRICONRGB;
if(Talpha) Ta= Tin= ((float)rect[3])/255.0f;
else if(tex->imaflag & TEX_CALCALPHA) {
Ta= Tin= MAX3(Tr, Tg, Tb);
}
else Ta= Tin= 1.0;
if(tex->flag & TEX_NEGALPHA) Ta= 1.0f-Ta;
if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
ibuf->rect-= (ibuf->x*ibuf->y);
}
}
if(tex->flag & TEX_COLORBAND) do_colorband(tex->coba);
if(tex->nor) return 3;
else return 1;
}
void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
/* rctf *stack; */
/* short *count; */
/* float x1, x2; */
{
rctf *rf, *newrct;
short a;
a= *count;
rf= stack;
for(;a>0;a--) {
if(rf->xmin<x1) {
if(rf->xmax<x1) {
rf->xmin+= (x2-x1);
rf->xmax+= (x2-x1);
}
else {
if(rf->xmax>x2) rf->xmax= x2;
newrct= stack+ *count;
(*count)++;
newrct->xmax= x2;
newrct->xmin= rf->xmin+(x2-x1);
newrct->ymin= rf->ymin;
newrct->ymax= rf->ymax;
if(newrct->xmin==newrct->xmax) (*count)--;
rf->xmin= x1;
}
}
else if(rf->xmax>x2) {
if(rf->xmin>x2) {
rf->xmin-= (x2-x1);
rf->xmax-= (x2-x1);
}
else {
if(rf->xmin<x1) rf->xmin= x1;
newrct= stack+ *count;
(*count)++;
newrct->xmin= x1;
newrct->xmax= rf->xmax-(x2-x1);
newrct->ymin= rf->ymin;
newrct->ymax= rf->ymax;
if(newrct->xmin==newrct->xmax) (*count)--;
rf->xmax= x2;
}
}
rf++;
}
}
void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
/* rctf *stack; */
/* short *count; */
/* float y1, y2; */
{
rctf *rf, *newrct;
short a;
a= *count;
rf= stack;
for(;a>0;a--) {
if(rf->ymin<y1) {
if(rf->ymax<y1) {
rf->ymin+= (y2-y1);
rf->ymax+= (y2-y1);
}
else {
if(rf->ymax>y2) rf->ymax= y2;
newrct= stack+ *count;
(*count)++;
newrct->ymax= y2;
newrct->ymin= rf->ymin+(y2-y1);
newrct->xmin= rf->xmin;
newrct->xmax= rf->xmax;
if(newrct->ymin==newrct->ymax) (*count)--;
rf->ymin= y1;
}
}
else if(rf->ymax>y2) {
if(rf->ymin>y2) {
rf->ymin-= (y2-y1);
rf->ymax-= (y2-y1);
}
else {
if(rf->ymin<y1) rf->ymin= y1;
newrct= stack+ *count;
(*count)++;
newrct->ymin= y1;
newrct->ymax= rf->ymax-(y2-y1);
newrct->xmin= rf->xmin;
newrct->xmax= rf->xmax;
if(newrct->ymin==newrct->ymax) (*count)--;
rf->ymax= y2;
}
}
rf++;
}
}
float square_rctf(rctf *rf)
/* rctf *rf; */
{
float x, y;
x= rf->xmax- rf->xmin;
y= rf->ymax- rf->ymin;
return (x*y);
}
float clipx_rctf(rctf *rf, float x1, float x2)
/* rctf *rf; */
/* float x1, x2; */
{
float size;
size= rf->xmax - rf->xmin;
if(rf->xmin<x1) {
rf->xmin= x1;
}
if(rf->xmax>x2) {
rf->xmax= x2;
}
if(rf->xmin > rf->xmax) {
rf->xmin = rf->xmax;
return 0.0;
}
else if(size!=0.0) {
return (rf->xmax - rf->xmin)/size;
}
return 1.0;
}
float clipy_rctf(rctf *rf, float y1, float y2)
/* rctf *rf; */
/* float y1, y2; */
{
float size;
size= rf->ymax - rf->ymin;
/* PRINT(f, size); */
if(rf->ymin<y1) {
rf->ymin= y1;
}
if(rf->ymax>y2) {
rf->ymax= y2;
}
/* PRINT(f, size); */
if(rf->ymin > rf->ymax) {
rf->ymin = rf->ymax;
return 0.0;
}
else if(size!=0.0) {
return (rf->ymax - rf->ymin)/size;
}
return 1.0;
}
void boxsampleclip(struct ImBuf *ibuf, rctf *rf, float *rcol,
float *gcol, float *bcol, float *acol) /* return kleur 0.0-1.0 */
/* struct ImBuf *ibuf; */
/* rctf *rf; */
/* float *rcol, *gcol, *bcol, *acol; */
{
/* sample box, is reeds geclipt en minx enz zijn op ibuf size gezet.
* Vergroot uit met antialiased edges van de pixels */
float muly,mulx,div;
int ofs;
int x, y, startx, endx, starty, endy;
char *rect;
startx= (int)floor(rf->xmin);
endx= (int)floor(rf->xmax);
starty= (int)floor(rf->ymin);
endy= (int)floor(rf->ymax);
if(startx < 0) startx= 0;
if(starty < 0) starty= 0;
if(endx>=ibuf->x) endx= ibuf->x-1;
if(endy>=ibuf->y) endy= ibuf->y-1;
if(starty==endy && startx==endx) {
ofs = starty*ibuf->x + startx;
rect = (char *)(ibuf->rect +ofs);
*rcol= ((float)rect[0])/255.0f;
*gcol= ((float)rect[1])/255.0f;
*bcol= ((float)rect[2])/255.0f;
/* alpha is globaal, reeds gezet in functie imagewraposa() */
if(Talpha) {
*acol= ((float)rect[3])/255.0f;
}
}
else {
div= *rcol= *gcol= *bcol= *acol= 0.0;
for(y=starty;y<=endy;y++) {
ofs = y*ibuf->x +startx;
rect = (char *)(ibuf->rect+ofs);
muly= 1.0;
if(starty==endy);
else {
if(y==starty) muly= 1.0f-(rf->ymin - y);
if(y==endy) muly= (rf->ymax - y);
}
if(startx==endx) {
mulx= muly;
if(Talpha) *acol+= mulx*rect[3];
*rcol+= mulx*rect[0];
*gcol+= mulx*rect[1];
*bcol+= mulx*rect[2];
div+= mulx;
}
else {
for(x=startx;x<=endx;x++) {
mulx= muly;
if(x==startx) mulx*= 1.0f-(rf->xmin - x);
if(x==endx) mulx*= (rf->xmax - x);
if(mulx==1.0) {
if(Talpha) *acol+= rect[3];
*rcol+= rect[0];
*gcol+= rect[1];
*bcol+= rect[2];
div+= 1.0;
}
else {
if(Talpha) *acol+= mulx*rect[3];
*rcol+= mulx*rect[0];
*gcol+= mulx*rect[1];
*bcol+= mulx*rect[2];
div+= mulx;
}
rect+=4;
}
}
}
if(div!=0.0) {
div*= 255.0;
*bcol/= div;
*gcol/= div;
*rcol/= div;
if(Talpha) *acol/= div;
}
else {
*rcol= *gcol= *bcol= *acol= 0.0;
}
}
}
void boxsample(struct ImBuf *ibuf,
float minx, float miny, float maxx, float maxy,
float *rcol, float *gcol, float *bcol, float *acol) /* return kleur 0.0-1.0 */
/* struct ImBuf *ibuf; */
/* float minx, miny, maxx, maxy; */
/* float *rcol, *gcol, *bcol, *acol; */
{
/* Sample box, doet clip. minx enz lopen van 0.0 - 1.0 .
* Vergroot uit met antialiased edges van de pixels.
* Als global imaprepeat is gezet, worden
* de weggeclipte stukken ook gesampled.
*/
rctf *rf, stack[8];
float opp, tot, r, g, b, a, alphaclip= 1.0;
short count=1;
rf= stack;
rf->xmin= minx*(ibuf->x);
rf->xmax= maxx*(ibuf->x);
rf->ymin= miny*(ibuf->y);
rf->ymax= maxy*(ibuf->y);
if(imapextend);
else if(imaprepeat) clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x));
else {
alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x));
if(alphaclip<=0.0) {
*rcol= *bcol= *gcol= *acol= 0.0;
return;
}
}
if(imapextend);
else if(imaprepeat) clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y));
else {
alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y));
if(alphaclip<=0.0) {
*rcol= *bcol= *gcol= *acol= 0.0;
return;
}
}
if(count>1) {
tot= *rcol= *bcol= *gcol= *acol= 0.0;
while(count--) {
boxsampleclip(ibuf, rf, &r, &g, &b, &a);
opp= square_rctf(rf);
tot+= opp;
*rcol+= opp*r;
*gcol+= opp*g;
*bcol+= opp*b;
if(Talpha) *acol+= opp*a;
rf++;
}
if(tot!= 0.0) {
*rcol/= tot;
*gcol/= tot;
*bcol/= tot;
if(Talpha) *acol/= tot;
}
}
else {
boxsampleclip(ibuf, rf, rcol, gcol, bcol, acol);
}
if(Talpha==0) *acol= 1.0;
if(alphaclip!=1.0) {
/* this is for laer investigation, premul or not? */
/* *rcol*= alphaclip; */
/* *gcol*= alphaclip; */
/* *bcol*= alphaclip; */
*acol*= alphaclip;
}
}
void filtersample(struct ImBuf *ibuf,
float fx, float fy,
float *rcol, float *gcol, float *bcol, float *acol)
/* return kleur 0.0-1.0 */
/* struct ImBuf *ibuf; */ /* fx en fy tussen 0.0 en 1.0 */
/* float fx, fy; */
/* float *rcol, *gcol, *bcol, *acol; */
{
/* met weighted filter 3x3
* de linker of rechter kolom is altijd 0
* en de bovenste of onderste rij is altijd 0
*/
int fac, fac1, fac2, fracx, fracy, filt[4];
int ix, iy, x4;
unsigned int r=0, g=0, b=0, a=0;
char *rowcol, *rfilt[4];
ix= (int)( 256.0*fx );
fracx= (ix & 255);
ix= (ix>>8);
iy= (int)( 256.0*fy );
fracy= (iy & 255);
iy= (iy>>8);
if(ix>=ibuf->x) ix= ibuf->x-1;
if(iy>=ibuf->y) iy= ibuf->y-1;
rowcol= (char *)(ibuf->rect+ iy*ibuf->x +ix);
rfilt[0]= rfilt[1]= rfilt[2]= rfilt[3]= rowcol;
x4= 4*ibuf->x;
if(fracx<128) {
if(ix>0) {
rfilt[0]-= 4;
rfilt[2]-=4;
}
else if(imaprepeat) {
rfilt[0]+= x4-4;
rfilt[2]+= x4-4;
}
if(fracy<128) {
/* geval linksonder */
fac1= 128+fracy;
fac2= 128-fracy;
if(iy>0) {
rfilt[3]-= x4;
rfilt[2]-= x4;
}
else if(imaprepeat) {
fac= x4*(ibuf->y-1) ;
rfilt[3]+= fac;
rfilt[2]+= fac;
}
}
else {
/* geval linksboven */
fac2= 384-fracy;
fac1= fracy-128;
if(iy<ibuf->y-1) {
rfilt[1]+= x4;
rfilt[0]+= x4;
}
else if(imaprepeat) {
fac= x4*(ibuf->y-1) ;
rfilt[1]-= fac;
rfilt[0]-= fac;
}
}
filt[1]=filt[3]= 128+ fracx;
filt[0]=filt[2]= 128- fracx;
filt[0]*= fac1;
filt[1]*= fac1;
filt[2]*= fac2;
filt[3]*= fac2;
}
else {
if(fracy<128) {
/* geval rechtsonder */
fac1= 128+fracy;
fac2= 128-fracy;
if(iy>0) {
rfilt[3]-= x4;
rfilt[2]-= x4;
}
else if(imaprepeat) {
fac= x4*(ibuf->y-1) ;
rfilt[3]+= fac;
rfilt[2]+= fac;
}
}
else {
/* geval rechtsboven */
fac2= 384-fracy;
fac1= fracy-128;
if(iy<ibuf->y-1) {
rfilt[1]+= x4;
rfilt[0]+= x4;
}
else if(imaprepeat) {
fac= x4*(ibuf->y-1) ;
rfilt[1]-= fac;
rfilt[0]-= fac;
}
}
filt[0]=filt[2]= 384-fracx;
filt[1]=filt[3]= fracx-128;
filt[0]*= fac1;
filt[1]*= fac1;
filt[2]*= fac2;
filt[3]*= fac2;
if(ix<ibuf->x-1) {
rfilt[1]+= 4;
rfilt[3]+=4;
}
else if(imaprepeat) {
rfilt[1]-= x4-4;
rfilt[3]-= x4-4;
}
}
for(fac=3; fac>=0; fac--) {
rowcol= rfilt[fac];
r+= filt[fac]*rowcol[0];
g+= filt[fac]*rowcol[1];
b+= filt[fac]*rowcol[2];
if(Talpha) a+= filt[fac]*rowcol[3]; /* alpha is globaal */
}
*rcol= ((float)r)/16777216.0f;
*gcol= ((float)g)/16777216.0f;
*bcol= ((float)b)/16777216.0f;
if(Talpha) *acol= ((float)a)/16777216.0f;
}
int imagewraposa(Tex *tex, float *texvec, float *dxt, float *dyt)
{
struct Image *ima;
struct ImBuf *ibuf, *previbuf;
float fx, fy, minx, maxx, miny, maxy, dx, dy, fac1, fac2, fac3, fac4;
float maxd, pixsize, val1, val2, val3;
int curmap;
#ifdef IMAGE_C_ARG_CHECK
if (!tex) {
printf("imagewraposa: null pointer to texture\n");
}
#endif
ima= tex->ima;
#ifdef IMAGE_C_ARG_CHECK
if (!ima) {
printf("imagewraposa: null pointer to image\n");
}
#endif
Tin= Ta= Tr= Tg= Tb= 0.0;
if(ima==0 || ima->ok== 0) {
return 0;
}
if(ima->ibuf==0) ima_ibuf_is_nul(tex);
if (ima->ok) {
if(tex->imaflag & TEX_MIPMAP) {
if(ima->mipmap[0]==0) makemipmap(ima);
}
ibuf = ima->ibuf;
if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
ibuf->rect+= (ibuf->x*ibuf->y);
}
Talpha= 0;
if(tex->imaflag & TEX_USEALPHA) {
if(tex->imaflag & TEX_CALCALPHA);
else Talpha= 1;
}
if(tex->imaflag & TEX_IMAROT) {
fy= texvec[0];
fx= texvec[1];
}
else {
fx= texvec[0];
fy= texvec[1];
}
if(ibuf->flags & IB_fields) {
if(R.r.mode & R_FIELDS) { /* field render */
if(R.flag & R_SEC_FIELD) { /* correctie voor tweede field */
/* fac1= 0.5/( (float)ibuf->y ); */
/* fy-= fac1; */
}
else { /* eerste field */
fac1= 0.5f/( (float)ibuf->y );
fy+= fac1;
}
}
}
/* pixel coordinaten */
minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] );
maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] );
miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] );
maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] );
/* tex_sharper afgeschaft */
minx= tex->filtersize*(maxx-minx)/2.0f;
miny= tex->filtersize*(maxy-miny)/2.0f;
if(tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
if(minx>0.25) minx= 0.25;
else if(minx<0.00001f) minx= 0.00001f; /* zijvlakken van eenheidskubus */
if(miny>0.25) miny= 0.25;
else if(miny<0.00001f) miny= 0.00001f;
/* repeat en clip */
/* let op: imaprepeat is globale waarde (zie boxsample) */
imaprepeat= (tex->extend==TEX_REPEAT);
imapextend= (tex->extend==TEX_EXTEND);
if(tex->extend == TEX_CLIPCUBE) {
if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0 || texvec[2]<-1.0 || texvec[2]>1.0) {
Tin= 0;
return 0;
}
}
else if(tex->extend == TEX_CLIP) {
if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0) {
Tin= 0.0;
return 0;
}
}
else {
if(tex->extend==TEX_EXTEND) {
if(fx>1.0) fx = 1.0;
else if(fx<0.0) fx= 0.0;
}
else {
if(fx>1.0) fx -= (int)(fx);
else if(fx<0.0) fx+= 1-(int)(fx);
}
if(tex->extend==TEX_EXTEND) {
if(fy>1.0) fy = 1.0;
else if(fy<0.0) fy= 0.0;
}
else {
if(fy>1.0) fy -= (int)(fy);
else if(fy<0.0) fy+= 1-(int)(fy);
}
}
/* keuze: */
if(tex->imaflag & TEX_MIPMAP) {
dx= minx;
dy= miny;
maxd= MAX2(dx, dy);
if(maxd>0.5) maxd= 0.5;
pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y);
curmap= 0;
previbuf= ibuf;
while(curmap<BLI_ARRAY_NELEMS(ima->mipmap) && ima->mipmap[curmap]) {
if(maxd < pixsize) break;
previbuf= ibuf;
ibuf= ima->mipmap[curmap];
pixsize= 1.0f / (float)MIN2(ibuf->x, ibuf->y); /* hier stond 1.0 */
curmap++;
}
if(previbuf!=ibuf || (tex->imaflag & TEX_INTERPOL)) {
/* minmaal 1 pixel sampelen */
if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x;
if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y;
}
if(tex->nor) {
/* beetje extra filter */
minx*= 1.35f;
miny*= 1.35f;
boxsample(ibuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta);
val1= Tr+Tg+Tb;
boxsample(ibuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
val2= fac1+fac2+fac3;
boxsample(ibuf, fx-2.0f*minx, fy-miny, fx+minx, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4);
val3= fac1+fac2+fac3;
if(previbuf!=ibuf) { /* interpoleren */
boxsample(previbuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
/* rgb berekenen */
dx= 2.0f*(pixsize-maxd)/pixsize;
if(dx>=1.0f) {
Ta= fac4; Tb= fac3;
Tg= fac2; Tr= fac1;
}
else {
dy= 1.0f-dx;
Tb= dy*Tb+ dx*fac3;
Tg= dy*Tg+ dx*fac2;
Tr= dy*Tr+ dx*fac1;
if(Talpha) Ta= dy*Ta+ dx*fac4;
}
val1= dy*val1+ dx*(fac1+fac2+fac3);
boxsample(previbuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
val2= dy*val2+ dx*(fac1+fac2+fac3);
boxsample(previbuf, fx-2.0f*minx, fy-miny, fx+minx, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4);
val3= dy*val3+ dx*(fac1+fac2+fac3);
}
/* niet x en y verwisselen! */
tex->nor[0]= (val1-val2);
tex->nor[1]= (val1-val3);
}
else {
maxx= fx+minx;
minx= fx-minx;
maxy= fy+miny;
miny= fy-miny;
boxsample(ibuf, minx, miny, maxx, maxy, &Tr, &Tg, &Tb, &Ta);
if(previbuf!=ibuf) { /* interpoleren */
boxsample(previbuf, minx, miny, maxx, maxy, &fac1, &fac2, &fac3, &fac4);
fx= 2.0f*(pixsize-maxd)/pixsize;
if(fx>=1.0) {
Ta= fac4; Tb= fac3;
Tg= fac2; Tr= fac1;
} else {
fy= 1.0f-fx;
Tb= fy*Tb+ fx*fac3;
Tg= fy*Tg+ fx*fac2;
Tr= fy*Tr+ fx*fac1;
if(Talpha) Ta= fy*Ta+ fx*fac4;
}
}
}
}
else {
if((tex->imaflag & TEX_INTERPOL)) {
/* minmaal 1 pixel sampelen */
if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x;
if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y;
}
if(tex->nor) {
/* beetje extra filter */
minx*= 1.35f;
miny*= 1.35f;
boxsample(ibuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta);
val1= Tr+Tg+Tb;
boxsample(ibuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4);
val2= fac1+fac2+fac3;
boxsample(ibuf, fx-2.0f*minx, fy-miny, fx+miny, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4);
val3= fac1+fac2+fac3;
/* niet x en y verwisselen! */
tex->nor[0]= (val1-val2);
tex->nor[1]= (val1-val3);
}
else {
boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta);
}
}
BRICONRGB;
if(tex->imaflag & TEX_CALCALPHA) {
Ta= Tin= MAX3(Tr, Tg, Tb);
}
else Tin= Ta;
if(tex->flag & TEX_NEGALPHA) Ta= 1.0f-Ta;
if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
ibuf->rect-= (ibuf->x*ibuf->y);
}
}
else {
Tin= 0.0f;
return 0;
}
if(tex->flag & TEX_COLORBAND) do_colorband(tex->coba);
if(tex->nor) return 3;
else return 1;
}