Effetto "old photo" su gimp
Moderatore: Staff
Regole del forum
1) Rispettare le idee altrui.
2) Evitare le offese dirette.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.
La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
1) Rispettare le idee altrui.
2) Evitare le offese dirette.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.
La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
-
sir_alex
- Linux 3.x

- Messaggi: 735
- Iscritto il: lun 21 mar 2005, 0:00
- Kernel: 2.6.35-22
- Desktop: KDE4
- Distribuzione: Ubuntu
- Località: Milano - Corbola (RO)
- Contatta:
Effetto "old photo" su gimp
Sto un po' sperimentando con l'effetto "old photo" di gimp, fondamentalmente un effetto seppia... una cosa secondo me sarebbe carina ma non ho la più vaga idea di come farla (e non so come scriverla in inglese per fare una ricerca su google): avete presente le vecchie foto, se sono piegate da tanto tempo si formano delle "crepe" nella superficie, che associate all'effetto seppia secondo me sarebbero molto carine (chiaramente 2 o 3, non un'esagerazione), qualche appassionato di fotoritocco saprebbe come farle?
- DanBadJar
- Linux 4.x

- Messaggi: 1027
- Iscritto il: ven 28 lug 2006, 19:27
- Nome Cognome: Daniele Malavasi
- Slackware: 13.1
- Kernel: 2.6.34.1
- Desktop: XFCE - Gnome
- Località: Bologna
- Contatta:
Io di ste cose non ci capisco una mazza, però si è parlato di Gimp e dei suoi manuali in un altro post: viewtopic.php?t=19674&highlight=manuali+gimp
Vedi se magari c'è qualcosa che cerchi
Vedi se magari c'è qualcosa che cerchi
Credo che quello che vuoi farlo sia fondamentalmente una operazione di
Inpainting / resynthesizing
Trovi degli ottimi plugin di gimp perfettamente funzionanti.
A questo link trovi il sorgente di quello che uso io
http://twiki.cis.rit.edu/bin/view/Peopl ... impResynth
Inpainting / resynthesizing
Trovi degli ottimi plugin di gimp perfettamente funzionanti.
A questo link trovi il sorgente di quello che uso io
http://twiki.cis.rit.edu/bin/view/Peopl ... impResynth
-
Feste
- Linux 2.x

