KisPixel
Boudewijn Rempt
boud at valdyas.org
Mon Jul 26 18:01:33 CEST 2004
On Monday 26 July 2004 15:12, Casper Boemann wrote:
> 1) Display on screen (obviously), and I think the current way is right on
> the money. But we need to extend it to handle invisible channels.
And compositing layers of different types. One thing I'm working on currently
-- stalled a bit because I'm waiting for the iterators to get finished and
four your work on auto-extending layers is selections. Currently, I model a
selection as a layer with a 256 bit grayscale colour model. Composite this
with a user-settable opacity, and you have a very clear way of representing
discontinuous selections. I hope. But for that, it's necessary to be able to
mix colour models in one image. The groundwork has been done, but I still
need to do a lot for that.
>
> 2) Infodocker (showing on screen in numbers what the value under the
> cursorpointer is). This could be accomplished by returning it as a string.
> That way any kind of channel could be shown, since it would be up to the
> colorstrategy to format the string.
>
Exactly.
> 3)Histograms. Hmm tricky in the general, since a channel could be anything
> (even bitflags perhabs, though that could outwardly be shown as seperate
> channels). On the other hand absolutely no gui should go into the
> colorstrategy, so what to do?
Not GUI, but some information, like the names of the channels a colour model
supports and boundary conditions does need to come from the colour strategy.
> Perhaps a function to extract a channel as a
> double (should preserve all scalar values even longs with full precision).
> How does the histogram function the decide the number of bins. Well
> obviously we cannot have 2^32 bins anyway as that would take up 16 gigs of
> memory. For gui purposes 256 bins should suffice. Functions telling the
> theoretically range of values of the channel should also be provided then.
> That would return 0-255.0 or 0-1.0E256 or something like that. The
> colorstrategy might know that even though it's a double only values 0-1.0
> are valid, and so that is returned.
This is all not too hard to solve; for now we're limited to 8 bits anyway, and
for the next release, we'll have to downsample a bit. Photogenics doesn't
offer a histogram, and I wonder whether a histogram is all that necessary for
high definition images. I intend to use the same widget for a levels dialog,
by the way.
>
> 4) Filters and Scripts. I think they should be limited to the compositions
> and other general functions (eg colordistance) we might come up with. But
> perhabs this is not enough for some kinds of manipulation. I don't know
> what might be needed. Insights anyone? please be specific.
>
Hm. There are a lot of different possibilities to mess with pixels that we
cannot all foresee, nor want to add to the colour strategy. For instance:
* darken/lighten pixel/channel
* composite
* copy from x,y to x',y'
* compute a value for x,y from the surrounding pixels (for instance when
scaling or convolving)
* compute something from two different pixels
* create a whole new, exciting pixel to put in place of the current pixel
For some computations, a colour must be converted to HSV and then back, I
believe.
You don't want to push the actual operations that a filter wants to implement
into the colour strategy -- except for the composition, I think -- because
that has the following disadvantages:
* Color strategies will get out of sync. Already a problem because the color
strategies we have currently don't support the same set of composite ops.
* Creating new filters gets pretty hard because they need to add stuff to all
the colour strategies.
Now if we could define a basic set of building blocks that makes it possible
to build any imaginable image operation, we should put the building blocks
into every color strategy. If that proves impossible, we need to expose the
raw channel data to the outside world. And that'll mean that there will be,
once we start building 16-bit channels and the like, plugins that cannot work
with every colour strategy.
For now it's enough that those algorithms that want to mess with pixel data
can loop over the channels, extract the relevant byte, and mess with that.
Or have a small type hierarchy for channel data -- simpler than one for every
possible pixel, and a bit like Cyrille's KisQuantum, only more extensive. No
doubt this can be done with templates, but I understand this a little better.
Like:
class KisChannel {
public:
KisChannel() {};
virtual ~KisChannel() {};
Q_UINT8 getDataAsByte() = 0;
Q_UINT32 getDataAsInt() = 0;
float getDataAsFloat() = 0;
double getDataAsDouble() = 0;
KisChannel &operator+=(const KisChannel &) = 0;
KisChannel &operator-=(const KisChannel &) = 0;
KisChannel &operator*=(int) = 0;
KisChannel &operator*=(long) = 0;
KisChannel &operator*=(double) = 0;
KisChannel &operator/=(int) = 0;
KisChannel &operator/=(long) = 0;
KisChannel &operator/=(double) = 0;
bool operator==(const KisChannel &, const KisChannel &) = 0;
bool operator!=(const KisChannel &, const KisChannel &) = 0;
KisChannel operator+(const KisChannel &, const KisChannel &) = 0;
KisChannel operator-(const KisChannel &, const KisChannel &) = 0;
KisChannel operator*(const KisChannel &, int) = 0;
KisChannel operator*(int, const KisChannel &) = 0;
KisChannel operator*(const KisChannel &, long) = 0;
KisChannel operator*(long, const KisChannel &) = 0;
KisChannel operator*(const KisChannel &, double) = 0;
KisChannel operator*(double, const KisChannel &) = 0;
KisChannel operator-(const KisChannel &) = 0;
KisChannel operator/(const KisChannel &, int) = 0;
KisChannel operator/(const KisChannel &, long) = 0;
};
class KisByteChannel {
public:
KisChannel(Q_UINT8 data) {m_data = data;}
....
private:
Q_UINT8 m_data;
}
class KisIntChannel {
public:
KisChannel(Q_UINT32 data) {m_data = data;}
....
private:
Q_UINT32 m_data;
}
class KisFloatChannel {
public:
KisChannel(float data) {m_data = data;}
....
private:
Q_UINT8 m_data;
}
class KisDoubleChannel {
public:
KisChannel(double data) {m_data = data;}
....
private:
double m_data;
}
Now the filters can work on a simple KisChannel, adding, multiplying,
dividing to their heart's content.
> 5) ChannelDocker. Showing the names of channels, visibillity status and
> more. Although not exactly individual pixeldata, it should still be shown
> in an independant manner. I think ChannelInfo does that right?
Right.
>
> 6)Mode change (say from rgb to cmyk). Should go through a single mediator.
> Be it a Lab colorstrategy or perhabs just koColor (not sure if koColor fits
> the following requirements though). The important thing is that no lowering
> of gamut should be imposed by the mediator (only the to and from modes).
> Also it should be colorspace aware (there are unlimited number of rgb
> spaces, so handling one rgb space is not enough - thats why we need lcms)
koColor doesn't fit the bill yet -- but might be expanded, and we can make do
with it for now. koColor supports (with some bugs):
indexed,
8 bit lab,
8 bit rgb,
8 bit hsv,
8 bit cmyk
Which should suffice for our first release.
>
> 7)Colorpicker. Again no restriction of gamut. Should also be colorspace
> aware. The standard ko/kde/qt things may not be enough. We may need to do
> our own.
We can nick a cmyk colour picker, or at least the guts, from Scribus.
> Also a true palette (like in the real world) would be nice, so the
> need for our own gui is also needed for other reasons. This is a
> paint/color/imagemanipulation application after all, so things that work
> for a normal office application probably is not enough for us. The best way
> in my opinion is again to go throught a mediator like Lab or xyz
You won't be able to mix colours realistically without some sophisticated
stuff; the papers I have read have sampled paint with a spectrometer,
isolated about 100 frequencies and then reduced the number of frequencies
until the mixing became too unreliable. We cannot simply use their data
because they only published a paper about the technique. Corel Painter makes
it look like it can mix paint realistically, but if you look at the colours
they are simply mixing RGB. (See the link to Impasto on the Krita website:
I'm in the train currently, so cannot look it up.)
(By the way, it might even be nice to have, in the future, virtual iterators,
i.e., iterators that generate a pixel value for a region of pixels, or for a
virtual pixel that lies between two (or four) pixels.)
--
Boudewijn Rempt | http://www.valdyas.org/fading/index.cgi
More information about the kimageshop
mailing list