1 #include "HalftoneView.h" 2 3 #include <Bitmap.h> 4 #include <StringView.h> 5 6 7 HalftonePreviewView::HalftonePreviewView(BRect frame, const char* name, 8 uint32 resizeMask, uint32 flags) 9 : 10 BView(frame, name, resizeMask, flags) 11 { 12 } 13 14 15 void 16 HalftonePreviewView::Preview(float gamma, float min, 17 Halftone::DitherType ditherType, bool color) 18 { 19 const color_space kColorSpace = B_RGB32; 20 const float right = Bounds().Width(); 21 const float bottom = Bounds().Height(); 22 BRect rect(0, 0, right, bottom); 23 24 BBitmap testImage(rect, kColorSpace, true); 25 BBitmap preview(rect, kColorSpace); 26 BView view(rect, "", B_FOLLOW_ALL, B_WILL_DRAW); 27 28 // create test image 29 testImage.Lock(); 30 testImage.AddChild(&view); 31 32 // color bars 33 const int height = Bounds().IntegerHeight()+1; 34 const int width = Bounds().IntegerWidth()+1; 35 const int delta = height / 4; 36 const float red_bottom = delta - 1; 37 const float green_bottom = red_bottom + delta; 38 const float blue_bottom = green_bottom + delta; 39 const float gray_bottom = height - 1; 40 41 for (int x = 0; x <= right; x ++) { 42 uchar value = x * 255 / width; 43 44 BPoint from(x, 0); 45 BPoint to(x, red_bottom); 46 // red 47 view.SetHighColor(255, value, value); 48 view.StrokeLine(from, to); 49 // green 50 from.y = to.y+1; 51 to.y = green_bottom; 52 view.SetHighColor(value, 255, value); 53 view.StrokeLine(from, to); 54 // blue 55 from.y = to.y+1; 56 to.y = blue_bottom; 57 view.SetHighColor(value, value, 255); 58 view.StrokeLine(from, to); 59 // gray 60 from.y = to.y+1; 61 to.y = gray_bottom; 62 view.SetHighColor(value, value, value); 63 view.StrokeLine(from, to); 64 } 65 66 view.Sync(); 67 testImage.RemoveChild(&view); 68 testImage.Unlock(); 69 70 // create preview image 71 Halftone halftone(kColorSpace, gamma, min, ditherType); 72 halftone.SetBlackValue(Halftone::kLowValueMeansBlack); 73 74 const int widthBytes = (width + 7) / 8; // byte boundary 75 uchar* buffer = new uchar[widthBytes]; 76 77 const uchar* src = (uchar*)testImage.Bits(); 78 uchar* dstRow = (uchar*)preview.Bits(); 79 80 const int numPlanes = color ? 3 : 1; 81 if (color) { 82 halftone.SetPlanes(Halftone::kPlaneRGB1); 83 } 84 85 for (int y = 0; y < height; y ++) { 86 for (int plane = 0; plane < numPlanes; plane ++) { 87 // halftone the preview image 88 halftone.Dither(buffer, src, 0, y, width); 89 90 // convert the plane(s) to RGB32 91 ColorRGB32Little* dst = (ColorRGB32Little*)dstRow; 92 const uchar* bitmap = buffer; 93 for (int x = 0; x < width; x ++, dst ++) { 94 const int bit = 7 - (x % 8); 95 const bool isSet = (*bitmap & (1 << bit)) != 0; 96 uchar value = isSet ? 255 : 0; 97 98 if (color) { 99 switch (plane) { 100 case 0: dst->red = value; 101 break; 102 case 1: dst->green = value; 103 break; 104 case 2: dst->blue = value; 105 break; 106 } 107 } else { 108 dst->red = dst->green = dst->blue = value; 109 } 110 111 if (bit == 0) { 112 bitmap ++; 113 } 114 } 115 } 116 117 // next row 118 src += testImage.BytesPerRow(); 119 dstRow += preview.BytesPerRow(); 120 } 121 122 delete[] buffer; 123 124 SetViewBitmap(&preview); 125 Invalidate(); 126 } 127 128 129 HalftoneView::HalftoneView(BRect frame, const char* name, uint32 resizeMask, 130 uint32 flags) 131 : 132 BView(frame, name, resizeMask, flags) 133 { 134 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 135 136 BRect r(frame); 137 float size, max; 138 139 r.OffsetTo(0, 0); 140 const int height = r.IntegerHeight()+1; 141 const int delta = height / 4; 142 const float red_top = 0; 143 const float green_top = delta; 144 const float blue_top = green_top + delta; 145 const float gray_top = r.bottom - delta; 146 147 const char* kRedLabel = "Red: "; 148 const char* kGreenLabel = "Green: "; 149 const char* kBlueLabel = "Blue: "; 150 const char* kGrayLabel = "Black: "; 151 152 BFont font(be_plain_font); 153 font_height fh; 154 font.GetHeight(&fh); 155 156 max = size = font.StringWidth(kRedLabel); 157 r.Set(0, 0, size, fh.ascent + fh.descent); 158 r.OffsetTo(0, red_top); 159 r.right = r.left + size; 160 AddChild(new BStringView(r, "red", kRedLabel)); 161 162 size = font.StringWidth(kGreenLabel); 163 r.Set(0, 0, size, fh.ascent + fh.descent); 164 if (max < size) max = size; 165 r.OffsetTo(0, green_top); 166 r.right = r.left + size; 167 AddChild(new BStringView(r, "green", kGreenLabel)); 168 169 size = font.StringWidth(kBlueLabel); 170 r.Set(0, 0, size, fh.ascent + fh.descent); 171 if (max < size) max = size; 172 r.OffsetTo(0, blue_top); 173 r.right = r.left + size; 174 AddChild(new BStringView(r, "blue", kBlueLabel)); 175 176 size = font.StringWidth(kGrayLabel); 177 r.Set(0, 0, size, fh.ascent + fh.descent); 178 if (max < size) max = size; 179 r.OffsetTo(0, gray_top); 180 r.right = r.left + size; 181 AddChild(new BStringView(r, "gray", kGrayLabel)); 182 183 r = frame; 184 r.OffsetTo(max, 0); 185 r.right -= max; 186 fPreview = new HalftonePreviewView(r, "preview", resizeMask, flags); 187 AddChild(fPreview); 188 } 189 190 191 void 192 HalftoneView::Preview(float gamma, float min, 193 Halftone::DitherType ditherType, bool color) 194 { 195 fPreview->Preview(gamma, min, ditherType, color); 196 } 197