- Messaggi: 388
- Iscritto il: ven 21 ott 2005, 14:24
- Slackware: 13
- Desktop: KDE 4.2.4
- Località: /home/feste
carocco ha scritto: http://twiki.cis.rit.edu/bin/view/Peopl ... impResynth
Error
Your IP address xx.xx.xxx.xxx is black listed at the TWiki web site due to excessive access or suspicious activities
Non ho capito la natura del messaggio di Feste.
Comunque se volete posto qui il codice
Comunque se volete posto qui il codice
Codice: Seleziona tutto
/*
The Resynthesizer - A GIMP plug-in for resynthesizing textures
Copyright (C) 2000 Paul Francis Harrison
Copyright (C) 2002 Laurent Despeyroux
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.
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
Original GIMP plug-in stripped for use in IDL by Adam Goodenough Feb, 2004
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <glib.h>
//Number of patches in leaf node of kd-tree
#define LEAF_SIZE 16
/* Radius of neighbourhood in pixels, originaly was 3 : arbitrarily set */
#define RADIUS_OF_NEIGHBOURHOOD_IN_PIXELS 3
/* Utility classes ===================================================== */
//Pixel channel type
typedef unsigned int Pixelel;
typedef int bool;
const bool true = 1, false = 0;
//Intersperse the bits from several bytes (used to sort colors
// allowing a fairly primitive quantization)
/* Optimisation by Laurent Despeyroux */
uint entwine(Pixelel *data, int n_el) {
int i,j,k,l;
uint result = 0;
for(i=0,k=1,l=0;i<8;i++,k*=2)
for(j=0;j<n_el;j++,l++)
if (data[j]&k)
result += 1 << l;
return result;
}
//Structure to hold an "entwine"ified pixels
typedef struct {
int x,y;
uint twine;
} Twine_list_item;
int twine_list_item_sorter(const void *a, const void *b) {
if ( ((Twine_list_item*)a)->twine < ((Twine_list_item*)b)->twine)
return -1;
else if ( ((Twine_list_item*)a)->twine > ((Twine_list_item*)b)->twine)
return 1;
else
return 0;
}
typedef struct {
int x,y;
} Coordinates;
/***************************/
/***************************/
/*** Entropy_accumulator ***/
/***************************/
/***************************/
//Structure+functions used to calculate the number of bits required to
//encode some normally distributed numbers
typedef struct {
uint *x;
uint *x_squared;
int n_els, n;
} Entropy_accumulator;
Entropy_accumulator *entropy_accumulator_new(int n_els) {
Entropy_accumulator *neo = g_new(Entropy_accumulator,1);
neo->n_els = n_els;
neo->x = g_new(uint,n_els);
neo->x_squared = g_new(uint,n_els);
return neo;
}
void entropy_accumulator_free(Entropy_accumulator *e) {
g_free(e->x);
g_free(e->x_squared);
g_free(e);
}
void entropy_accumulator_calculate(Entropy_accumulator *e,
double *bits,double *entropy) {
int i;
if (e->n <= 1) {
*entropy = (double)(e->n_els)*sizeof(Pixelel)*8.0;
*bits = e->n*(*entropy);
return;
}
*entropy = *bits = 0.0;
for(i=0;i<e->n_els;i++) {
double mu = (double)(e->x[i]) / e->n;
double sigma, L;
double sum_squares = e->x_squared[i]-e->x[i]*mu;
if (sum_squares < e->n-1)
sum_squares = e->n-1;
sigma = sqrt( sum_squares / (e->n-1) );
L =
e->n/2.0*log(2*3.1415926535) + e->n/2.0*log(sigma*sigma) +
1.0/(2.0*sigma*sigma)*sum_squares;
*bits += log(256)+log(sigma)+L+
0.5*log((double)(e->n)*e->n/(2.0*pow(sigma,6.0)))
-0.5*log(12)+0.5;
*entropy += 0.5*log(2*3.14159265)+0.5+log(sigma);
}
//Convert from nits to bits
*bits /= log(2);
*entropy /= log(2);
}
void entropy_accumulator_clear(Entropy_accumulator *e) {
int i;
for(i=0;i<e->n_els;i++) {
e->x[i] = 0;
e->x_squared[i] = 0;
}
e->n = 0;
}
void entropy_accumulator_add(Entropy_accumulator *e, Pixelel *data) {
int i;
for(i=0;i<e->n_els;i++) {
e->x[i] += data[i];
e->x_squared[i] += (uint)(data[i])*(uint)(data[i]);
}
e->n++;
}
/**************/
/**************/
/*** Bitmap ***/
/**************/
/**************/
//Bitmap class with three dimensions (width, height, number of channels)
typedef struct {
int width, height, depth, element_size;
void *data;
} Bitmap;
Bitmap *bitmap_new(int element_size) {
Bitmap *neo = g_new(Bitmap,1);
neo->element_size = element_size;
neo->data = 0;
return neo;
}
void bitmap_free(Bitmap *b) {
g_free(b->data);
g_free(b);
}
void bitmap_size(Bitmap *b, int w,int h,int d) {
b->width = w;
b->height = h;
b->depth = d;
g_free(b->data);
b->data = g_malloc(w*h*d*b->element_size);
}
#define bitmap_at(b,type,x,y) \
( (type*)((b)->data)+((x)+(y)*(b)->width)*(b)->depth )
//Structure used to hold information about pixels in the output
typedef struct {
bool use;
bool done;
int priority;
int heap_index;
} Status;
/************/
/************/
/*** Heap ***/
/************/
/************/
//Heap used to prioritize the selection of pixels in the output
typedef struct {
Status **data;
int n_els;
} Heap;
void heap_put(Heap *h, Status *item,int index) {
h->data[index] = item;
if (item)
item->heap_index = index;
}
Heap *heap_new(Status *items,int n_items) {
int i;
Heap *h = g_new(Heap,1);
h->n_els = n_items;
h->data = g_new(Status*,n_items);
for(i=0;i<n_items;i++)
heap_put(h,items+i,i);
return h;
}
void heap_free(Heap *h) {
g_free(h->data);
g_free(h);
}
int heap_parent(int i) { return (i+1)/2-1; }
int heap_left_child(int i) { return (i+1)*2-1; }
int heap_right_child(int i) { return (i+1)*2; }
void heap_promote(Heap *h, Status *item) {
int i = item->heap_index;
int heap_parent_i ;
while(i > 0 &&
(!h->data[heap_parent_i=((i+1)/2-1)] ||
h->data[heap_parent_i]->priority < item->priority))
{
/* heap_put(h, h->data[heap_parent_i],i); */ /* the 2 next lines are the transcription of this call inline L.D. */
if ((h->data[i] = h->data[heap_parent_i]))
h->data[heap_parent_i]->heap_index = i;
i = heap_parent_i;
}
heap_put(h, item, i);
}
void heap_become_heapish(Heap *h) {
int i;
for(i=0;i<h->n_els;i++)
if (h->data[i]->done)
h->data[i] = 0;
else
heap_promote(h, h->data[i]);
}
Status *heap_pop_top(Heap *h) {
Status *top = h->data[0];
int heap_right_child_i ;
int i=0;
for(;;) {
int next = heap_left_child(i);
if (next >= h->n_els) {
/*heap_put(h, 0,i);*/ /* the next line is the transcription of this call inline L.D. */
h->data[i] = 0;
break;
}
if ((heap_right_child_i=heap_right_child(i)) < h->n_els &&
h->data[heap_right_child_i] != NULL &&
(!h->data[next] ||
h->data[next]->priority < h->data[heap_right_child_i]->priority))
next = heap_right_child_i;
/* heap_put(h,h->data[next],i); */ /* the 2 next lines are the transcription of this call inline L.D. */
if ((h->data[i] = h->data[next]))
h->data[next]->heap_index = i;
i = next;
if (!h->data[i])
break;
}
return top;
}
/******************/
/******************/
/*** KDTREE ***/
/******************/
/******************/
// k-d trees are a way to do fast(ish) closest vector
// searches
typedef struct {
int offset_no;
Pixelel value;
} Pattern;
typedef struct {
int x,y,el, offset;
uint weight;
//So we can sort from largest to smallest weight
// (provides a good speedup as distance calculations can often be aborted earlier)
//bool operator < (const Offset &other) const { return weight > other.weight; }
} Offset;
int offset_sorter(const void *a, const void *b) {
if ( ((Offset*)a)->weight > ((Offset*)b)->weight)
return -1;
else if ( ((Offset*)a)->weight < ((Offset*)b)->weight)
return 1;
else
return 0;
}
/************/
/************/
/*** Tree ***/
/************/
/************/
struct _Node;
typedef struct {
struct _Node *node;
int best_dist;
//bool operator < (const Queue_item &other) const {
// return best_dist > other.best_dist;
//}
} Queue_item;
// Globals to avoid passing around these things incessantly
// Array of Offset
GArray *Offsets;
// Array of Pattern
GArray *Patterns;
//More globals... array of Queue_item
GArray *node_queue;
int node_queue_count;
int cutoff_dist;
Pixelel *best;
void set_up_tree_globals() {
Offsets = g_array_new(FALSE,FALSE,sizeof(Offset));
Patterns = g_array_new(FALSE,FALSE,sizeof(Pattern));
node_queue = g_array_new(FALSE,FALSE,sizeof(Queue_item));
}
void clean_up_tree_globals() {
g_array_free(Offsets,TRUE);
g_array_free(Patterns,TRUE);
g_array_free(node_queue,TRUE);
}
void node_queue_upheap(int i) {
Queue_item item = g_array_index(node_queue,Queue_item,i);
for(;;) {
int parent;
if (i == 0)
break;
parent = heap_parent(i);
if (g_array_index(node_queue,Queue_item,parent).best_dist <
item.best_dist)
break;
g_array_index(node_queue,Queue_item,i) =
g_array_index(node_queue,Queue_item,parent);
i = parent;
}
g_array_index(node_queue,Queue_item,i) = item;
}
void node_queue_enqueue(Queue_item item) {
if (node_queue_count == node_queue->len)
g_array_set_size(node_queue,(node_queue->len?node_queue->len*2:1));
g_array_index(node_queue,Queue_item,node_queue_count++) = item;
node_queue_upheap(node_queue_count-1);
}
void node_queue_pop_top() {
int i = 0;
for(;;) {
int child,right_child;
child = heap_left_child(i);
if (child >= node_queue_count)
break;
right_child = heap_right_child(i);
if (right_child < node_queue_count &&
g_array_index(node_queue,Queue_item,right_child).best_dist <
g_array_index(node_queue,Queue_item,child).best_dist)
child = right_child;
g_array_index(node_queue,Queue_item,i) =
g_array_index(node_queue,Queue_item,child);
i = child;
}
g_array_index(node_queue,Queue_item,i) =
g_array_index(node_queue,Queue_item,--node_queue_count);
node_queue_upheap(i);
}
typedef struct {
Pixelel min, max;
} Bound;
struct _Node {
gboolean is_leaf;
Bound *bounds;
union {
struct {
Pixelel **patches;
int n_patches;
} leaf;
struct {
struct _Node *left_child, *right_child;
} inner;
} data;
};
typedef struct _Node Node;
void node_free(Node *node) {
g_free(node->bounds);
if (node->is_leaf)
g_free(node->data.leaf.patches);
else {
node_free(node->data.inner.left_child);
node_free(node->data.inner.right_child);
}
g_free(node);
}
void node_add_to_queue(Node *n)
{
Queue_item item;
int i, dist = 0;
for(i=0;i < Patterns->len;i++)
{
int offset_no = g_array_index(Patterns,Pattern,i).offset_no;
if (g_array_index(Patterns,Pattern,i).value < n->bounds[offset_no].min)
{
dist += g_array_index(Offsets,Offset,offset_no).weight *
(n->bounds[offset_no].min-g_array_index(Patterns,Pattern,i).value);
if (dist >= cutoff_dist)
return;
}
else
if (g_array_index(Patterns,Pattern,i).value >
n->bounds[offset_no].max)
{
dist += g_array_index(Offsets,Offset,offset_no).weight *
(g_array_index(Patterns,Pattern,i).value-n->bounds[offset_no].max);
if (dist >= cutoff_dist)
return;
}
} /* for i < Patterns->len */
item.node = n;
item.best_dist = dist;
node_queue_enqueue(item);
}
void node_do_it(Node *n)
{
if (n->is_leaf)
{
int i,j;
for(i=0;i<n->data.leaf.n_patches;i++)
{
int dist = 0;
for(j=0;j<Patterns->len;j++)
{
int offset_no = g_array_index(Patterns,Pattern,j).offset_no;
dist += g_array_index(Offsets,Offset,offset_no).weight *
abs((int)(n->data.leaf.patches
[i][g_array_index(Offsets,Offset,offset_no).offset]) -
(int)(g_array_index(Patterns,Pattern,j).value));
if (dist > cutoff_dist)
goto skip;
}
best = n->data.leaf.patches[i];
cutoff_dist = dist;
skip: ;
}
}
else
{
node_add_to_queue(n->data.inner.left_child);
node_add_to_queue(n->data.inner.right_child);
}
}
Pixelel *query_tree(Node *tree) {
//Clear the pq
node_queue_count = 0;
cutoff_dist = 1<<30;
node_do_it(tree);
while(node_queue_count) {
Queue_item item = g_array_index(node_queue,Queue_item,0);
if (item.best_dist > cutoff_dist)
break;
node_queue_pop_top();
node_do_it(item.node);
}
return best;
}
Node *build_tree(Pixelel **items,int n_items) {
int i,j;
Node *node = g_new(Node,1);
node->is_leaf = n_items <= LEAF_SIZE;
if (node->is_leaf) {
node->data.leaf.patches = g_new(Pixelel*,n_items);
node->data.leaf.n_patches = n_items;
for(i=0;i<n_items;i++)
node->data.leaf.patches[i] = items[i];
}
node->bounds = g_new(Bound,Offsets->len);
for(i=0;i<Offsets->len;i++) {
node->bounds[i].min = 255;
node->bounds[i].max = 0;
}
for(i=0;i<n_items;i++)
for(j=0;j<Offsets->len;j++) {
int offset = g_array_index(Offsets,Offset,j).offset;
if (items[i][offset] < node->bounds[j].min)
node->bounds[j].min = items[i][offset];
if (items[i][offset] > node->bounds[j].max)
node->bounds[j].max = items[i][offset];
}
if (!node->is_leaf) {
int best = 0;
int best_offset, lower, upper, start_upper, pivot;
Pixelel *temp;
for(i=1;i<Offsets->len;i++)
if (g_array_index(Offsets,Offset,i).weight*
(node->bounds[i].max-node->bounds[i].min) >
g_array_index(Offsets,Offset,best).weight*
(node->bounds[best].max-node->bounds[best].min))
best = i;
best_offset = g_array_index(Offsets,Offset,best).offset;
lower=0;
upper=n_items-1;
for(;;) {
Pixelel p_val = items[lower][best_offset];
start_upper = lower+1;
for(i=lower+1;i<=upper;i++)
if (items[i][best_offset] < p_val) {
Pixelel *temp = items[i];
items[i] = items[start_upper];
items[start_upper] = temp;
start_upper++;
}
pivot = start_upper-1;
temp = items[lower];
items[lower] = items[pivot];
items[pivot] = temp;
if (pivot == n_items/2)
break;
if (pivot < n_items/2)
lower = pivot+1;
else
upper = pivot-1;
}
node->data.inner.left_child =
build_tree(items,n_items/2);
node->data.inner.right_child =
build_tree(items+n_items/2,n_items-n_items/2);
}
return node;
}
/******************/
/******************/
/*** Parameters ***/
/******************/
/******************/
typedef struct {
bool h_tile, v_tile;
gint32 corpus_id, input_map_id, output_map_id;
double random_weight, map_weight;
} Parameters;
bool wrap_or_clip(Parameters *parameters, Bitmap *image, int *xx,int *yy)
{ /* optimisation by Laurent Despeyroux, not important */
if (*xx < 0)
{
if (parameters->h_tile)
*xx += image->width;
else
return false;
}
else
{
if (*xx >= image->width)
{
if (parameters->h_tile)
*xx -= image->width;
else
return false;
}
}
if (*yy < 0)
{
if (parameters->v_tile)
*yy += image->height;
else
return false;
}
else
{
if (*yy >= image->height)
{
if (parameters->v_tile)
*yy -= image->height;
else
return false;
}
}
return true;
}
/* ------------------------------------------------------------------ */
/* */
/* Here is the most important function : the one that does the work ! */
/* */
/* ------------------------------------------------------------------ */
static void run(void)
{
int i,j,k,l,x,y;
Parameters parameters;
int input_bytes, map_bytes, map_pos, random_bytes, random_pos, bytes,
n_pixels, n_corpus_pixels, patch_radius;
Bitmap *status, *weights;
GArray *neighbours;
Heap *heap;
int weight_sum_len;
double *weight_sum;
Node *tree;
/* ----begin---- */
srand(time(0));
/* Setup parameters */
parameters.corpus_id = 2;
parameters.input_map_id = -1;
parameters.output_map_id = -1;
parameters.v_tile = false;
parameters.h_tile = false;
parameters.random_weight = 0.25;
parameters.map_weight = 0.75;
input_bytes = 3;
map_bytes = 0;
map_pos = input_bytes;
random_bytes = 1;
random_pos = map_pos + map_bytes;
bytes = random_pos + random_bytes;
status = bitmap_new(sizeof(Status));
//Have done this output pixel yet?, pixel priority
weights = bitmap_new(sizeof(int));
//Weighting given to neighbours when a pixel is added
patch_radius = RADIUS_OF_NEIGHBOURHOOD_IN_PIXELS ;
neighbours = g_array_new(FALSE,FALSE,sizeof(Coordinates));
/* Choose which neighbours to use */
{
int radius;
for(radius=1;radius<=patch_radius;radius++) {
for(i=0;i<radius*2;i++) {
Coordinates c;
c.x = -radius+i;
c.y = radius;
g_array_append_val(neighbours,c);
c.x = radius;
c.y = radius-i;
g_array_append_val(neighbours,c);
c.x = radius-i;
c.y = -radius;
g_array_append_val(neighbours,c);
c.x = -radius;
c.y = -radius+i;
g_array_append_val(neighbours,c);
}
}
}
/************MYMASK************/
Bitmap *mymask = bitmap_new(sizeof(Pixelel));
bitmap_size(mymask, 32, 32, 1);
int xi,yi;
for(yi=0;yi<mymask->height;yi++)
for(xi=0;xi<mymask->width;xi++) {
if ( xi >= 12 &&
xi <= 23 &&
yi >= 12 &&
yi <= 19){
((Pixelel*)mymask->data)[yi*mymask->width+xi] = 255;
}
else ((Pixelel*)mymask->data)[yi*mymask->width+xi] = 0;
}
/************MYCORPUS************/
Bitmap *mycorpus = bitmap_new(sizeof(Pixelel));
bitmap_size(mycorpus, 32, 32, 4);
for(yi=0;yi<mycorpus->height;yi++)
for(xi=0;xi<mycorpus->width;xi++) {
if ( xi >= 12 &&
xi <= 23 &&
yi >= 12 &&
yi <= 19){
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4] = 255;
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+1] = 128;
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+2] = 64;
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+3] = 0;
}
else {
if (xi % 8 < 4){
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4] = 255;
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+1] = 128;
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+2] = 64;
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+3] = 0;
} else {
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4] = 64;
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+1] = 128;
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+2] = 255;
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+3] = 0;
}}
}
/************MYDATA************/
Bitmap *mydata = bitmap_new(sizeof(Pixelel));
bitmap_size(mydata, 32, 32, 4);
for(yi=0;yi<mydata->height;yi++)
for(xi=0;xi<mydata->width;xi++) {
((Pixelel*)mydata->data)[(yi*mycorpus->width+xi)*4] =
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4];
((Pixelel*)mydata->data)[(yi*mycorpus->width+xi)*4+1] =
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+1];
((Pixelel*)mydata->data)[(yi*mycorpus->width+xi)*4+2] =
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+2];
((Pixelel*)mydata->data)[(yi*mycorpus->width+xi)*4+3] =
((Pixelel*)mycorpus->data)[(yi*mycorpus->width+xi)*4+3];
}
/* Allocate memory for output and status tracking */
{
bitmap_size(status,mydata->width,mydata->height,1);
heap = heap_new(status->data,status->width*status->height);
for(i=0;i<status->width*status->height;i++) {
((Status*)status->data)[i].use = true;
((Status*)status->data)[i].done = (((Pixelel*)mymask->data)[i] != 255);
((Status*)status->data)[i].priority = 0;
}
}
n_pixels = 0;
{
Pixelel *ptr = mydata->data;
for(i=0;i<mydata->width*mydata->height;i++,ptr+=mydata->depth) {
if (!((Status*)status->data)[i].done) {
n_pixels++;
for(j=0;j<input_bytes;j++)
ptr[j] = 128;
}
ptr[random_pos] = rand();
}
}
{
Pixelel *ptr = ((Pixelel*)mycorpus->data) + random_pos;
for(i=0;i<mycorpus->width*mycorpus->height;i++,ptr+=mycorpus->depth)
*ptr = rand();
}
/* Work out which pixels from the corpus to use */
{
Pixelel *ptr;
ptr = mymask->data;
for(i=0;i<mymask->width*mymask->height;i++,ptr++)
*ptr = (*ptr ? 0 : 1);
}
for(y=patch_radius;y<mycorpus->height-patch_radius;y++)
for(x=patch_radius;x<mycorpus->width-patch_radius;x++)
if (bitmap_at(mymask,Pixelel,x,y)[0])
for(i=0;i<neighbours->len;i++) {
Coordinates *n = &g_array_index(neighbours,Coordinates,i);
if (bitmap_at(mymask,Pixelel,x+n->x,y+n->y)[0])
bitmap_at(mymask,Pixelel,x+n->x,y+n->y)[0]++;
}
n_corpus_pixels = 0;
{
Pixelel *ptr;
ptr = mymask->data;
for(i=0;i<mymask->width*mymask->height;i++,ptr++)
if (*ptr == neighbours->len+1) {
*ptr = (*ptr == neighbours->len+1 ? 1 : 0);
n_corpus_pixels++;
} else
*ptr = 0;
}
/* Sanity check */
if (!n_corpus_pixels || !n_pixels) {
if (!n_corpus_pixels)
printf("The input texture is too small.");
else
printf("The output image is too small.");
exit(1);
}
/* Examine neighbouring pixel interactions */
bitmap_size(weights, mycorpus->width,mycorpus->height,neighbours->len);
weight_sum_len = neighbours->len;
weight_sum = g_new(double,weight_sum_len);
for(i=0;i<weight_sum_len;i++)
weight_sum[i] = 0.0;
{
double total_bits, total_entropy;
Twine_list_item *sorted_list;
uint mask;
int start;
Entropy_accumulator *accumulator = entropy_accumulator_new(input_bytes);
entropy_accumulator_clear(accumulator);
for(i=0;i<mycorpus->width*mycorpus->height;i++)
if (((Pixelel*)(mymask->data))[i])
entropy_accumulator_add(accumulator,(Pixelel*)mycorpus->data+i*mycorpus->depth);
entropy_accumulator_calculate(accumulator, &total_bits, &total_entropy);
sorted_list = g_new(Twine_list_item,n_corpus_pixels);
for(i=0,y=0;y<mycorpus->height;y++)
for(x=0;x<mycorpus->width;x++)
if (bitmap_at(mymask,Pixelel,x,y)[0]) {
sorted_list[i].x = x;
sorted_list[i].y = y;
sorted_list[i].twine = entwine(bitmap_at(mycorpus,Pixelel,x,y), input_bytes);
i++;
}
qsort(sorted_list,n_corpus_pixels,sizeof(Twine_list_item),
twine_list_item_sorter);
for(i=0;i<neighbours->len;i++) {
/* Find best quantization level */
int best_level = 0;
double best_bits = 1e30;
for(j=0;j<=(int)(sizeof(Pixelel)*8);j++) {
double this_bits;
mask = (uint)(-1);
mask <<= j*input_bytes;
entropy_accumulator_clear(accumulator);
start = 0;
this_bits = 0.0;
for(k=0;;k++) {
if (k == n_corpus_pixels ||
(sorted_list[start].twine&mask) != (sorted_list[k].twine&mask)) {
double bits, entropy;
entropy_accumulator_calculate(accumulator, &bits, &entropy);
this_bits += bits;
entropy_accumulator_clear(accumulator);
start = k;
}
if (k == n_corpus_pixels)
break;
entropy_accumulator_add(accumulator,
bitmap_at(mycorpus,Pixelel,
sorted_list[k].x+g_array_index(neighbours,Coordinates,i).x,
sorted_list[k].y+g_array_index(neighbours,Coordinates,i).y));
}
//Kinda dodgy, its possible the length won't be a... whats the
// technical term... one hump function
if (this_bits > best_bits)
break;
best_level = j;
best_bits = this_bits;
}
/* Calculate weights */
mask = (uint)(-1);
mask <<= best_level*input_bytes;
entropy_accumulator_clear(accumulator);
start = 0;
for(k=0;;k++) {
if (k == n_corpus_pixels ||
(sorted_list[start].twine&mask) != (sorted_list[k].twine&mask)) {
int weight;
double bits, entropy;
entropy_accumulator_calculate(accumulator, &bits, &entropy);
weight = (int)( (total_entropy - entropy) * 65536.0 );
if (weight < 0)
weight = 0;
weight_sum[i] += weight * (k-start);
for(l=start;l<k;l++)
bitmap_at(weights,int,sorted_list[l].x,sorted_list[l].y)[i] =
weight;
entropy_accumulator_clear(accumulator);
start = k;
}
if (k == n_corpus_pixels)
break;
entropy_accumulator_add(accumulator,
bitmap_at(mycorpus,Pixelel,
sorted_list[k].x+g_array_index(neighbours,Coordinates,i).x,
sorted_list[k].y+g_array_index(neighbours,Coordinates,i).y));
}
}
g_free(sorted_list);
entropy_accumulator_free(accumulator);
} /* Calculating weights */
set_up_tree_globals();
{
double sum, map_sum;
Offset offset;
for(y=0;y<mycorpus->height;y++)
for(x=0;x<mycorpus->width;x++)
if (bitmap_at(mymask,Pixelel,x,y)[0]) {
int *weight = bitmap_at(weights,int,x,y);
int sum = 0;
for(i=0;i<neighbours->len;i++) {
sum += weight[i];
}
if (sum == 0)
for(i=0;i<neighbours->len;i++)
weight[i] = 65536 / neighbours->len;
else
for(i=0;i<neighbours->len;i++)
weight[i] = (int)(weight[i] * 65536.0 / sum);
}
for(i=0;i<weight_sum_len;i++) {
weight_sum[i] = pow(2.0,weight_sum[i]
/n_corpus_pixels
/65536.0);
}
sum = 0.0;
for(i=0;i<neighbours->len;i++)
sum += weight_sum[i];
map_sum = 0.0;
for(i=0;i<neighbours->len;i++) {
offset.weight = (int)(weight_sum[i]*65536.0 / sum);
offset.x = -g_array_index(neighbours,Coordinates,i).x;
offset.y = -g_array_index(neighbours,Coordinates,i).y;
for(j=0;j<input_bytes;j++) {
offset.el = j;
offset.offset = j
- g_array_index(neighbours,Coordinates,i).x * mycorpus->depth
- g_array_index(neighbours,Coordinates,i).y * mycorpus->depth * mycorpus->width;
g_array_append_val(Offsets,offset);
}
}
offset.x = 0;
offset.y = 0;
offset.el = random_pos;
offset.offset = random_pos;
offset.weight = (int)(pow(2,16.0*parameters.random_weight));
g_array_append_val(Offsets,offset);
for(y=0;y<mydata->height;y++)
for(x=0;x<mydata->width;x++)
if (!bitmap_at(status,Status,x,y)[0].done)
for(i=0;i<neighbours->len;i++) {
int xx = x - g_array_index(neighbours,Coordinates,i).x;
int yy = y - g_array_index(neighbours,Coordinates,i).y;
bool use;
if (!wrap_or_clip(¶meters,mydata,&xx,&yy))
use = false;
else
use = bitmap_at(status,Status,xx,yy)[0].done;
if (use)
bitmap_at(status,Status,x,y)[0].priority += (int)(weight_sum[i]*65536.0/sum);
}
}
g_free(weight_sum);
qsort(& (g_array_index(Offsets,Offset,0)), Offsets->len, sizeof(Offset),
offset_sorter);
{
Pixelel **items = g_new(Pixelel*,n_corpus_pixels);
for(i=0,y=0;y<mycorpus->height;y++)
for(x=0;x<mycorpus->width;x++)
if (bitmap_at(mymask,Pixelel,x,y)[0])
items[i++] = bitmap_at(mycorpus,Pixelel,x,y);
tree = build_tree(items,n_corpus_pixels);
g_free(items);
}
/* ------------------------ */
/* ------ Grow image ------ */
/* ------------------------ */
{
Status *next;
int n_pixels_done = 0;
Pixelel* tmp_2 ;
heap_become_heapish(heap);
while(next = heap_pop_top(heap)) {
Pixelel *result;
int *weight;
int pos = next-((Status*)status->data);
int x = pos % status->width;
int y = pos / status->width;
g_array_set_size(Patterns,0);
for(i=0;i<Offsets->len;i++) {
Offset *o = &g_array_index(Offsets,Offset,i);
int yy = y + o->y;
int xx = x + o->x;
int el = o->el;
if (wrap_or_clip(¶meters,mydata,&xx,&yy))
{
Status *tmp = bitmap_at(status,Status,xx,yy) ;
if ( tmp[0].use && (el >= input_bytes || tmp[0].done))
{
Pattern pattern;
pattern.offset_no = i;
pattern.value = bitmap_at(mydata,Pixelel,xx,yy)[el];
g_array_append_val(Patterns,pattern);
}
}
}
bitmap_at(status,Status,x,y)[0].done = true;
result = query_tree(tree);
tmp_2 = bitmap_at(mydata,Pixelel,x,y) ;
for(i=0;i<input_bytes;i++)
tmp_2[i] = result[i];
weight = (result - ((Pixelel*)mycorpus->data))/mycorpus->depth*weights->depth + weights->data;
for(i=0;i<neighbours->len;i++) {
int xx = x + g_array_index(neighbours,Coordinates,i).x;
int yy = y + g_array_index(neighbours,Coordinates,i).y;
if (wrap_or_clip(¶meters,mydata,&xx,&yy))
{
Status *tmp = bitmap_at(status,Status,xx,yy) ;
if ( tmp[0].use && !tmp[0].done)
{
tmp[0].priority += weight[i];
heap_promote(heap,tmp);
}
}
}
n_pixels_done++;
} /* -----end while (!progress_monitor_aborted(monitor)...----- */
} /* ------ end of Grow image ------ */
node_free(tree);
clean_up_tree_globals();
for (i=0;i<mydata->width*mydata->height;i++){
if (i%mydata->width == 0) printf("\n");
printf("%i ",((Pixelel*)mydata->data)[i*4]);
}
bitmap_free(status);
bitmap_free(weights);
bitmap_free(mymask);
bitmap_free(mycorpus);
bitmap_free(mydata);
heap_free(heap);
g_array_free(neighbours,TRUE);
}
int main(int argC, char** argV){
run();
}
