xref: /haiku/src/libs/print/libprint/HalftoneView.cpp (revision b06a48ab8f30b45916a9c157b992827779182163)
1 #include "HalftoneView.h"
2 
3 #include <Bitmap.h>
4 #include <StringView.h>
5 
6 HalftonePreviewView::HalftonePreviewView(
7 	BRect frame,
8 	const char* name,
9 	uint32 resizeMask,
10 	uint32 flags)
11 	: BView(frame, name, resizeMask, flags)
12 {
13 }
14 
15 void HalftonePreviewView::preview(float gamma, float min, Halftone::DitherType ditherType, bool color)
16 {
17 	const color_space kColorSpace = B_RGB32;
18 	const float right = Bounds().Width();
19 	const float bottom = Bounds().Height();
20 	BRect rect(0, 0, right, bottom);
21 
22 	BBitmap testImage(rect, kColorSpace, true);
23 	BBitmap preview(rect, kColorSpace);
24 	BView view(rect, "", B_FOLLOW_ALL, B_WILL_DRAW);
25 
26 	// create test image
27 	testImage.Lock();
28 	testImage.AddChild(&view);
29 
30 	// color bars
31 	const int height = Bounds().IntegerHeight()+1;
32 	const int width  = Bounds().IntegerWidth()+1;
33 	const int delta  = height / 4;
34 	const float red_bottom   = delta - 1;
35 	const float green_bottom = red_bottom + delta;
36 	const float blue_bottom  = green_bottom + delta;
37 	const float gray_bottom  = height - 1;
38 
39 	for (int x = 0; x <= right; x ++) {
40 		uchar value = x * 255 / width;
41 
42 		BPoint from(x, 0);
43 		BPoint to(x, red_bottom);
44 		// red
45 		view.SetHighColor(255, value, value);
46 		view.StrokeLine(from, to);
47 		// green
48 		from.y = to.y+1;
49 		to.y = green_bottom;
50 		view.SetHighColor(value, 255, value);
51 		view.StrokeLine(from, to);
52 		// blue
53 		from.y = to.y+1;
54 		to.y = blue_bottom;
55 		view.SetHighColor(value, value, 255);
56 		view.StrokeLine(from, to);
57 		// gray
58 		from.y = to.y+1;
59 		to.y = gray_bottom;
60 		view.SetHighColor(value, value, value);
61 		view.StrokeLine(from, to);
62 	}
63 
64 	view.Sync();
65 	testImage.RemoveChild(&view);
66 	testImage.Unlock();
67 
68 	// create preview image
69 	Halftone halftone(kColorSpace, gamma, min, ditherType);
70 	halftone.setBlackValue(Halftone::kLowValueMeansBlack);
71 
72 	const int widthBytes = (width + 7) / 8; // byte boundary
73 	uchar* buffer = new uchar[widthBytes];
74 
75 	const uchar* src = (uchar*)testImage.Bits();
76 	uchar* dstRow = (uchar*)preview.Bits();
77 
78 	const int numPlanes = color ? 3 : 1;
79 	if (color) {
80 		halftone.setPlanes(Halftone::kPlaneRGB1);
81 	}
82 
83 	for (int y = 0; y < height; y ++) {
84 		for (int plane = 0; plane < numPlanes;  plane ++) {
85 			// halftone the preview image
86 			halftone.dither(buffer, src, 0, y, width);
87 
88 			// convert the plane(s) to RGB32
89 			ColorRGB32Little* dst = (ColorRGB32Little*)dstRow;
90 			const uchar* bitmap = buffer;
91 			for (int x = 0; x < width; x ++, dst ++) {
92 				const int bit = 7 - (x % 8);
93 				const bool isSet = (*bitmap & (1 << bit)) != 0;
94 				uchar value = isSet ? 255 : 0;
95 
96 				if (color) {
97 					switch (plane) {
98 						case 0: dst->red = value;
99 							break;
100 						case 1: dst->green = value;
101 							break;
102 						case 2: dst->blue = value;
103 							break;
104 					}
105 				} else {
106 					dst->red = dst->green = dst->blue = value;
107 				}
108 
109 				if (bit == 0) {
110 					bitmap ++;
111 				}
112 			}
113 		}
114 
115 		// next row
116 		src += testImage.BytesPerRow();
117 		dstRow += preview.BytesPerRow();
118 	}
119 
120 	delete buffer;
121 
122 	SetViewBitmap(&preview);
123 	Invalidate();
124 }
125 
126 HalftoneView::HalftoneView(
127 	BRect frame,
128 	const char* name,
129 	uint32 resizeMask,
130 	uint32 flags)
131 	: BView(frame, name, resizeMask, flags)
132 {
133 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
134 
135 	BRect r(frame);
136 	float size, max;
137 
138 	r.OffsetTo(0, 0);
139 	const int height = r.IntegerHeight()+1;
140 	const int delta  = height / 4;
141 	const float red_top   = 0;
142 	const float green_top = delta;
143 	const float blue_top  = green_top + delta;
144 	const float gray_top  = r.bottom - delta;
145 
146 	const char* kRedLabel   = "Red: ";
147 	const char* kGreenLabel = "Green: ";
148 	const char* kBlueLabel  = "Blue: ";
149 	const char* kGrayLabel  = "Black: ";
150 
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 void HalftoneView::preview(float gamma, float min, Halftone::DitherType ditherType, bool color)
191 {
192 	fPreview->preview(gamma, min, ditherType, color);
193 }
194