xref: /haiku/src/libs/print/libprint/HalftoneView.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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