23#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
24#define BigEndianToNative16(x) __builtin_bswap16(x)
25#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
26#define BigEndianToNative16(x) (x)
29#define BigEndianToNative16(x) ntohs(x)
33#include <ApplicationServices/ApplicationServices.h>
34#include <CoreFoundation/CoreFoundation.h>
35#include <CoreGraphics/CoreGraphics.h>
36#elif defined(WIN32) && !defined(_ISOC99_SOURCE)
47static const uint8_t palette[256] = {
67#define LABEL_MAX_WIDTH 340
68#define LABEL_MAX_HEIGHT 12
69#define LABEL_TYPE_PALETTED 1
70#define LABEL_TYPE_BGRA 2
103static CTLineRef create_text_line(CGColorSpaceRef color_space,
const char *str,
int scale) {
105 const CGFloat components[] = {
106 (CGFloat)1.0, (CGFloat)1.0
109 CTFontRef font_ref = CTFontCreateWithName(CFSTR(
"Helvetica"), 10.0 * scale, NULL);
110 CGColorRef color = CGColorCreate(color_space, components);
111 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault,
112 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
114 CTLineRef result = NULL;
116 if (font_ref != NULL && color != NULL && dict != NULL) {
117 CFDictionarySetValue(dict, kCTForegroundColorAttributeName, color);
118 CFDictionarySetValue(dict, kCTFontAttributeName, font_ref);
120 CFStringRef tmp = CFStringCreateWithCString(kCFAllocatorDefault, str, kCFStringEncodingUTF8);
122 CFAttributedStringRef attr_tmp = CFAttributedStringCreate(kCFAllocatorDefault, tmp, dict);
123 if (attr_tmp != NULL) {
124 result = CTLineCreateWithAttributedString(attr_tmp);
139 if (font_ref != NULL) {
146static int render_label(
const char *label,
uint8_t *bitmap_data,
149 CGColorSpaceRef color_space = CGColorSpaceCreateDeviceGray();
150 if (color_space == NULL) {
151 fprintf(stderr,
"Could not obtain color space\n");
155 CTLineRef line = create_text_line(color_space, label, scale);
157 fprintf(stderr,
"Could not render text line\n");
158 CGColorSpaceRelease(color_space);
162 CGContextRef context = CGBitmapContextCreate(bitmap_data,
width,
height,
163 8,
width, color_space, kCGImageAlphaNone);
165 if(context == NULL) {
166 fprintf(stderr,
"Could not init CoreGraphics context\n");
168 CGColorSpaceRelease(color_space);
172 CGRect rect = CTLineGetImageBounds(line, context);
173 CGContextSetTextPosition(context, 2.0 * scale, 2.0 * scale);
174 CTLineDraw(line, context);
175 CGContextFlush(context);
178 *newwidth = (
uint16_t)(rect.size.width + 4 * scale);
180 CGContextRelease(context);
181 CGColorSpaceRelease(color_space);
185static void *make_label(
const char *label,
int scale,
bool bgra,
uint16_t *label_size) {
189 if (label_data == NULL) {
190 fprintf(stderr,
"Label allocation failure\n");
195 int err = render_label(label, label_data->
data,
width,
height, scale, &newwidth);
202 if (newwidth >
width) {
203 fprintf(stderr,
"Label %s with %d pixels does not fit in %d pixels\n", label, newwidth,
width);
213 label_data->
width = htons(newwidth);
222 label_data->
data[index * 4 + 0] = 0;
223 label_data->
data[index * 4 + 1] = 0;
224 label_data->
data[index * 4 + 2] = 0;
225 label_data->
data[index * 4 + 3] = 0xFF - alpha;
230 label_data->
data[i] = clut[label_data->
data[i] >> 4U];
239static int write_file(
const char *filename,
uint8_t *buffer,
size_t size) {
240 FILE *fh = fopen(filename,
"wb+");
242 fprintf(stderr,
"Cannot open file %s for writing!\n", filename);
246 if (fwrite(buffer,
size, 1, fh) != 1) {
247 fprintf(stderr,
"Cannot write %zu bytes in %s!\n",
size, filename);
257static int read_file(
const char *filename,
uint8_t **buffer,
size_t *
size) {
258 FILE *fh = fopen(filename,
"rb");
260 fprintf(stderr,
"Missing file %s!\n", filename);
264 if (fseek(fh, 0, SEEK_END)) {
265 fprintf(stderr,
"Failed to find end of %s!\n", filename);
270 long pos = ftell(fh);
273 fprintf(stderr,
"Invalid file size (%ld) of %s!\n", pos, filename);
278 if (fseek(fh, 0, SEEK_SET)) {
279 fprintf(stderr,
"Failed to rewind %s!\n", filename);
288 fprintf(stderr,
"Failed to allocate %zu bytes for %s!\n", *
size, filename);
293 if (fread(*buffer, *
size, 1, fh) != 1) {
294 fprintf(stderr,
"Failed to read %zu bytes from %s!\n", *
size, filename);
304static int write_ppm(
const char *filename,
size_t width,
size_t height,
uint8_t *pixel,
bool bgra) {
305 FILE *fh = fopen(filename,
"wb");
307 fprintf(stderr,
"Failed to open out file %s!\n", filename);
312 if (fprintf(fh,
"P7\nWIDTH %zu\nHEIGHT %zu\nDEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n",
width,
height) < 0) {
313 fprintf(stderr,
"Failed to write ppm header to %s!\n", filename);
319 for (
size_t x = 0;
x <
width; ++
x) {
325 col[3] = 0xFF - pixel[3];
329 col[0] = col[1] = col[2] = 0;
331 col[3] = palette[*pixel];
334 if (fwrite(col,
sizeof(col), 1, fh) != 1) {
335 fprintf(stderr,
"Failed to write ppm pixel %zux%zu to %s!\n",
x,
y, filename);
347static int decode_label(
const char *infile,
const char *outfile) {
351 if (read_file(infile, (
uint8_t **) &label, &
size)) {
356 fprintf(stderr,
"Too low size %zu!\n",
size);
362 fprintf(stderr,
"Invalid version %02X!\n", label->type);
373 exp_size *= SIZE_MAX / 4 >= exp_size ? 4 : 0;
377 fprintf(stderr,
"Image type %d mismatch %zux%zu with size %zu!\n", label->type,
width,
height,
size);
382 (void)remove(outfile);
384 int ret = write_ppm(outfile,
width,
height, label->data, bgra);
389static int encode_label(
const char *label,
bool bgra,
const char *outfile,
const char *outfile2x) {
391 for (
int scale = 1; scale <= 2; scale++) {
392 const char *filename = scale == 1 ? outfile : outfile2x;
394 void *label_data = make_label(label, scale, bgra, &label_size);
395 bool ok = label_data != NULL && write_file(filename, label_data, label_size) == 0;
407 fprintf(stderr,
"Encoding labels is unsupported!\n");
412int main(
int argc,
char *argv[]) {
413 if (argc == 4 && strcmp(argv[1],
"-d") == 0) {
414 return decode_label(argv[2], argv[3]);
417 if (argc == 5 && strcmp(argv[1],
"-e") == 0) {
418 return encode_label(argv[2],
false, argv[3], argv[4]);
421 if (argc == 5 && strcmp(argv[1],
"-bgra") == 0) {
422 return encode_label(argv[2],
true, argv[3], argv[4]);
427 " disklabel -d .disk_label image.ppm!\n"
428 " disklabel -e \"Label\" .disk_label .disk_label_2x\n"
429 " disklabel -bgra \"Label\" .disk_label .disk_label_2x\n");
struct DiskLabel_ DiskLabel
#define BigEndianToNative16(x)
#define LABEL_TYPE_PALETTED
#define memmove(dst, src, len)