Skip to content

Commit

Permalink
Selection: support alpha in selections
Browse files Browse the repository at this point in the history
  • Loading branch information
dsizzle committed Oct 27, 2023
1 parent a675dac commit 844fff6
Show file tree
Hide file tree
Showing 15 changed files with 256 additions and 128 deletions.
6 changes: 1 addition & 5 deletions artpaint/Utilities/BitmapUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,7 @@ BitmapUtilities::ConvertToMask(BBitmap* inBitmap, uint8 color)
for (int32 y = 0; y < out_map->Bounds().IntegerHeight() + 1; y++) {
for (int32 x = 0; x < out_map->Bounds().IntegerWidth() + 1; x++) {
c.word = *(in_bits + x + y * in_bpr);
// revert this change when the rest of ArtPaint understands
// selections with alpha
float alpha = 0;
if (c.bytes[3] > 0x00)
alpha = 1;
float alpha = (float)c.bytes[3] / 255.;

*(out_bits + x + y * out_bpr) = (uint8)((float)color * alpha);
}
Expand Down
8 changes: 6 additions & 2 deletions artpaint/Utilities/ScaleUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,18 @@ ScaleUtilities::ScaleVerticallyGray(float width, float height, BPoint offset, BB
uint8* source_bits = (uint8*)source->Bits();
int32 source_bpr = source->BytesPerRow();

for (int32 y = 0; y <= (int32)height; y++) {
int32 max_width = width;
int32 max_height = height;

for (int32 y = 0; y <= (int32)max_height; y++) {
int32 low = floor(ratio * y);
int32 high = ceil(ratio * y);
float weight = (ratio * y) - low;

uint8* src_bits_low = source_bits + (int32)offset.x + (low + (int32)ceil(offset.y + 0.5)) * source_bpr;
uint8* src_bits_high = source_bits + (int32)offset.x + (high + (int32)ceil(offset.y + 0.5)) * source_bpr;

for (int32 x = 0; x <= width; x++) {
for (int32 x = 0; x <= max_width; x++) {
*(target_bits + x + y * target_bpr)
= linear_interpolation(*(src_bits_low + x),
*(src_bits_high + x), weight);
Expand Down
6 changes: 6 additions & 0 deletions artpaint/application/PixelOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,12 @@ inline uint32 linear_interpolation(uint32 p1, uint32 p2, float t)
}


inline uint8 linear_interpolation(uint8 p1, uint8 p2, float t)
{
return (p1 * (1.0 - t)) + (p2 * t);
}


inline uint32 mitchell_netravali(uint32 p0, uint32 p1, uint32 p2, uint32 p3,
float t, float B, float C)
{
Expand Down
7 changes: 6 additions & 1 deletion artpaint/application/Selection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,12 @@ Selection::Invert()
uint8* bits = (uint8*)selection_map->Bits();
int32 bits_length = selection_map->BitsLength();
for (int32 i = 0; i < bits_length; i++) {
*bits = ~(*bits);
union color_conversion pixel;
pixel.word = *bits;
for (int i = 0; i < 4; ++i)
pixel.bytes[i] = 255 - pixel.bytes[i];

*bits = pixel.word;
++bits;
}
selection_bounds = BRect(0, 0, -1, -1);
Expand Down
23 changes: 23 additions & 0 deletions artpaint/application/Selection.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ class Selection {
// GetBoundingRect-function.
inline bool ContainsPoint(BPoint);
inline bool ContainsPoint(int32, int32);

inline uint8 Value(BPoint);
inline uint8 Value(int32, int32);
};


Expand All @@ -207,6 +210,26 @@ Selection::ContainsPoint(int32 x, int32 y)
}


uint8
Selection::Value(BPoint p)
{
return Value((int32)p.x, (int32)p.y);
}


uint8
Selection::Value(int32 x, int32 y)
{
if (x < 0 || y < 0)
return 0;

if (selection_bits == NULL || image_bounds.Contains(BPoint(x, y)) == false)
return 0;

return *(selection_bits + y * selection_bpr + x);
}


// This class contains the vital data that describe selection. A selection
// can be archived with such data and selection can also be modified to
// represent the same selection as the SelectionData represents.
Expand Down
3 changes: 0 additions & 3 deletions artpaint/paintwindow/ImageView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2114,9 +2114,6 @@ ImageView::ManipulatorFinisherThread()
the_image->SetImageSize();
the_image->Render();

// also recalculate the selection
selection->Recalculate();

// Change the selection for the undo-queue if necessary.
if ((new_event != NULL)
&& !(undo_queue->ReturnSelectionMap() == selection->ReturnSelectionMap())) {
Expand Down
18 changes: 16 additions & 2 deletions artpaint/tools/BitmapDrawer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,10 @@ BitmapDrawer::SetPixel(
BPoint location, uint32 color, Selection* sel, uint32 (*composite_func)(uint32, uint32))
{
if (sel == NULL || sel->ContainsPoint(location)) {
float sel_alpha = 1.0;
if (sel != NULL && sel->IsEmpty() == false)
sel_alpha = sel->Value(location) / 255.;

if (bitmap_bounds.Contains(location)) {
if (composite_func) {
union {
Expand All @@ -1224,14 +1228,24 @@ BitmapDrawer::SetPixel(
} norm_color, target_color;

norm_color.word = color;
norm_color.bytes[3] *= sel_alpha;

uint32 target = GetPixel(location);
target_color.word = target;

*(bitmap_bits + (int32)location.x + (int32)location.y * bitmap_bpr)
= (*composite_func)(target_color.word, norm_color.word);
} else
*(bitmap_bits + (int32)location.x + (int32)location.y * bitmap_bpr) = color;
} else {
union {
unsigned char bytes[4];
uint32 word;
} norm_color;

norm_color.word = color;
norm_color.bytes[3] *= sel_alpha;

*(bitmap_bits + (int32)location.x + (int32)location.y * bitmap_bpr) = norm_color.word;
}

return B_OK;
} else
Expand Down
5 changes: 5 additions & 0 deletions artpaint/tools/Brush.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,11 +491,16 @@ Brush::draw(BBitmap* buffer, BPoint point, Selection* selection)
target_bits = bits + (y + py) * bpr + left;
for (int32 x = left; x <= right; ++x) {
if (selection->IsEmpty() || selection->ContainsPoint(x, y + py)) {
float sel_alpha = 1.0;
if (selection->IsEmpty() == false && selection->ContainsPoint(x, y + py))
sel_alpha = selection->Value(x, y + py) / 255.;

union color_conversion brush_color, target_color, result;
brush_color.word = *(brush_bits + (x - px) + y * brush_bpr);
brush_color.bytes[0] = 0xFF;
brush_color.bytes[1] = 0xFF;
brush_color.bytes[2] = 0xFF;
brush_color.bytes[3] *= sel_alpha;

target_color.word = *target_bits;

Expand Down
42 changes: 21 additions & 21 deletions artpaint/tools/FillTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ FillTool::NormalFill(ImageView* view, uint32 buttons, BPoint start, Selection* s
if ((sel == NULL || sel->IsEmpty() == true || sel->ContainsPoint(x, y))
&& compare_2_pixels_with_variance(
old_color, drawer->GetPixel(x, y), tolerance)) {
drawer->SetPixel(x, y, color);
drawer->SetPixel(x, y, color, sel);
}
}
}
Expand Down Expand Up @@ -246,7 +246,7 @@ FillTool::CheckSpans(BPoint span_start, BitmapDrawer* drawer, PointStack& stack,
} else if (binary_bits != NULL)
*(binary_bits + y * binary_bpr + (x / 8)) |= (0x01 << (7 - x % 8));

drawer->SetPixel(x, y, new_color);
drawer->SetPixel(x, y, new_color, sel);

if (spans == BOTH || spans == LOWER) {
if ((inside_lower_span == FALSE)
Expand Down Expand Up @@ -303,7 +303,7 @@ FillTool::CheckSpans(BPoint span_start, BitmapDrawer* drawer, PointStack& stack,
} else if (binary_bits != NULL)
*(binary_bits + y * binary_bpr + (x / 8)) |= (0x01 << (7 - x % 8));

drawer->SetPixel(x, y, new_color);
drawer->SetPixel(x, y, new_color, sel);

if (spans == BOTH || spans == LOWER) {
if ((inside_lower_span == FALSE)
Expand Down Expand Up @@ -364,7 +364,7 @@ FillTool::FillSpan(BPoint span_start, BitmapDrawer* drawer, int32 min_x, int32 m
// Then go from start towards the left side of the bitmap.
while ((sel == NULL || sel->IsEmpty() || sel->ContainsPoint(x, y)) && (x >= min_x)
&& (compare_2_pixels_with_variance(drawer->GetPixel(x, y), old_color, tolerance))) {
drawer->SetPixel(x, y, new_color);
drawer->SetPixel(x, y, new_color, sel);
if (binary_bits != NULL)
*(binary_bits + y * binary_bpr + (x / 8))
= *(binary_bits + y * binary_bpr + (x / 8)) | (0x01 << (7 - x % 8));
Expand All @@ -375,7 +375,7 @@ FillTool::FillSpan(BPoint span_start, BitmapDrawer* drawer, int32 min_x, int32 m
x = start_x + 1;
while ((sel == NULL || sel->IsEmpty() || sel->ContainsPoint(x, y)) && (x <= max_x)
&& (compare_2_pixels_with_variance(drawer->GetPixel(x, y), old_color, tolerance))) {
drawer->SetPixel(x, y, new_color);
drawer->SetPixel(x, y, new_color, sel);
if (binary_bits != NULL)
*(binary_bits + y * binary_bpr + (x / 8))
= *(binary_bits + y * binary_bpr + (x / 8)) | (0x01 << (7 - x % 8));
Expand Down Expand Up @@ -523,16 +523,16 @@ FillTool::GradientFill(

if (fToolSettings.shape == GRADIENT_CONIC) {
FillGradientConic(drawer, binary_map, start, new_point, min_x, max_x, min_y,
max_y, color, gradient_color);
max_y, color, gradient_color, 2, sel);
} else if (fToolSettings.shape == GRADIENT_RADIAL) {
FillGradientRadial(drawer, binary_map, start, new_point, min_x, max_x,
min_y, max_y, color, gradient_color, 2);
min_y, max_y, color, gradient_color, 2, sel);
} else if (fToolSettings.shape == GRADIENT_SQUARE) {
FillGradientSquare(drawer, binary_map, start, new_point, min_x, max_x,
min_y, max_y, color, gradient_color, 2);
min_y, max_y, color, gradient_color, 2, sel);
} else {
FillGradientLinear(drawer, binary_map, start, new_point, min_x, max_x,
min_y, max_y, color, gradient_color, 2);
min_y, max_y, color, gradient_color, 2, sel);
}

bitmap->Lock();
Expand Down Expand Up @@ -560,16 +560,16 @@ FillTool::GradientFill(
// Here calculate the final gradient.
if (fToolSettings.shape == GRADIENT_CONIC) {
FillGradientConic(drawer, binary_map, start, new_point, min_x, max_x, min_y, max_y,
color, gradient_color);
color, gradient_color, 1, sel);
} else if (fToolSettings.shape == GRADIENT_RADIAL) {
FillGradientRadial(drawer, binary_map, start, new_point, min_x, max_x, min_y, max_y,
color, gradient_color);
color, gradient_color, 1, sel);
} else if (fToolSettings.shape == GRADIENT_SQUARE) {
FillGradientSquare(drawer, binary_map, start, new_point, min_x, max_x, min_y, max_y,
color, gradient_color);
color, gradient_color, 1, sel);
} else {
FillGradientLinear(drawer, binary_map, start, new_point, min_x, max_x, min_y, max_y,
color, gradient_color);
color, gradient_color, 1, sel);
}
// Update the image-view.
bitmap->Lock();
Expand Down Expand Up @@ -773,7 +773,7 @@ FillTool::MakeFloodBinaryMap(BitmapDrawer* drawer, int32 min_x, int32 max_x, int
void
FillTool::FillGradientLinear(BitmapDrawer* drawer, BBitmap* binary_map, BPoint start, BPoint end,
int32 min_x, int32 max_x, int32 min_y, int32 max_y, uint32 new_color, uint32 gradient_color,
uint8 skip)
uint8 skip, Selection* sel)
{
uchar* binary_bits = (uchar*)binary_map->Bits();
int32 binary_bpr = binary_map->BytesPerRow();
Expand Down Expand Up @@ -838,7 +838,7 @@ FillTool::FillGradientLinear(BitmapDrawer* drawer, BBitmap* binary_map, BPoint s

for (int dy = 0; dy < skip; ++dy) {
for (int dx = 0; dx < skip; ++dx)
drawer->SetPixel(x + dx, y + dy, out_color.word);
drawer->SetPixel(x + dx, y + dy, out_color.word, sel);
}
}
}
Expand All @@ -849,7 +849,7 @@ FillTool::FillGradientLinear(BitmapDrawer* drawer, BBitmap* binary_map, BPoint s
void
FillTool::FillGradientRadial(BitmapDrawer* drawer, BBitmap* binary_map, BPoint start, BPoint end,
int32 min_x, int32 max_x, int32 min_y, int32 max_y, uint32 new_color, uint32 gradient_color,
uint8 skip)
uint8 skip, Selection* sel)
{
uchar* binary_bits = (uchar*)binary_map->Bits();
int32 binary_bpr = binary_map->BytesPerRow();
Expand Down Expand Up @@ -901,7 +901,7 @@ FillTool::FillGradientRadial(BitmapDrawer* drawer, BBitmap* binary_map, BPoint s

for (int dy = 0; dy < skip; ++dy) {
for (int dx = 0; dx < skip; ++dx)
drawer->SetPixel(x + dx, y + dy, out_color.word);
drawer->SetPixel(x + dx, y + dy, out_color.word, sel);
}
}
}
Expand All @@ -912,7 +912,7 @@ FillTool::FillGradientRadial(BitmapDrawer* drawer, BBitmap* binary_map, BPoint s
void
FillTool::FillGradientSquare(BitmapDrawer* drawer, BBitmap* binary_map, BPoint start, BPoint end,
int32 min_x, int32 max_x, int32 min_y, int32 max_y, uint32 new_color, uint32 gradient_color,
uint8 skip)
uint8 skip, Selection* sel)
{
uchar* binary_bits = (uchar*)binary_map->Bits();
int32 binary_bpr = binary_map->BytesPerRow();
Expand Down Expand Up @@ -971,7 +971,7 @@ FillTool::FillGradientSquare(BitmapDrawer* drawer, BBitmap* binary_map, BPoint s

for (int dy = 0; dy < skip; ++dy) {
for (int dx = 0; dx < skip; ++dx)
drawer->SetPixel(x + dx, y + dy, out_color.word);
drawer->SetPixel(x + dx, y + dy, out_color.word, sel);
}
}
}
Expand All @@ -982,7 +982,7 @@ FillTool::FillGradientSquare(BitmapDrawer* drawer, BBitmap* binary_map, BPoint s
void
FillTool::FillGradientConic(BitmapDrawer* drawer, BBitmap* binary_map, BPoint start, BPoint end,
int32 min_x, int32 max_x, int32 min_y, int32 max_y, uint32 new_color, uint32 gradient_color,
uint8 skip)
uint8 skip, Selection* sel)
{
uchar* binary_bits = (uchar*)binary_map->Bits();
int32 binary_bpr = binary_map->BytesPerRow();
Expand Down Expand Up @@ -1043,7 +1043,7 @@ FillTool::FillGradientConic(BitmapDrawer* drawer, BBitmap* binary_map, BPoint st

for (int dy = 0; dy < skip; ++dy) {
for (int dx = 0; dx < skip; ++dx)
drawer->SetPixel(x + dx, y + dy, out_color.word);
drawer->SetPixel(x + dx, y + dy, out_color.word, sel);
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions artpaint/tools/FillTool.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,16 @@ class FillTool : public DrawingTool {
Selection* = NULL);
void FillGradientLinear(BitmapDrawer*, BBitmap*, BPoint,
BPoint, int32, int32, int32, int32, uint32,
uint32, uint8 skip = 1);
uint32, uint8 skip = 1, Selection* sel = NULL);
void FillGradientRadial(BitmapDrawer*, BBitmap*, BPoint,
BPoint, int32, int32, int32, int32, uint32,
uint32, uint8 skip = 1);
uint32, uint8 skip = 1, Selection* sel = NULL);
void FillGradientSquare(BitmapDrawer*, BBitmap*, BPoint,
BPoint, int32, int32, int32, int32, uint32,
uint32, uint8 skip = 1);
uint32, uint8 skip = 1, Selection* sel = NULL);
void FillGradientConic(BitmapDrawer*, BBitmap*, BPoint,
BPoint, int32, int32, int32, int32, uint32,
uint32, uint8 skip = 1);
uint32, uint8 skip = 1, Selection* sel = NULL);

BRect calcBinaryMapBounds(BBitmap *boolean_map);
};
Expand Down
5 changes: 2 additions & 3 deletions artpaint/viewmanipulators/RotationManipulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,8 @@ RotationManipulator::ManipulateBitmap(
}

// We must make a copy of the selection in order to be able to rotate it
selection->RotateTo(center, the_angle);
selection->Recalculate();
BBitmap* selmap = ManipulateSelectionMap(new_settings);
selection->ReplaceSelection(selmap);

BRect selection_bounds = selection->GetBoundingRect();
int32 sel_top = (int32)selection_bounds.top;
Expand Down Expand Up @@ -693,7 +693,6 @@ RotationManipulator::PreviewBitmap(bool full_quality, BRegion* updated_region)
void
RotationManipulator::Reset()
{
selection->RotateTo(settings->origo, 0);
settings->angle = 0;
previous_angle = 0;

Expand Down
Loading

0 comments on commit 844fff6

Please sign in to comment.