/* find value for entry in hash, -1 if not found */ zip_int64_t _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error) { zip_uint16_t hash_value; zip_hash_entry_t *entry; if (hash == NULL || name == NULL) { zip_error_set(error, ZIP_ER_INVAL, 0); return -1; } hash_value = _hash_string(name, hash->table_size); for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) { if (strcmp((const char *)name, (const char *)entry->name) == 0) { if (flags & ZIP_FL_UNCHANGED) { if (entry->orig_index != -1) { return entry->orig_index; } } else { if (entry->current_index != -1) { return entry->current_index; } } break; } } zip_error_set(error, ZIP_ER_NOENT, 0); return -1; }
unsigned khlist_get(struct khlist *hl, const char *str, void **pud){ unsigned hash = _hash_string(str, HASH_OFFSET); unsigned hasha = _hash_string(str, HASH_A); unsigned hashb = _hash_string(str, HASH_B); unsigned hash_start = hash % hl->size; unsigned npos = hash_start; while (hl->hash_t[npos].exist == 1){ if (hl->hash_t[npos].hasha == hasha && hl->hash_t[npos].hashb == hashb){ if (pud) *pud = hl->hash_t[npos].ud; return npos; }else npos = (npos + 1) % hl->size; if (npos == hash_start) break; } return -1; }
unsigned khlist_set(struct khlist *hl, const char *str, void *ud){ unsigned hash = _hash_string(str, HASH_OFFSET); unsigned hasha = _hash_string(str, HASH_A); unsigned hashb = _hash_string(str, HASH_B); unsigned hash_start = hash % hl->size; unsigned npos = hash_start; while (hl->hash_t[npos].exist == 1){ if (hl->hash_t[npos].hasha == hasha && hl->hash_t[npos].hashb == hashb) return -1; npos = (npos + 1) % hl->size; if (npos == hash_start){ if (_expand(hl) == NULL) return -1; return khlist_set(hl, str, ud); } } hl->hash_t[npos].exist = 1; hl->hash_t[npos].hasha = hasha; hl->hash_t[npos].hashb = hashb; hl->hash_t[npos].ud = ud; return npos; }
/* insert into hash, return error on existence or memory issues */ bool _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error) { zip_uint16_t hash_value; zip_hash_entry_t *entry; if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) { zip_error_set(error, ZIP_ER_INVAL, 0); return false; } hash_value = _hash_string(name, hash->table_size); for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) { if (strcmp((const char *)name, (const char *)entry->name) == 0) { if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) { zip_error_set(error, ZIP_ER_EXISTS, 0); return false; } else { break; } } } if (entry == NULL) { if ((entry=(zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) { zip_error_set(error, ZIP_ER_MEMORY, 0); return false; } entry->name = name; entry->next = hash->table[hash_value]; hash->table[hash_value] = entry; entry->orig_index = -1; } if (flags & ZIP_FL_UNCHANGED) { entry->orig_index = (zip_int64_t)index; } entry->current_index = (zip_int64_t)index; return true; }
/* remove entry from hash, error if not found */ bool _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error) { zip_uint16_t hash_value; zip_hash_entry_t *entry, *previous; if (hash == NULL || name == NULL) { zip_error_set(error, ZIP_ER_INVAL, 0); return false; } hash_value = _hash_string(name, hash->table_size); previous = NULL; entry = hash->table[hash_value]; while (entry) { if (strcmp((const char *)name, (const char *)entry->name) == 0) { if (entry->orig_index == -1) { if (previous) { previous->next = entry->next; } else { hash->table[hash_value] = entry->next; } free(entry); } else { entry->current_index = -1; } return true; } previous = entry; entry = entry->next; }; zip_error_set(error, ZIP_ER_NOENT, 0); return false; }
void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out) { dt_iop_grain_data_t *data = (dt_iop_grain_data_t *)piece->data; unsigned int hash = _hash_string(piece->pipe->image.filename) % (int)fmax(roi_out->width * 0.3, 1.0); const int ch = piece->colors; // Apply grain to image const double strength = (data->strength / 100.0); const double octaves = 3; // double zoom=1.0+(8*(data->scale/100.0)); const double wd = fminf(piece->buf_in.width, piece->buf_in.height); const double zoom = (1.0 + 8 * data->scale / 100) / 800.0; const int filter = fabsf(roi_out->scale - 1.0f) > 0.01; // filter width depends on world space (i.e. reverse wd norm and roi->scale, as well as buffer input to // pixelpipe iscale) const double filtermul = piece->iscale / (roi_out->scale * wd); const float fib1 = 34.0, fib2 = 21.0; const float fib1div2 = fib1 / fib2; #ifdef _OPENMP #pragma omp parallel for default(none) shared(data, hash) #endif for(int j = 0; j < roi_out->height; j++) { float *in = ((float *)ivoid) + (size_t)roi_out->width * j * ch; float *out = ((float *)ovoid) + (size_t)roi_out->width * j * ch; const double wy = (roi_out->y + j) / roi_out->scale; const double y = wy / wd; // y: normalized to shorter side of image, so with pixel aspect = 1. for(int i = 0; i < roi_out->width; i++) { // calculate x, y in a resolution independent way: // wx,wy: worldspace in full image pixel coords: const double wx = (roi_out->x + i) / roi_out->scale; // x: normalized to shorter side of image, so with pixel aspect = 1. const double x = wx / wd; // double noise=_perlin_2d_noise(x, y, octaves,0.25, zoom)*1.5; double noise = 0.0; if(filter) { // if zoomed out a lot, use rank-1 lattice downsampling for(int l = 0; l < fib2; l++) { float px = l / fib2, py = l * fib1div2; py -= (int)py; float dx = px * filtermul, dy = py * filtermul; noise += (1.0 / fib2) * _simplex_2d_noise(x + dx + hash, y + dy, octaves, 1.0, zoom); } } else { noise = _simplex_2d_noise(x + hash, y, octaves, 1.0, zoom); } out[0] = in[0] + dt_lut_lookup_2d_1c(data->grain_lut, (noise * strength) * GRAIN_LIGHTNESS_STRENGTH_SCALE, in[0] / 100.0f); out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; out += ch; in += ch; } } }