diff options
-rw-r--r-- | utils/wpseditor/buildall.bat | 18 | ||||
-rwxr-xr-x | utils/wpseditor/buildall.sh | 8 | ||||
-rw-r--r-- | utils/wpseditor/gui/src/qsyntaxer.cpp | 88 | ||||
-rw-r--r-- | utils/wpseditor/gui/src/qsyntaxer.h | 42 | ||||
-rw-r--r-- | utils/wpseditor/libwps/buildall.bat | 8 | ||||
-rw-r--r-- | utils/wpseditor/screenshot/Makefile | 43 | ||||
-rw-r--r-- | utils/wpseditor/screenshot/bmp.h | 114 | ||||
-rw-r--r-- | utils/wpseditor/screenshot/gd_bmp.c | 778 | ||||
-rw-r--r-- | utils/wpseditor/screenshot/main.c | 361 |
9 files changed, 1378 insertions, 82 deletions
diff --git a/utils/wpseditor/buildall.bat b/utils/wpseditor/buildall.bat index c550a30850..b813a38510 100644 --- a/utils/wpseditor/buildall.bat +++ b/utils/wpseditor/buildall.bat | |||
@@ -1,9 +1,9 @@ | |||
1 | @echo off | 1 | @echo off |
2 | echo qmake... | 2 | echo qmake... |
3 | qmake | 3 | qmake |
4 | echo Building gui... | 4 | echo Building gui... |
5 | mingw32-make 1>nul | 5 | mingw32-make 1>nul |
6 | echo Building libs... | 6 | echo Building libs... |
7 | cd libwps | 7 | cd libwps |
8 | call buildall.bat 2>nul | 8 | call buildall.bat 2>nul |
9 | cd .. | 9 | cd .. |
diff --git a/utils/wpseditor/buildall.sh b/utils/wpseditor/buildall.sh index 2539ba2161..c891900813 100755 --- a/utils/wpseditor/buildall.sh +++ b/utils/wpseditor/buildall.sh | |||
@@ -1,4 +1,4 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | qmake && make | 2 | qmake && make |
3 | cd libwps | 3 | cd libwps |
4 | ./buildall.sh 2> /dev/null | 4 | ./buildall.sh 2> /dev/null |
diff --git a/utils/wpseditor/gui/src/qsyntaxer.cpp b/utils/wpseditor/gui/src/qsyntaxer.cpp index 412ca38148..fa2608be45 100644 --- a/utils/wpseditor/gui/src/qsyntaxer.cpp +++ b/utils/wpseditor/gui/src/qsyntaxer.cpp | |||
@@ -1,44 +1,44 @@ | |||
1 | #include <QTextCharFormat> | 1 | #include <QTextCharFormat> |
2 | 2 | ||
3 | #include "qsyntaxer.h" | 3 | #include "qsyntaxer.h" |
4 | 4 | ||
5 | QSyntaxer::QSyntaxer(QTextDocument *parent) | 5 | QSyntaxer::QSyntaxer(QTextDocument *parent) |
6 | : QSyntaxHighlighter(parent) { | 6 | : QSyntaxHighlighter(parent) { |
7 | HighlightingRule rule; | 7 | HighlightingRule rule; |
8 | 8 | ||
9 | hrules["operator"].pattern = QRegExp("%[^\\| \n<\\?%]{1,2}"); | 9 | hrules["operator"].pattern = QRegExp("%[^\\| \n<\\?%]{1,2}"); |
10 | hrules["operator"].format.setFontWeight(QFont::Bold); | 10 | hrules["operator"].format.setFontWeight(QFont::Bold); |
11 | hrules["operator"].format.setForeground(Qt::darkBlue); | 11 | hrules["operator"].format.setForeground(Qt::darkBlue); |
12 | 12 | ||
13 | 13 | ||
14 | hrules["question"].pattern = QRegExp("%[\\?]{1}[^<]{1,2}"); | 14 | hrules["question"].pattern = QRegExp("%[\\?]{1}[^<]{1,2}"); |
15 | hrules["question"].format.setForeground(Qt::darkMagenta); | 15 | hrules["question"].format.setForeground(Qt::darkMagenta); |
16 | 16 | ||
17 | hrules["question2"].pattern = QRegExp("(<|>)"); | 17 | hrules["question2"].pattern = QRegExp("(<|>)"); |
18 | hrules["question2"].format.setForeground(Qt::red); | 18 | hrules["question2"].format.setForeground(Qt::red); |
19 | 19 | ||
20 | 20 | ||
21 | hrules["limiter"].pattern = QRegExp("\\|"); | 21 | hrules["limiter"].pattern = QRegExp("\\|"); |
22 | hrules["limiter"].format.setForeground(Qt::darkRed); | 22 | hrules["limiter"].format.setForeground(Qt::darkRed); |
23 | 23 | ||
24 | hrules["comment"].pattern = QRegExp("#[^\n]*"); | 24 | hrules["comment"].pattern = QRegExp("#[^\n]*"); |
25 | hrules["comment"].format.setForeground(Qt::darkGreen); | 25 | hrules["comment"].format.setForeground(Qt::darkGreen); |
26 | hrules["comment"].format.setFontItalic(true); | 26 | hrules["comment"].format.setFontItalic(true); |
27 | } | 27 | } |
28 | // | 28 | // |
29 | void QSyntaxer::highlightBlock(const QString &text) { | 29 | void QSyntaxer::highlightBlock(const QString &text) { |
30 | QTextCharFormat wholeText; | 30 | QTextCharFormat wholeText; |
31 | wholeText.setFont(QFont("arial",11,QFont::Normal)); | 31 | wholeText.setFont(QFont("arial",11,QFont::Normal)); |
32 | setFormat(0,text.length(),wholeText); | 32 | setFormat(0,text.length(),wholeText); |
33 | 33 | ||
34 | foreach (HighlightingRule rule, hrules) { | 34 | foreach (HighlightingRule rule, hrules) { |
35 | QRegExp expression(rule.pattern); | 35 | QRegExp expression(rule.pattern); |
36 | int index = text.indexOf(expression); | 36 | int index = text.indexOf(expression); |
37 | while (index >= 0) { | 37 | while (index >= 0) { |
38 | int length = expression.matchedLength(); | 38 | int length = expression.matchedLength(); |
39 | setFormat(index, length, rule.format); | 39 | setFormat(index, length, rule.format); |
40 | index = text.indexOf(expression, index + length); | 40 | index = text.indexOf(expression, index + length); |
41 | } | 41 | } |
42 | } | 42 | } |
43 | 43 | ||
44 | } | 44 | } |
diff --git a/utils/wpseditor/gui/src/qsyntaxer.h b/utils/wpseditor/gui/src/qsyntaxer.h index 9cecd3e5ed..b85651cf69 100644 --- a/utils/wpseditor/gui/src/qsyntaxer.h +++ b/utils/wpseditor/gui/src/qsyntaxer.h | |||
@@ -1,21 +1,21 @@ | |||
1 | #ifndef QSYNTAXER_H | 1 | #ifndef QSYNTAXER_H |
2 | #define QSYNTAXER_H | 2 | #define QSYNTAXER_H |
3 | // | 3 | // |
4 | #include <QSyntaxHighlighter> | 4 | #include <QSyntaxHighlighter> |
5 | 5 | ||
6 | class QTextCharFormat; | 6 | class QTextCharFormat; |
7 | 7 | ||
8 | class QSyntaxer : public QSyntaxHighlighter { | 8 | class QSyntaxer : public QSyntaxHighlighter { |
9 | Q_OBJECT | 9 | Q_OBJECT |
10 | struct HighlightingRule { | 10 | struct HighlightingRule { |
11 | QRegExp pattern; | 11 | QRegExp pattern; |
12 | QTextCharFormat format; | 12 | QTextCharFormat format; |
13 | }; | 13 | }; |
14 | QMap<QString,HighlightingRule> hrules; | 14 | QMap<QString,HighlightingRule> hrules; |
15 | public: | 15 | public: |
16 | QSyntaxer(QTextDocument *parent = 0); | 16 | QSyntaxer(QTextDocument *parent = 0); |
17 | 17 | ||
18 | protected: | 18 | protected: |
19 | void highlightBlock(const QString &text); | 19 | void highlightBlock(const QString &text); |
20 | }; | 20 | }; |
21 | #endif | 21 | #endif |
diff --git a/utils/wpseditor/libwps/buildall.bat b/utils/wpseditor/libwps/buildall.bat index c545453934..fb66b41904 100644 --- a/utils/wpseditor/libwps/buildall.bat +++ b/utils/wpseditor/libwps/buildall.bat | |||
@@ -1,4 +1,4 @@ | |||
1 | @echo off | 1 | @echo off |
2 | FOR /F "tokens=1,2* delims=, " %%i in (targets.txt) do @mingw32-make MODEL=%%j TARGET=%%i build 2>nul | 2 | FOR /F "tokens=1,2* delims=, " %%i in (targets.txt) do @mingw32-make MODEL=%%j TARGET=%%i build 2>nul |
3 | echo Copying files... | 3 | echo Copying files... |
4 | xcopy /I /Y *.dll ..\gui\bin | 4 | xcopy /I /Y *.dll ..\gui\bin |
diff --git a/utils/wpseditor/screenshot/Makefile b/utils/wpseditor/screenshot/Makefile new file mode 100644 index 0000000000..18a6de35a5 --- /dev/null +++ b/utils/wpseditor/screenshot/Makefile | |||
@@ -0,0 +1,43 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | ROOT=../../.. | ||
10 | |||
11 | OS = w32 | ||
12 | CC = gcc | ||
13 | |||
14 | ifeq ($(findstring MINGW,$(shell uname)),MINGW) | ||
15 | OS = w32 | ||
16 | CC = mingw32-gcc | ||
17 | RM = rm | ||
18 | endif | ||
19 | |||
20 | ifeq ($(findstring Linux,$(shell uname)),Linux) | ||
21 | OS = linux | ||
22 | CC = gcc | ||
23 | RM = rm -f | ||
24 | endif | ||
25 | |||
26 | |||
27 | |||
28 | COMMON= main.c gd_bmp.c | ||
29 | |||
30 | INCLUDE=-I ../libwps/src \ | ||
31 | -I $(ROOT)/apps/gui \ | ||
32 | -I $(ROOT)/firmware/export \ | ||
33 | -I $(ROOT)/apps/recorder \ | ||
34 | -I $(ROOT)/apps \ | ||
35 | -I . | ||
36 | |||
37 | CFLAGS = -g -Wall | ||
38 | |||
39 | all: | ||
40 | $(CC) $(INCLUDE) $(CFLAGS) $(COMMON) -rdynamic -ldl -lgd -lpng -o screenshot | ||
41 | |||
42 | clean: | ||
43 | $(RM) screenshot | ||
diff --git a/utils/wpseditor/screenshot/bmp.h b/utils/wpseditor/screenshot/bmp.h new file mode 100644 index 0000000000..71d5a4a5bc --- /dev/null +++ b/utils/wpseditor/screenshot/bmp.h | |||
@@ -0,0 +1,114 @@ | |||
1 | /* $Id$ */ | ||
2 | #ifdef __cplusplus | ||
3 | extern "C" { | ||
4 | #endif | ||
5 | |||
6 | /* | ||
7 | gd_bmp.c | ||
8 | |||
9 | Bitmap format support for libgd | ||
10 | |||
11 | * Written 2007, Scott MacVicar | ||
12 | --------------------------------------------------------------------------- | ||
13 | |||
14 | Todo: | ||
15 | |||
16 | RLE4, RLE8 and Bitfield encoding | ||
17 | Add full support for Windows v4 and Windows v5 header formats | ||
18 | |||
19 | ---------------------------------------------------------------------------- | ||
20 | */ | ||
21 | |||
22 | #ifndef BMP_H | ||
23 | #define BMP_H 1 | ||
24 | |||
25 | #define BMP_PALETTE_3 1 | ||
26 | #define BMP_PALETTE_4 2 | ||
27 | |||
28 | #define BMP_WINDOWS_V3 40 | ||
29 | #define BMP_OS2_V1 12 | ||
30 | #define BMP_OS2_V2 64 | ||
31 | #define BMP_WINDOWS_V4 108 | ||
32 | #define BMP_WINDOWS_V5 124 | ||
33 | |||
34 | #define BMP_BI_RGB 0 | ||
35 | #define BMP_BI_RLE8 1 | ||
36 | #define BMP_BI_RLE4 2 | ||
37 | #define BMP_BI_BITFIELDS 3 | ||
38 | #define BMP_BI_JPEG 4 | ||
39 | #define BMP_BI_PNG 5 | ||
40 | |||
41 | #define BMP_RLE_COMMAND 0 | ||
42 | #define BMP_RLE_ENDOFLINE 0 | ||
43 | #define BMP_RLE_ENDOFBITMAP 1 | ||
44 | #define BMP_RLE_DELTA 2 | ||
45 | |||
46 | #define BMP_RLE_TYPE_RAW 0 | ||
47 | #define BMP_RLE_TYPE_RLE 1 | ||
48 | |||
49 | /* BMP header. */ | ||
50 | typedef struct | ||
51 | { | ||
52 | /* 16 bit - header identifying the type */ | ||
53 | signed short int magic; | ||
54 | |||
55 | /* 32bit - size of the file */ | ||
56 | int size; | ||
57 | |||
58 | /* 16bit - these two are in the spec but "reserved" */ | ||
59 | signed short int reserved1; | ||
60 | signed short int reserved2; | ||
61 | |||
62 | /* 32 bit - offset of the bitmap header from data in bytes */ | ||
63 | signed int off; | ||
64 | |||
65 | } bmp_hdr_t; | ||
66 | |||
67 | /* BMP info. */ | ||
68 | typedef struct | ||
69 | { | ||
70 | /* 16bit - Type, ie Windows or OS/2 for the palette info */ | ||
71 | signed short int type; | ||
72 | /* 32bit - The length of the bitmap information header in bytes. */ | ||
73 | signed int len; | ||
74 | |||
75 | /* 32bit - The width of the bitmap in pixels. */ | ||
76 | signed int width; | ||
77 | |||
78 | /* 32bit - The height of the bitmap in pixels. */ | ||
79 | signed int height; | ||
80 | |||
81 | /* 8 bit - The bitmap data is specified in top-down order. */ | ||
82 | signed char topdown; | ||
83 | |||
84 | /* 16 bit - The number of planes. This must be set to a value of one. */ | ||
85 | signed short int numplanes; | ||
86 | |||
87 | /* 16 bit - The number of bits per pixel. */ | ||
88 | signed short int depth; | ||
89 | |||
90 | /* 32bit - The type of compression used. */ | ||
91 | signed int enctype; | ||
92 | |||
93 | /* 32bit - The size of the image in bytes. */ | ||
94 | signed int size; | ||
95 | |||
96 | /* 32bit - The horizontal resolution in pixels/metre. */ | ||
97 | signed int hres; | ||
98 | |||
99 | /* 32bit - The vertical resolution in pixels/metre. */ | ||
100 | signed int vres; | ||
101 | |||
102 | /* 32bit - The number of color indices used by the bitmap. */ | ||
103 | signed int numcolors; | ||
104 | |||
105 | /* 32bit - The number of color indices important for displaying the bitmap. */ | ||
106 | signed int mincolors; | ||
107 | |||
108 | } bmp_info_t; | ||
109 | |||
110 | #endif | ||
111 | |||
112 | #ifdef __cplusplus | ||
113 | } | ||
114 | #endif | ||
diff --git a/utils/wpseditor/screenshot/gd_bmp.c b/utils/wpseditor/screenshot/gd_bmp.c new file mode 100644 index 0000000000..8fe737da03 --- /dev/null +++ b/utils/wpseditor/screenshot/gd_bmp.c | |||
@@ -0,0 +1,778 @@ | |||
1 | /* | ||
2 | Stolen from http://cvs.php.net/viewcvs.cgi/gd/playground/gdbmp/ | ||
3 | */ | ||
4 | |||
5 | /* | ||
6 | gd_bmp.c | ||
7 | |||
8 | Bitmap format support for libgd | ||
9 | |||
10 | * Written 2007, Scott MacVicar | ||
11 | --------------------------------------------------------------------------- | ||
12 | |||
13 | Todo: | ||
14 | |||
15 | Bitfield encoding | ||
16 | |||
17 | ---------------------------------------------------------------------------- | ||
18 | */ | ||
19 | /* $Id$ */ | ||
20 | #ifdef HAVE_CONFIG_H | ||
21 | #include "config.h" | ||
22 | #endif | ||
23 | |||
24 | #include <stdio.h> | ||
25 | #include <math.h> | ||
26 | #include <string.h> | ||
27 | #include <stdlib.h> | ||
28 | #include "gd.h" | ||
29 | #include "bmp.h" | ||
30 | |||
31 | extern void* gdCalloc (size_t nmemb, size_t size); | ||
32 | |||
33 | static int bmp_read_header(gdIOCtxPtr infile, bmp_hdr_t *hdr); | ||
34 | static int bmp_read_info(gdIOCtxPtr infile, bmp_info_t *info); | ||
35 | static int bmp_read_windows_v3_info(gdIOCtxPtr infile, bmp_info_t *info); | ||
36 | static int bmp_read_os2_v1_info(gdIOCtxPtr infile, bmp_info_t *info); | ||
37 | static int bmp_read_os2_v2_info(gdIOCtxPtr infile, bmp_info_t *info); | ||
38 | |||
39 | static int bmp_read_direct(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header); | ||
40 | static int bmp_read_1bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header); | ||
41 | static int bmp_read_4bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header); | ||
42 | static int bmp_read_8bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header); | ||
43 | static int bmp_read_rle(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info); | ||
44 | |||
45 | #if GD_MAJOR_VERSION == 2 && GD_MINOR_VERSION < 1 | ||
46 | /* Byte helper functions, since added to GD 2.1 */ | ||
47 | static int gdGetIntLSB(signed int *result, gdIOCtx * ctx); | ||
48 | static int gdGetWordLSB(signed short int *result, gdIOCtx * ctx); | ||
49 | #endif | ||
50 | |||
51 | #define BMP_DEBUG(s) | ||
52 | |||
53 | gdImagePtr gdImageCreateFromBmpCtx(gdIOCtxPtr infile); | ||
54 | |||
55 | gdImagePtr gdImageCreateFromBmp(FILE * inFile) | ||
56 | { | ||
57 | gdImagePtr im = 0; | ||
58 | gdIOCtx *in = gdNewFileCtx(inFile); | ||
59 | im = gdImageCreateFromBmpCtx(in); | ||
60 | in->gd_free(in); | ||
61 | return im; | ||
62 | } | ||
63 | |||
64 | gdImagePtr gdImageCreateFromBmpPtr(int size, void *data) | ||
65 | { | ||
66 | gdImagePtr im; | ||
67 | gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0); | ||
68 | im = gdImageCreateFromBmpCtx(in); | ||
69 | in->gd_free(in); | ||
70 | return im; | ||
71 | } | ||
72 | |||
73 | gdImagePtr gdImageCreateFromBmpCtx(gdIOCtxPtr infile) | ||
74 | { | ||
75 | bmp_hdr_t *hdr; | ||
76 | bmp_info_t *info; | ||
77 | gdImagePtr im = NULL; | ||
78 | int error = 0; | ||
79 | |||
80 | if (!(hdr= (bmp_hdr_t *)gdCalloc(1, sizeof(bmp_hdr_t)))) { | ||
81 | return NULL; | ||
82 | } | ||
83 | |||
84 | if (bmp_read_header(infile, hdr)) { | ||
85 | gdFree(hdr); | ||
86 | return NULL; | ||
87 | } | ||
88 | |||
89 | if (hdr->magic != 0x4d42) { | ||
90 | gdFree(hdr); | ||
91 | return NULL; | ||
92 | } | ||
93 | |||
94 | if (!(info = (bmp_info_t *)gdCalloc(1, sizeof(bmp_info_t)))) { | ||
95 | gdFree(hdr); | ||
96 | return NULL; | ||
97 | } | ||
98 | |||
99 | if (bmp_read_info(infile, info)) { | ||
100 | gdFree(hdr); | ||
101 | gdFree(info); | ||
102 | return NULL; | ||
103 | } | ||
104 | |||
105 | BMP_DEBUG(printf("Numcolours: %d\n", info->numcolors)); | ||
106 | BMP_DEBUG(printf("Width: %d\n", info->width)); | ||
107 | BMP_DEBUG(printf("Height: %d\n", info->height)); | ||
108 | BMP_DEBUG(printf("Planes: %d\n", info->numplanes)); | ||
109 | BMP_DEBUG(printf("Depth: %d\n", info->depth)); | ||
110 | BMP_DEBUG(printf("Offset: %d\n", hdr->off)); | ||
111 | |||
112 | if (info->depth >= 16) { | ||
113 | im = gdImageCreateTrueColor(info->width, info->height); | ||
114 | } else { | ||
115 | im = gdImageCreate(info->width, info->height); | ||
116 | } | ||
117 | |||
118 | if (!im) { | ||
119 | gdFree(hdr); | ||
120 | gdFree(info); | ||
121 | return NULL; | ||
122 | } | ||
123 | |||
124 | switch (info->depth) { | ||
125 | case 1: | ||
126 | BMP_DEBUG(printf("1-bit image\n")); | ||
127 | error = bmp_read_1bit(im, infile, info, hdr); | ||
128 | break; | ||
129 | case 4: | ||
130 | BMP_DEBUG(printf("4-bit image\n")); | ||
131 | error = bmp_read_4bit(im, infile, info, hdr); | ||
132 | break; | ||
133 | case 8: | ||
134 | BMP_DEBUG(printf("8-bit image\n")); | ||
135 | error = bmp_read_8bit(im, infile, info, hdr); | ||
136 | break; | ||
137 | case 16: | ||
138 | case 24: | ||
139 | case 32: | ||
140 | BMP_DEBUG(printf("Direct BMP image\n")); | ||
141 | error = bmp_read_direct(im, infile, info, hdr); | ||
142 | break; | ||
143 | default: | ||
144 | BMP_DEBUG(printf("Unknown bit count\n")); | ||
145 | error = 1; | ||
146 | } | ||
147 | |||
148 | gdFree(hdr); | ||
149 | gdFree(info); | ||
150 | |||
151 | if (error) { | ||
152 | gdImageDestroy(im); | ||
153 | return NULL; | ||
154 | } | ||
155 | |||
156 | return im; | ||
157 | } | ||
158 | |||
159 | static int bmp_read_header(gdIOCtx *infile, bmp_hdr_t *hdr) | ||
160 | { | ||
161 | if( | ||
162 | !gdGetWordLSB(&hdr->magic, infile) || | ||
163 | !gdGetIntLSB(&hdr->size, infile) || | ||
164 | !gdGetWordLSB(&hdr->reserved1, infile) || | ||
165 | !gdGetWordLSB(&hdr->reserved2 , infile) || | ||
166 | !gdGetIntLSB(&hdr->off , infile) | ||
167 | ) { | ||
168 | return 1; | ||
169 | } | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static int bmp_read_info(gdIOCtx *infile, bmp_info_t *info) | ||
174 | { | ||
175 | /* read BMP length so we can work out the version */ | ||
176 | if (!gdGetIntLSB(&info->len, infile)) { | ||
177 | return 1; | ||
178 | } | ||
179 | |||
180 | switch (info->len) { | ||
181 | /* For now treat Windows v4 + v5 as v3 */ | ||
182 | case BMP_WINDOWS_V3: | ||
183 | case BMP_WINDOWS_V4: | ||
184 | case BMP_WINDOWS_V5: | ||
185 | BMP_DEBUG(printf("Reading Windows Header\n")); | ||
186 | if (bmp_read_windows_v3_info(infile, info)) { | ||
187 | return 1; | ||
188 | } | ||
189 | break; | ||
190 | case BMP_OS2_V1: | ||
191 | if (bmp_read_os2_v1_info(infile, info)) { | ||
192 | return 1; | ||
193 | } | ||
194 | break; | ||
195 | case BMP_OS2_V2: | ||
196 | if (bmp_read_os2_v2_info(infile, info)) { | ||
197 | return 1; | ||
198 | } | ||
199 | break; | ||
200 | default: | ||
201 | BMP_DEBUG(printf("Unhandled bitmap\n")); | ||
202 | return 1; | ||
203 | } | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static int bmp_read_windows_v3_info(gdIOCtxPtr infile, bmp_info_t *info) | ||
208 | { | ||
209 | if ( | ||
210 | !gdGetIntLSB(&info->width, infile) || | ||
211 | !gdGetIntLSB(&info->height, infile) || | ||
212 | !gdGetWordLSB(&info->numplanes, infile) || | ||
213 | !gdGetWordLSB(&info->depth, infile) || | ||
214 | !gdGetIntLSB(&info->enctype, infile) || | ||
215 | !gdGetIntLSB(&info->size, infile) || | ||
216 | !gdGetIntLSB(&info->hres, infile) || | ||
217 | !gdGetIntLSB(&info->vres, infile) || | ||
218 | !gdGetIntLSB(&info->numcolors, infile) || | ||
219 | !gdGetIntLSB(&info->mincolors, infile) | ||
220 | ) { | ||
221 | return 1; | ||
222 | } | ||
223 | |||
224 | if (info->height < 0) { | ||
225 | info->topdown = 1; | ||
226 | info->height = -info->height; | ||
227 | } else { | ||
228 | info->topdown = 0; | ||
229 | } | ||
230 | |||
231 | info->type = BMP_PALETTE_4; | ||
232 | |||
233 | if (info->width <= 0 || info->height <= 0 || info->numplanes <= 0 || | ||
234 | info->depth <= 0 || info->numcolors < 0 || info->mincolors < 0) { | ||
235 | return 1; | ||
236 | } | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int bmp_read_os2_v1_info(gdIOCtxPtr infile, bmp_info_t *info) | ||
242 | { | ||
243 | if ( | ||
244 | !gdGetWordLSB((signed short int *)&info->width, infile) || | ||
245 | !gdGetWordLSB((signed short int *)&info->height, infile) || | ||
246 | !gdGetWordLSB(&info->numplanes, infile) || | ||
247 | !gdGetWordLSB(&info->depth, infile) | ||
248 | ) { | ||
249 | return 1; | ||
250 | } | ||
251 | |||
252 | /* OS2 v1 doesn't support topdown */ | ||
253 | info->topdown = 0; | ||
254 | |||
255 | info->numcolors = 1 << info->depth; | ||
256 | info->type = BMP_PALETTE_3; | ||
257 | |||
258 | if (info->width <= 0 || info->height <= 0 || info->numplanes <= 0 || | ||
259 | info->depth <= 0 || info->numcolors < 0) { | ||
260 | return 1; | ||
261 | } | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int bmp_read_os2_v2_info(gdIOCtxPtr infile, bmp_info_t *info) | ||
267 | { | ||
268 | char useless_bytes[24]; | ||
269 | if ( | ||
270 | !gdGetIntLSB(&info->width, infile) || | ||
271 | !gdGetIntLSB(&info->height, infile) || | ||
272 | !gdGetWordLSB(&info->numplanes, infile) || | ||
273 | !gdGetWordLSB(&info->depth, infile) || | ||
274 | !gdGetIntLSB(&info->enctype, infile) || | ||
275 | !gdGetIntLSB(&info->size, infile) || | ||
276 | !gdGetIntLSB(&info->hres, infile) || | ||
277 | !gdGetIntLSB(&info->vres, infile) || | ||
278 | !gdGetIntLSB(&info->numcolors, infile) || | ||
279 | !gdGetIntLSB(&info->mincolors, infile) | ||
280 | ) { | ||
281 | return 1; | ||
282 | } | ||
283 | |||
284 | /* Lets seek the next 24 pointless bytes, we don't care too much about it */ | ||
285 | if (!gdGetBuf(useless_bytes, 24, infile)) { | ||
286 | return 1; | ||
287 | } | ||
288 | |||
289 | if (info->height < 0) { | ||
290 | info->topdown = 1; | ||
291 | info->height = -info->height; | ||
292 | } else { | ||
293 | info->topdown = 0; | ||
294 | } | ||
295 | |||
296 | info->type = BMP_PALETTE_4; | ||
297 | |||
298 | if (info->width <= 0 || info->height <= 0 || info->numplanes <= 0 || | ||
299 | info->depth <= 0 || info->numcolors < 0 || info->mincolors < 0) { | ||
300 | return 1; | ||
301 | } | ||
302 | |||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int bmp_read_direct(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header) | ||
308 | { | ||
309 | int ypos = 0, xpos = 0, row = 0; | ||
310 | int padding = 0, alpha = 0, red = 0, green = 0, blue = 0; | ||
311 | signed short int data = 0; | ||
312 | |||
313 | switch(info->enctype) { | ||
314 | case BMP_BI_RGB: | ||
315 | /* no-op */ | ||
316 | break; | ||
317 | |||
318 | case BMP_BI_BITFIELDS: | ||
319 | if (info->depth == 24) { | ||
320 | BMP_DEBUG(printf("Bitfield compression isn't supported for 24-bit\n")); | ||
321 | return 1; | ||
322 | } | ||
323 | BMP_DEBUG(printf("Currently no bitfield support\n")); | ||
324 | return 1; | ||
325 | break; | ||
326 | |||
327 | case BMP_BI_RLE8: | ||
328 | if (info->depth != 8) { | ||
329 | BMP_DEBUG(printf("RLE is only valid for 8-bit images\n")); | ||
330 | return 1; | ||
331 | } | ||
332 | case BMP_BI_RLE4: | ||
333 | if (info->depth != 4) { | ||
334 | BMP_DEBUG(printf("RLE is only valid for 4-bit images\n")); | ||
335 | return 1; | ||
336 | } | ||
337 | case BMP_BI_JPEG: | ||
338 | case BMP_BI_PNG: | ||
339 | default: | ||
340 | BMP_DEBUG(printf("Unsupported BMP compression format\n")); | ||
341 | return 1; | ||
342 | } | ||
343 | |||
344 | /* There is a chance the data isn't until later, would be wierd but it is possible */ | ||
345 | if (gdTell(infile) != header->off) { | ||
346 | /* Should make sure we don't seek past the file size */ | ||
347 | gdSeek(infile, header->off); | ||
348 | } | ||
349 | |||
350 | /* The line must be divisible by 4, else its padded with NULLs */ | ||
351 | padding = ((int)(info->depth / 8) * info->width) % 4; | ||
352 | if (padding) { | ||
353 | padding = 4 - padding; | ||
354 | } | ||
355 | |||
356 | |||
357 | for (ypos = 0; ypos < info->height; ++ypos) { | ||
358 | if (info->topdown) { | ||
359 | row = ypos; | ||
360 | } else { | ||
361 | row = info->height - ypos - 1; | ||
362 | } | ||
363 | |||
364 | for (xpos = 0; xpos < info->width; xpos++) { | ||
365 | if (info->depth == 16) { | ||
366 | if (!gdGetWordLSB(&data, infile)) { | ||
367 | return 1; | ||
368 | } | ||
369 | BMP_DEBUG(printf("Data: %X\n", data)); | ||
370 | red = ((data & 0x7C00) >> 10) << 3; | ||
371 | green = ((data & 0x3E0) >> 5) << 3; | ||
372 | blue = (data & 0x1F) << 3; | ||
373 | BMP_DEBUG(printf("R: %d, G: %d, B: %d\n", red, green, blue)); | ||
374 | } else if (info->depth == 24) { | ||
375 | if (!gdGetByte(&blue, infile) || !gdGetByte(&green, infile) || !gdGetByte(&red, infile)) { | ||
376 | return 1; | ||
377 | } | ||
378 | } else { | ||
379 | if (!gdGetByte(&blue, infile) || !gdGetByte(&green, infile) || !gdGetByte(&red, infile) || !gdGetByte(&alpha, infile)) { | ||
380 | return 1; | ||
381 | } | ||
382 | } | ||
383 | /*alpha = gdAlphaMax - (alpha >> 1);*/ | ||
384 | gdImageSetPixel(im, xpos, row, gdTrueColor(red, green, blue)); | ||
385 | } | ||
386 | for (xpos = padding; xpos > 0; --xpos) { | ||
387 | if (!gdGetByte(&red, infile)) { | ||
388 | return 1; | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static int bmp_read_palette(gdImagePtr im, gdIOCtxPtr infile, int count, int read_four) | ||
397 | { | ||
398 | int i; | ||
399 | int r, g, b, z; | ||
400 | |||
401 | for (i = 0; i < count; i++) { | ||
402 | if ( | ||
403 | !gdGetByte(&r, infile) || | ||
404 | !gdGetByte(&g, infile) || | ||
405 | !gdGetByte(&b, infile) || | ||
406 | (read_four && !gdGetByte(&z, infile)) | ||
407 | ) { | ||
408 | return 1; | ||
409 | } | ||
410 | im->red[i] = r; | ||
411 | im->green[i] = g; | ||
412 | im->blue[i] = b; | ||
413 | im->open[i] = 1; | ||
414 | } | ||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | static int bmp_read_1bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header) | ||
419 | { | ||
420 | int ypos = 0, xpos = 0, row = 0, index = 0; | ||
421 | int padding = 0, current_byte = 0, bit = 0; | ||
422 | |||
423 | if (info->enctype != BMP_BI_RGB) { | ||
424 | return 1; | ||
425 | } | ||
426 | |||
427 | if (!info->numcolors) { | ||
428 | info->numcolors = 2; | ||
429 | } else if (info->numcolors < 0 || info->numcolors > 2) { | ||
430 | return 1; | ||
431 | } | ||
432 | |||
433 | if (bmp_read_palette(im, infile, info->numcolors, (info->type == BMP_PALETTE_4))) { | ||
434 | return 1; | ||
435 | } | ||
436 | |||
437 | im->colorsTotal = info->numcolors; | ||
438 | |||
439 | /* There is a chance the data isn't until later, would be wierd but it is possible */ | ||
440 | if (gdTell(infile) != header->off) { | ||
441 | /* Should make sure we don't seek past the file size */ | ||
442 | gdSeek(infile, header->off); | ||
443 | } | ||
444 | |||
445 | /* The line must be divisible by 4, else its padded with NULLs */ | ||
446 | padding = ((int)ceill(0.1 * info->width)) % 4; | ||
447 | if (padding) { | ||
448 | padding = 4 - padding; | ||
449 | } | ||
450 | |||
451 | for (ypos = 0; ypos < info->height; ++ypos) { | ||
452 | if (info->topdown) { | ||
453 | row = ypos; | ||
454 | } else { | ||
455 | row = info->height - ypos - 1; | ||
456 | } | ||
457 | |||
458 | for (xpos = 0; xpos < info->width; xpos += 8) { | ||
459 | /* Bitmaps are always aligned in bytes so we'll never overflow */ | ||
460 | if (!gdGetByte(¤t_byte, infile)) { | ||
461 | return 1; | ||
462 | } | ||
463 | |||
464 | for (bit = 0; bit < 8; bit++) { | ||
465 | index = ((current_byte & (0x80 >> bit)) != 0 ? 0x01 : 0x00); | ||
466 | if (im->open[index]) { | ||
467 | im->open[index] = 0; | ||
468 | } | ||
469 | gdImageSetPixel(im, xpos + bit, row, index); | ||
470 | /* No need to read anything extra */ | ||
471 | if ((xpos + bit) >= info->width) { | ||
472 | break; | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | |||
477 | for (xpos = padding; xpos > 0; --xpos) { | ||
478 | if (!gdGetByte(&index, infile)) { | ||
479 | return 1; | ||
480 | } | ||
481 | } | ||
482 | } | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | static int bmp_read_4bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header) | ||
487 | { | ||
488 | int ypos = 0, xpos = 0, row = 0, index = 0; | ||
489 | int padding = 0, current_byte = 0; | ||
490 | |||
491 | if (info->enctype != BMP_BI_RGB && info->enctype != BMP_BI_RLE4) { | ||
492 | return 1; | ||
493 | } | ||
494 | |||
495 | if (!info->numcolors) { | ||
496 | info->numcolors = 16; | ||
497 | } else if (info->numcolors < 0 || info->numcolors > 16) { | ||
498 | return 1; | ||
499 | } | ||
500 | |||
501 | if (bmp_read_palette(im, infile, info->numcolors, (info->type == BMP_PALETTE_4))) { | ||
502 | return 1; | ||
503 | } | ||
504 | |||
505 | im->colorsTotal = info->numcolors; | ||
506 | |||
507 | /* There is a chance the data isn't until later, would be wierd but it is possible */ | ||
508 | if (gdTell(infile) != header->off) { | ||
509 | /* Should make sure we don't seek past the file size */ | ||
510 | gdSeek(infile, header->off); | ||
511 | } | ||
512 | |||
513 | /* The line must be divisible by 4, else its padded with NULLs */ | ||
514 | padding = ((int)ceil(0.5 * info->width)) % 4; | ||
515 | if (padding) { | ||
516 | padding = 4 - padding; | ||
517 | } | ||
518 | |||
519 | switch (info->enctype) { | ||
520 | case BMP_BI_RGB: | ||
521 | for (ypos = 0; ypos < info->height; ++ypos) { | ||
522 | if (info->topdown) { | ||
523 | row = ypos; | ||
524 | } else { | ||
525 | row = info->height - ypos - 1; | ||
526 | } | ||
527 | |||
528 | for (xpos = 0; xpos < info->width; xpos += 2) { | ||
529 | if (!gdGetByte(¤t_byte, infile)) { | ||
530 | return 1; | ||
531 | } | ||
532 | |||
533 | index = (current_byte >> 4) & 0x0f; | ||
534 | if (im->open[index]) { | ||
535 | im->open[index] = 0; | ||
536 | } | ||
537 | gdImageSetPixel(im, xpos, row, index); | ||
538 | |||
539 | /* This condition may get called often, potential optimsations */ | ||
540 | if (xpos >= info->width) { | ||
541 | break; | ||
542 | } | ||
543 | |||
544 | index = current_byte & 0x0f; | ||
545 | if (im->open[index]) { | ||
546 | im->open[index] = 0; | ||
547 | } | ||
548 | gdImageSetPixel(im, xpos + 1, row, index); | ||
549 | } | ||
550 | |||
551 | for (xpos = padding; xpos > 0; --xpos) { | ||
552 | if (!gdGetByte(&index, infile)) { | ||
553 | return 1; | ||
554 | } | ||
555 | } | ||
556 | } | ||
557 | break; | ||
558 | |||
559 | case BMP_BI_RLE4: | ||
560 | if (bmp_read_rle(im, infile, info)) { | ||
561 | return 1; | ||
562 | } | ||
563 | break; | ||
564 | |||
565 | default: | ||
566 | return 1; | ||
567 | } | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static int bmp_read_8bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp_hdr_t *header) | ||
572 | { | ||
573 | int ypos = 0, xpos = 0, row = 0, index = 0; | ||
574 | int padding = 0; | ||
575 | |||
576 | if (info->enctype != BMP_BI_RGB && info->enctype != BMP_BI_RLE8) { | ||
577 | return 1; | ||
578 | } | ||
579 | |||
580 | if (!info->numcolors) { | ||
581 | info->numcolors = 256; | ||
582 | } else if (info->numcolors < 0 || info->numcolors > 256) { | ||
583 | return 1; | ||
584 | } | ||
585 | |||
586 | if (bmp_read_palette(im, infile, info->numcolors, (info->type == BMP_PALETTE_4))) { | ||
587 | return 1; | ||
588 | } | ||
589 | |||
590 | im->colorsTotal = info->numcolors; | ||
591 | |||
592 | /* There is a chance the data isn't until later, would be wierd but it is possible */ | ||
593 | if (gdTell(infile) != header->off) { | ||
594 | /* Should make sure we don't seek past the file size */ | ||
595 | gdSeek(infile, header->off); | ||
596 | } | ||
597 | |||
598 | /* The line must be divisible by 4, else its padded with NULLs */ | ||
599 | padding = (1 * info->width) % 4; | ||
600 | if (padding) { | ||
601 | padding = 4 - padding; | ||
602 | } | ||
603 | |||
604 | switch (info->enctype) { | ||
605 | case BMP_BI_RGB: | ||
606 | for (ypos = 0; ypos < info->height; ++ypos) { | ||
607 | if (info->topdown) { | ||
608 | row = ypos; | ||
609 | } else { | ||
610 | row = info->height - ypos - 1; | ||
611 | } | ||
612 | |||
613 | for (xpos = 0; xpos < info->width; ++xpos) { | ||
614 | if (!gdGetByte(&index, infile)) { | ||
615 | return 1; | ||
616 | } | ||
617 | |||
618 | if (im->open[index]) { | ||
619 | im->open[index] = 0; | ||
620 | } | ||
621 | gdImageSetPixel(im, xpos, row, index); | ||
622 | } | ||
623 | /* Could create a new variable, but it isn't really worth it */ | ||
624 | for (xpos = padding; xpos > 0; --xpos) { | ||
625 | if (!gdGetByte(&index, infile)) { | ||
626 | return 1; | ||
627 | } | ||
628 | } | ||
629 | } | ||
630 | break; | ||
631 | |||
632 | case BMP_BI_RLE8: | ||
633 | if (bmp_read_rle(im, infile, info)) { | ||
634 | return 1; | ||
635 | } | ||
636 | break; | ||
637 | |||
638 | default: | ||
639 | return 1; | ||
640 | } | ||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static int bmp_read_rle(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info) | ||
645 | { | ||
646 | int ypos = 0, xpos = 0, row = 0, index = 0; | ||
647 | int rle_length = 0, rle_data = 0; | ||
648 | int padding = 0; | ||
649 | int i = 0, j = 0; | ||
650 | int pixels_per_byte = 8 / info->depth; | ||
651 | |||
652 | for (ypos = 0; ypos < info->height && xpos <= info->width;) { | ||
653 | if (!gdGetByte(&rle_length, infile) || !gdGetByte(&rle_data, infile)) { | ||
654 | return 1; | ||
655 | } | ||
656 | row = info->height - ypos - 1; | ||
657 | |||
658 | if (rle_length != BMP_RLE_COMMAND) { | ||
659 | if (im->open[rle_data]) { | ||
660 | im->open[rle_data] = 0; | ||
661 | } | ||
662 | |||
663 | for (i = 0; (i < rle_length) && (xpos < info->width);) { | ||
664 | for (j = 1; (j <= pixels_per_byte) && (xpos < info->width) && (i < rle_length); j++, xpos++, i++) { | ||
665 | index = (rle_data & (((1 << info->depth) - 1) << (8 - (j * info->depth)))) >> (8 - (j * info->depth)); | ||
666 | if (im->open[index]) { | ||
667 | im->open[index] = 0; | ||
668 | } | ||
669 | gdImageSetPixel(im, xpos, row, index); | ||
670 | } | ||
671 | } | ||
672 | } else if (rle_length == BMP_RLE_COMMAND && rle_data > 2) { | ||
673 | /* Uncompressed RLE needs to be even */ | ||
674 | padding = 0; | ||
675 | for (i = 0; (i < rle_data) && (xpos < info->width); i += pixels_per_byte) { | ||
676 | int max_pixels = pixels_per_byte; | ||
677 | |||
678 | if (!gdGetByte(&index, infile)) { | ||
679 | return 1; | ||
680 | } | ||
681 | padding++; | ||
682 | |||
683 | if (rle_data - i < max_pixels) { | ||
684 | max_pixels = rle_data - i; | ||
685 | } | ||
686 | |||
687 | for (j = 1; (j <= max_pixels) && (xpos < info->width); j++, xpos++) { | ||
688 | int temp = (index >> (8 - (j * info->depth))) & ((1 << info->depth) - 1); | ||
689 | if (im->open[temp]) { | ||
690 | im->open[temp] = 0; | ||
691 | } | ||
692 | gdImageSetPixel(im, xpos, row, temp); | ||
693 | } | ||
694 | } | ||
695 | |||
696 | /* Make sure the bytes read are even */ | ||
697 | if (padding % 2 && !gdGetByte(&index, infile)) { | ||
698 | return 1; | ||
699 | } | ||
700 | } else if (rle_length == BMP_RLE_COMMAND && rle_data == BMP_RLE_ENDOFLINE) { | ||
701 | /* Next Line */ | ||
702 | xpos = 0; | ||
703 | ypos++; | ||
704 | } else if (rle_length == BMP_RLE_COMMAND && rle_data == BMP_RLE_DELTA) { | ||
705 | /* Delta Record, used for bmp files that contain other data*/ | ||
706 | if (!gdGetByte(&rle_length, infile) || !gdGetByte(&rle_data, infile)) { | ||
707 | return 1; | ||
708 | } | ||
709 | xpos += rle_length; | ||
710 | ypos += rle_data; | ||
711 | } else if (rle_length == BMP_RLE_COMMAND && rle_data == BMP_RLE_ENDOFBITMAP) { | ||
712 | /* End of bitmap */ | ||
713 | break; | ||
714 | } | ||
715 | } | ||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | #if GD_MAJOR_VERSION == 2 && GD_MINOR_VERSION < 1 | ||
720 | static int gdGetWordLSB(signed short int *result, gdIOCtx * ctx) | ||
721 | { | ||
722 | unsigned int high = 0, low = 0; | ||
723 | low = (ctx->getC) (ctx); | ||
724 | if (low == EOF) { | ||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | high = (ctx->getC) (ctx); | ||
729 | if (high == EOF) { | ||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | if (result) { | ||
734 | *result = (high << 8) | low; | ||
735 | } | ||
736 | |||
737 | return 1; | ||
738 | } | ||
739 | |||
740 | static int gdGetIntLSB(signed int *result, gdIOCtx * ctx) | ||
741 | { | ||
742 | int c = 0; | ||
743 | unsigned int r = 0; | ||
744 | |||
745 | c = (ctx->getC) (ctx); | ||
746 | if (c == EOF) { | ||
747 | return 0; | ||
748 | } | ||
749 | r |= (c << 24); | ||
750 | r >>= 8; | ||
751 | |||
752 | c = (ctx->getC) (ctx); | ||
753 | if (c == EOF) { | ||
754 | return 0; | ||
755 | } | ||
756 | r |= (c << 24); | ||
757 | r >>= 8; | ||
758 | |||
759 | c = (ctx->getC) (ctx); | ||
760 | if (c == EOF) { | ||
761 | return 0; | ||
762 | } | ||
763 | r |= (c << 24); | ||
764 | r >>= 8; | ||
765 | |||
766 | c = (ctx->getC) (ctx); | ||
767 | if (c == EOF) { | ||
768 | return 0; | ||
769 | } | ||
770 | r |= (c << 24); | ||
771 | |||
772 | if (result) { | ||
773 | *result = (signed int)r; | ||
774 | } | ||
775 | |||
776 | return 1; | ||
777 | } | ||
778 | #endif | ||
diff --git a/utils/wpseditor/screenshot/main.c b/utils/wpseditor/screenshot/main.c new file mode 100644 index 0000000000..fb81e069b0 --- /dev/null +++ b/utils/wpseditor/screenshot/main.c | |||
@@ -0,0 +1,361 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Maurus Cuelenaere | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <stdarg.h> | ||
24 | #include <string.h> | ||
25 | #include <dlfcn.h> | ||
26 | #include <unistd.h> | ||
27 | #include "gd.h" | ||
28 | #include "gdfonts.h" | ||
29 | #include "api.h" | ||
30 | |||
31 | #define DEBUGF1 _debug | ||
32 | #define DEBUGF2 if(verbose) _debug | ||
33 | |||
34 | #define getFont() gdFontGetSmall() | ||
35 | |||
36 | static struct trackstate mp3data = | ||
37 | { | ||
38 | (char*)"Test title", | ||
39 | (char*)"Test artist", | ||
40 | (char*)"Test album", | ||
41 | (char*)"Test genre", | ||
42 | (char*)"Test disc", | ||
43 | (char*)"Test track", | ||
44 | (char*)"Test year", | ||
45 | (char*)"Test composer", | ||
46 | (char*)"Test comment", | ||
47 | (char*)"Test album artist", | ||
48 | (char*)"Test grouping", | ||
49 | 1, /* int discnum */ | ||
50 | 1, /* int tracknum */ | ||
51 | 1, /* int version */ | ||
52 | 1, /* int layer */ | ||
53 | 2008, /* int year */ | ||
54 | |||
55 | 100, /* int length */ | ||
56 | 70 /* int elapsed */ | ||
57 | }; | ||
58 | |||
59 | static struct wpsstate wpsdata = {-20, -1, -1, 70, API_STATUS_FASTFORWARD}; | ||
60 | /* volume, fontheight, fontwidth, battery_level, audio_status */ | ||
61 | |||
62 | static struct proxy_api api; | ||
63 | static bool verbose = false; | ||
64 | static int (*wps_init)(const char* buff, struct proxy_api *api, bool isfile); | ||
65 | static int (*wps_display)(); | ||
66 | static int (*wps_refresh)(); | ||
67 | static gdImagePtr framebuffer; | ||
68 | static gdImagePtr backdrop; | ||
69 | |||
70 | extern gdImagePtr gdImageCreateFromBmp(FILE * inFile); | ||
71 | extern char *get_current_dir_name (void) __THROW; | ||
72 | |||
73 | int _debug(const char* fmt,...) | ||
74 | { | ||
75 | #if 0 /* Doesn't want to compile ?? */ | ||
76 | struct va_list ap; | ||
77 | |||
78 | va_start(ap, fmt); | ||
79 | |||
80 | fprintf(stdout, "[DBG] "); | ||
81 | vfprintf(stdout, fmt, ap); | ||
82 | fprintf(stdout, "\n"); | ||
83 | |||
84 | va_end(ap); | ||
85 | |||
86 | return 0; | ||
87 | #else | ||
88 | return -1; | ||
89 | #endif | ||
90 | } | ||
91 | |||
92 | void _putsxy(int x, int y, const unsigned char *str) | ||
93 | { | ||
94 | struct viewport_api avp; | ||
95 | int black = gdImageColorAllocate(framebuffer, 0, 0, 0); | ||
96 | |||
97 | api.get_current_vp(&avp); | ||
98 | |||
99 | gdImageString(framebuffer, getFont(), x + avp.x, y + avp.y - avp.fontheight, (unsigned char*)str, black); | ||
100 | } | ||
101 | |||
102 | void _transparent_bitmap_part(const void *src, int src_x, int src_y, | ||
103 | int stride, int x, int y, int width, int height) | ||
104 | { | ||
105 | FILE *_image; | ||
106 | gdImagePtr image; | ||
107 | int pink; | ||
108 | |||
109 | DEBUGF2("transparent_bitmap_part(const void *src=%s, int src_x=%d, int src_y=%d, int stride=%d, int x=%d, int y=%d, int width=%d, int height=%d", (char*)src, src_x, src_y, stride, x, y, width, height); | ||
110 | |||
111 | _image = fopen(src, "rb"); | ||
112 | if(_image == NULL) | ||
113 | return; | ||
114 | |||
115 | image = gdImageCreateFromBmp(_image); | ||
116 | fclose(_image); | ||
117 | |||
118 | pink = gdTrueColor(255, 0, 255); | ||
119 | gdImageColorTransparent(image, pink); | ||
120 | |||
121 | gdImageCopy(framebuffer, image, x, y, src_x, src_y, width, height); | ||
122 | |||
123 | gdImageDestroy(image); | ||
124 | } | ||
125 | |||
126 | void _bitmap_part(const void *src, int src_x, int src_y, | ||
127 | int stride, int x, int y, int width, int height) | ||
128 | { | ||
129 | FILE *_image; | ||
130 | gdImagePtr image; | ||
131 | |||
132 | DEBUGF2("bitmap_part(const void *src=%s, int src_x=%d, int src_y=%d, int stride=%d, int x=%d, int y=%d, int width=%d, int height=%d", (char*)src, src_x, src_y, stride, x, y, width, height); | ||
133 | |||
134 | _image = fopen(src, "rb"); | ||
135 | if(_image == NULL) | ||
136 | return; | ||
137 | |||
138 | image = gdImageCreateFromBmp(_image); | ||
139 | fclose(_image); | ||
140 | |||
141 | gdImageCopy(framebuffer, image, x, y, src_x, src_y, width, height); | ||
142 | |||
143 | gdImageDestroy(image); | ||
144 | } | ||
145 | |||
146 | void _drawpixel(int x, int y) | ||
147 | { | ||
148 | int black = gdImageColorAllocate(framebuffer, 0, 0, 0); | ||
149 | gdImageSetPixel(framebuffer, x, y, black); | ||
150 | } | ||
151 | |||
152 | void _fillrect(int x, int y, int width, int height) | ||
153 | { | ||
154 | /* Don't draw this as backdrop is used */ | ||
155 | #if 0 | ||
156 | int black = gdImageColorAllocate(framebuffer, 0, 0, 0); | ||
157 | gdImageFilledRectangle(framebuffer, x, y, x+width, y+height, black); | ||
158 | #endif | ||
159 | } | ||
160 | |||
161 | void _hline(int x1, int x2, int y) | ||
162 | { | ||
163 | int black = gdImageColorAllocate(framebuffer, 0, 0, 0); | ||
164 | gdImageLine(framebuffer, x1, y, x2, y, black); | ||
165 | } | ||
166 | |||
167 | void _vline(int x, int y1, int y2) | ||
168 | { | ||
169 | int black = gdImageColorAllocate(framebuffer, 0, 0, 0); | ||
170 | gdImageLine(framebuffer, x, y1, x, y2, black); | ||
171 | } | ||
172 | |||
173 | void _clear_viewport(int x, int y, int w, int h, int color) | ||
174 | { | ||
175 | if(backdrop == NULL) | ||
176 | return; | ||
177 | |||
178 | gdImageCopy(framebuffer, backdrop, x, y, x, y, w, h); | ||
179 | } | ||
180 | |||
181 | static bool _load_wps_backdrop(char* filename) | ||
182 | { | ||
183 | FILE *image; | ||
184 | if(backdrop != NULL) | ||
185 | gdImageDestroy(backdrop); | ||
186 | |||
187 | DEBUGF2("load backdrop: %s", filename); | ||
188 | |||
189 | image = fopen(filename, "rb"); | ||
190 | if(image == NULL) | ||
191 | return false; | ||
192 | |||
193 | backdrop = gdImageCreateFromBmp(image); | ||
194 | fclose(image); | ||
195 | |||
196 | return true; | ||
197 | } | ||
198 | |||
199 | int _read_bmp_file(const char* filename, int *width, int *height) | ||
200 | { | ||
201 | FILE *_image; | ||
202 | gdImagePtr image; | ||
203 | |||
204 | DEBUGF2("load backdrop: %s", filename); | ||
205 | |||
206 | _image = fopen(filename, "rb"); | ||
207 | if(_image == NULL) | ||
208 | return 0; | ||
209 | |||
210 | image = gdImageCreateFromBmp(_image); | ||
211 | fclose(_image); | ||
212 | |||
213 | *width = image->sx; | ||
214 | *height = image->sy; | ||
215 | |||
216 | gdImageDestroy(image); | ||
217 | |||
218 | return 1; | ||
219 | } | ||
220 | |||
221 | static void _drawBackdrop() | ||
222 | { | ||
223 | if(backdrop == NULL) | ||
224 | return; | ||
225 | |||
226 | gdImageCopy(framebuffer, backdrop, 0, 0, 0, 0, backdrop->sx, backdrop->sy); | ||
227 | } | ||
228 | |||
229 | static int screenshot(char *model, char *wps, char *png) | ||
230 | { | ||
231 | char lib[255]; | ||
232 | void *handle; | ||
233 | FILE *out, *in; | ||
234 | |||
235 | in = fopen(wps, "rb"); | ||
236 | if(in == NULL) | ||
237 | { | ||
238 | fprintf(stderr, "[ERR] Cannot open WPS: %s\n", wps); | ||
239 | return -1; | ||
240 | } | ||
241 | fclose(in); | ||
242 | |||
243 | out = fopen(png, "wb"); | ||
244 | if(out == NULL) | ||
245 | { | ||
246 | fprintf(stderr, "[ERR] Cannot open PNG: %s\n", png); | ||
247 | return -2; | ||
248 | } | ||
249 | |||
250 | snprintf(lib, 255, "%s/libwps_%s.so", (char*)get_current_dir_name(), (char*)model); | ||
251 | handle = dlopen(lib, RTLD_LAZY); | ||
252 | if (!handle) | ||
253 | { | ||
254 | fprintf(stderr, "[ERR] Cannot open library: %s\n", dlerror()); | ||
255 | fclose(out); | ||
256 | return -3; | ||
257 | } | ||
258 | |||
259 | wps_init = dlsym(handle, "wps_init"); | ||
260 | wps_display = dlsym(handle, "wps_display"); | ||
261 | wps_refresh = dlsym(handle, "wps_refresh"); | ||
262 | |||
263 | if (!wps_init || !wps_display || !wps_refresh) | ||
264 | { | ||
265 | fprintf(stderr, "[ERR] Failed to resolve funcs!"); | ||
266 | dlclose(handle); | ||
267 | fclose(out); | ||
268 | return -4; | ||
269 | } | ||
270 | |||
271 | memset(&api, 0, sizeof(struct proxy_api)); | ||
272 | |||
273 | if(verbose) | ||
274 | api.verbose = 3; | ||
275 | else | ||
276 | api.verbose = 0; | ||
277 | |||
278 | api.putsxy = &_putsxy; | ||
279 | api.transparent_bitmap_part = &_transparent_bitmap_part; | ||
280 | api.bitmap_part = &_bitmap_part; | ||
281 | api.drawpixel = &_drawpixel; | ||
282 | api.fillrect = &_fillrect; | ||
283 | api.hline = &_hline; | ||
284 | api.vline = &_vline; | ||
285 | api.clear_viewport = &_clear_viewport; | ||
286 | api.load_wps_backdrop = &_load_wps_backdrop; | ||
287 | api.read_bmp_file = &_read_bmp_file; | ||
288 | api.debugf = &_debug; | ||
289 | |||
290 | wps_init(wps, &api, true); | ||
291 | |||
292 | framebuffer = gdImageCreateTrueColor(api.getwidth(), api.getheight()); | ||
293 | |||
294 | _drawBackdrop(); | ||
295 | |||
296 | if(strcmp(api.get_model_name(), model) != 0) | ||
297 | { | ||
298 | fprintf(stderr, "[ERR] Model name doesn't match the one supplied by the library\n"); | ||
299 | fprintf(stderr, " %s <-> %s\n", model, api.get_model_name()); | ||
300 | dlclose(handle); | ||
301 | fclose(out); | ||
302 | gdImageDestroy(framebuffer); | ||
303 | gdImageDestroy(backdrop); | ||
304 | wps_init = NULL; | ||
305 | wps_display = NULL; | ||
306 | wps_refresh = NULL; | ||
307 | return -5; | ||
308 | } | ||
309 | fprintf(stdout, "[INFO] Model: %s\n", api.get_model_name()); | ||
310 | |||
311 | wpsdata.fontheight = getFont()->h; | ||
312 | wpsdata.fontwidth = getFont()->w; | ||
313 | api.set_wpsstate(wpsdata); | ||
314 | api.set_trackstate(mp3data); | ||
315 | api.set_next_trackstate(mp3data); | ||
316 | |||
317 | _drawBackdrop(); | ||
318 | wps_refresh(); | ||
319 | gdImagePng(framebuffer, out); | ||
320 | |||
321 | fprintf(stdout, "[INFO] Image written\n"); | ||
322 | |||
323 | dlclose(handle); | ||
324 | fclose(out); | ||
325 | gdImageDestroy(framebuffer); | ||
326 | gdImageDestroy(backdrop); | ||
327 | |||
328 | wps_init = NULL; | ||
329 | wps_display = NULL; | ||
330 | wps_refresh = NULL; | ||
331 | |||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static void usage(void) | ||
336 | { | ||
337 | fprintf(stderr, "Usage: screenshot [-V] <MODEL> <WPS_FILE> <OUT_PNG>\n"); | ||
338 | fprintf(stderr, "Example: screenshot h10_5gb iCatcher.wps out.png\n"); | ||
339 | } | ||
340 | |||
341 | int main(int argc, char ** argv) | ||
342 | { | ||
343 | if(argc < 4) | ||
344 | { | ||
345 | usage(); | ||
346 | return -1; | ||
347 | } | ||
348 | |||
349 | if(strcmp(argv[1], "-V") == 0) | ||
350 | { | ||
351 | verbose = true; | ||
352 | return screenshot(argv[2], argv[3], argv[4]); | ||
353 | } | ||
354 | else | ||
355 | { | ||
356 | verbose = false; | ||
357 | return screenshot(argv[1], argv[2], argv[3]); | ||
358 | } | ||
359 | |||
360 | return 0; | ||
361 | } | ||