Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
VlasovRoman committed May 5, 2016
1 parent 0a78839 commit 328bd04
Show file tree
Hide file tree
Showing 64 changed files with 4,011 additions and 0 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# RIP

RIP is a library for complex image processing.

## License

GPLv3

## How to use RIP?

Package in your `dub.json`:
```d
{
"dependencies": {
"rip": "~>0.0.1"
}
}
```
## Dependencies

RIP needs dlib library for loading jpeg/png/bmp/tga files.
WARNING: image can be saved ONLY in ppm/pam/png formats.
12 changes: 12 additions & 0 deletions dub.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "rip",
"description": "Raster and Image processor",
"copyright": "Copyright © 2016, Oleg Baharew, Roman Vlasov",
"license": "GPL-3.0",
"authors": ["Oleg Baharev (aka aquaratixc)", "Roman Vlasov"],
"dependencies": {
"dlib": {
"version" : "*"
}
}
}
116 changes: 116 additions & 0 deletions source/rip/analysis/histogram.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
module rip.analysis.histogram;

private {
import std.algorithm;
import std.range;
import std.math;

import rip.concepts.color;
import rip.concepts.surface;
import rip.concepts.channel;
import rip.concepts.ranges : toSurface;
}

struct Histogram {
uint[] data;

const Channel channel;

alias data this;

this(Channel channel) {
this.channel = channel;
data = new uint[channel.getRangeSize!uint()];
}
}

Histogram takeHistogram(Range)(in Range pixelRange, Channel channel)
//Проверка типа на InputRange
//if(InputRange!Range)
{
auto histogram = Histogram(channel);

pixelRange
.getPixels()
.each!(
(color) => histogram[ channel.getIndex(color) ]++
);

return histogram;
}

//std.algorithm.max не приспособлен для диапазонов
//TODO: убрать это отсюда. Ну позязя :p
T maxValue(T)(T[] args...) {
T max = args[0];

foreach(value; args) {
if(value > max)
max = value;
}

return max;
}

Surface drawHistogram( Histogram histogram,
RGBColor background = new RGBColor(255, 255, 255),
RGBColor pencil = new RGBColor(0, 0, 0)) {
uint width = histogram.channel.getRangeSize!uint;
uint height = cast(uint)
(maxValue(histogram.data) / histogram.channel.getRangeSize!float);

auto surface = new Surface(width, height);

foreach(i; 0..width) {
foreach(j; 0..height) {
if(j <= histogram[i] / histogram.channel.getRangeSize!float()) {
surface[i, height - j - 1] = pencil;
}
else {
surface[i, height - j - 1] = background;
}
}
}

return surface;
}

auto equalizeHistogram(Histogram histogram) {
Histogram equalizedHistogram = histogram;

uint pixelsNumber = histogram.data.reduce!"a + b";

auto probability = histogram
.data
.map!(( float a) => a / pixelsNumber)
.array;

int i = 1;
foreach(ref el; probability[1..$-1]) {
el += probability[i-1];
i++;
}

uint size = histogram.channel.getRangeSize!uint;

equalizedHistogram = probability.map!(a => cast(uint)(a * size)).array;
return equalizedHistogram;
}

Surface appearHistogramToSurface(Histogram histogram, Surface sur) {
import rip.concepts;

auto channel = histogram.channel;

auto getNewColor(in RGBColor color) {
return channel.injectValue(color, channel.getValue(color));
}

return sur
//функция ниже отзеркаливает картинку по диагонали
.createFences(1,1)
.map!(a => a.front)
.map!getNewColor
//функция ниже отзеркаливает картинку по диагонали
.toSurface(sur.getWidth!size_t, sur.getHeight!size_t);
}
5 changes: 5 additions & 0 deletions source/rip/analysis/package.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module rip.analysis;

public{
import rip.analysis.histogram;
}
71 changes: 71 additions & 0 deletions source/rip/concepts/channel.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
module rip.concepts.channel;
//пересмотреть концепт каналов, и в случае введения в проект,
//перенести его в concepts.

private {
import std.algorithm;
import std.math;

import rip.concepts.color;
}

class Channel {
float[2] range;
uint function(in RGBColor color) getValue;

RGBColor function( in RGBColor color,
in float value) injectValue;

this( float rangeMin, float rangeMax,
uint function(in RGBColor color) func,
RGBColor function(in RGBColor color, in float value) colorFunc){

range[0] = rangeMin;
range[1] = rangeMax;
getValue = func;
injectValue = colorFunc;
}

T getRangeSize(T)() const {
return cast(T)round(range[1] - range[0] + 1);
}
}

enum DefaultChannels {

Red = new Channel(
0.0f, 255.0f,
(in color) => color.red!int,
(in color, in value) => new RGBColor(
value,
color.green!ubyte,
color.blue!ubyte)
),

Green = new Channel(
0.0f, 255.0f,
(in color) => color.green!int,
(in color, in value) => new RGBColor(
color.red!ubyte,
value,
color.blue!ubyte)
),

Blue = new Channel(
0.0f, 255.0f,
(in color) => color.blue!int,
(in color, in value) => new RGBColor(
color.red!ubyte,
color.green!ubyte,
value)
),

Grayscale = new Channel(
0.0f, 255.0f,
//так-как для построении гистограммы требуется черно-белое изображение,
//достаточно узнать только значение одного из каналов
(in color) => color.blue!int,
(in color, in value) => new RGBColor(
value, value, value)
)
}
Loading

0 comments on commit 328bd04

Please sign in to comment.