diff options
-rw-r--r-- | Jamfile | 14 | ||||
-rw-r--r-- | test/x11pdf.c | 367 | ||||
-rw-r--r-- | test/ximage.c | 640 |
3 files changed, 1020 insertions, 1 deletions
@@ -127,11 +127,23 @@ LINKLIBS = -lm ; +LINKLIBS on x11pdf = -lX11 -lXext $(LINKLIBS) ; + Main pdfclean : test/pdfclean.c ; Main pdfdebug : test/pdfdebug.c ; Main pdfmerge : test/pdfmerge.c ; Main pdfrip : test/pdfrip.c ; Main pdffunction : test/pdffunction.c ; -LinkLibraries pdfclean pdfdebug pdfmerge pdfrip pdffunction : libmupdf libfitz ; +Main x11pdf : test/x11pdf.c test/ximage.c ; + +LinkLibraries + pdfclean + pdfdebug + pdfmerge + pdfrip + pdffunction + x11pdf + : libmupdf libfitz ; + diff --git a/test/x11pdf.c b/test/x11pdf.c new file mode 100644 index 00000000..a1c3372f --- /dev/null +++ b/test/x11pdf.c @@ -0,0 +1,367 @@ +#include <fitz.h> +#include <mupdf.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/Intrinsic.h> +#include <X11/cursorfont.h> +#include <X11/keysym.h> + +extern int ximage_init(Display *display, int screen, Visual *visual); +extern int ximage_get_depth(void); +extern Visual *ximage_get_visual(void); +extern Colormap ximage_get_colormap(void); +extern void ximage_blit(Drawable d, GC gc, int dstx, int dsty, + unsigned char *srcdata, + int srcx, int srcy, int srcw, int srch, int srcstride); + +static Display *xdpy; +static int xscr; +static Window xwin; +static GC xgc; +static XEvent xevt; +static int mapped = 0; +static Cursor xcarrow, xchand, xcwait; + +static float zoom = 1.0; +static int rotate = 0; +static int pageno = 1; +static int count = 0; + +static int hist[256]; +static int histlen = 0; + +/* for 123G commands */ +static unsigned char pagebuf[256]; +static int pagebufidx = 0; + +static pdf_xref *xref; +static pdf_pagetree *pages; +static fz_renderer *rast; +static fz_pixmap *image; + +void usage() +{ + fprintf(stderr, "usage: x11pdf [-u password] file.pdf\n"); + exit(1); +} + +/* + * X11 magic + */ + +static void xopen(void) +{ + xdpy = XOpenDisplay(nil); + assert(xdpy != nil); + + xscr = DefaultScreen(xdpy); + + ximage_init(xdpy, xscr, DefaultVisual(xdpy, xscr)); + + xcarrow = XCreateFontCursor(xdpy, XC_left_ptr); + xchand = XCreateFontCursor(xdpy, XC_hand2); + xcwait = XCreateFontCursor(xdpy, XC_watch); + + xwin = XCreateWindow(xdpy, DefaultRootWindow(xdpy), + 10, 10, 200, 100, 1, + ximage_get_depth(), + InputOutput, + ximage_get_visual(), + 0, + nil); + + XSetWindowColormap(xdpy, xwin, ximage_get_colormap()); + XSelectInput(xdpy, xwin, + StructureNotifyMask | ExposureMask | KeyPressMask | + PointerMotionMask | ButtonPressMask); + + mapped = 0; + + xgc = XCreateGC(xdpy, xwin, 0, nil); +} + +static void xresize(void) +{ + XWindowChanges values; + int mask; + + mask = CWWidth | CWHeight; + values.width = image->w; + values.height = image->h; + XConfigureWindow(xdpy, xwin, mask, &values); + + if (!mapped) + { + XMapWindow(xdpy, xwin); + XFlush(xdpy); + + while (1) + { + XNextEvent(xdpy, &xevt); + if (xevt.type == MapNotify) + break; + } + + XSetForeground(xdpy, xgc, WhitePixel(xdpy, xscr)); + XFillRectangle(xdpy, xwin, xgc, 0, 0, image->w, image->h); + XFlush(xdpy); + + mapped = 1; + } +} + +static void xblit(void) +{ + ximage_blit(xwin, xgc, 0, 0, image->samples, 0, 0, + image->w, image->h, image->w * image->n); +} + +static void xtitle(char *s) +{ + XmbSetWMProperties(xdpy, xwin, s, s, 0, 0, 0, 0, 0); +} + +static void showpage(void) +{ + fz_error *error; + pdf_page *page; + fz_matrix ctm; + fz_rect bbox; + char s[256]; + fz_obj *pageobj; + + assert(pageno > 0 && pageno <= pdf_getpagecount(pages)); + + pageobj = pdf_getpageobject(pages, pageno - 1); + + XDefineCursor(xdpy, xwin, xcwait); + XFlush(xdpy); + + if (image) + fz_freepixmap(image); + image = nil; + + sprintf(s, "Loading page %d", pageno); + XSetForeground(xdpy, xgc, BlackPixel(xdpy, xscr)); + XDrawString(xdpy, xwin, xgc, 10, 20, s, strlen(s)); + XFlush(xdpy); + + error = pdf_loadpage(&page, xref, pageobj); + if (error) + fz_abort(error); + + sprintf(s, "Rendering..."); + XSetForeground(xdpy, xgc, BlackPixel(xdpy, xscr)); + XDrawString(xdpy, xwin, xgc, 10, 30, s, strlen(s)); + XFlush(xdpy); + + ctm = fz_concat(fz_translate(0, -page->mediabox.max.y), + fz_scale(zoom, -zoom)); + + bbox = page->mediabox; + bbox.min.x = bbox.min.x * zoom; + bbox.min.y = bbox.min.y * zoom; + bbox.max.x = bbox.max.x * zoom; + bbox.max.y = bbox.max.y * zoom; + + error = fz_rendertree(&image, rast, page->tree, ctm, bbox); + if (error) + fz_abort(error); + + pdf_freepage(page); + + XDefineCursor(xdpy, xwin, xcarrow); + XFlush(xdpy); + + xresize(); + xblit(); +} + +static void pdfopen(char *filename, char *password) +{ + fz_error *error; + + error = pdf_openpdf(&xref, filename); + if (error) + fz_abort(error); + + error = pdf_decryptpdf(xref); + if (error) + fz_abort(error); + + if (xref->crypt) + { + error = pdf_setpassword(xref->crypt, password); + if (error) fz_abort(error); + } + + error = pdf_loadpagetree(&pages, xref); + if (error) fz_abort(error); + + count = pdf_getpagecount(pages); + + error = fz_newrenderer(&rast, pdf_devicergb); + if (error) fz_abort(error); + + image = nil; +} + +static void handlekey(int c) +{ + int oldpage = pageno; + float oldzoom = zoom; + int oldrotate = rotate; + + if (c >= '0' && c <= '9') + pagebuf[pagebufidx++] = c; + else + if (c != 'g' && c != 'G') + pagebufidx = 0; + + switch (c) + { + case 'b': + pageno--; + if (pageno < 1) + pageno = 1; + break; + case 'B': + pageno -= 10; + if (pageno < 1) + pageno = 1; + break; + case ' ': + case 'f': + pageno++; + if (pageno > count) + pageno = count; + break; + case 'F': + pageno += 10; + if (pageno > count) + pageno = count; + break; + case 't': + case 'T': + if (histlen > 0) + pageno = hist[--histlen]; + break; + case '-': + zoom -= 0.1; + if (zoom < 0.1) + zoom = 0.1; + break; + case '+': + zoom += 0.1; + if (zoom > 3.0) + zoom = 3.0; + break; + case '<': + rotate -= 90; + break; + case '>': + rotate += 90; + break; + case 'q': + exit(0); + case 'g': + case 'G': + if (pagebufidx > 0) + { + pagebuf[pagebufidx] = '\0'; + pageno = atoi(pagebuf); + pagebufidx = 0; + if (pageno < 1) + pageno = 1; + if (pageno > count) + pageno = count; + } + else + { + if (c == 'G') + { + pageno = count; + } + } + break; + } + + if (pageno != oldpage || zoom != oldzoom || rotate != oldrotate) + showpage(); +} + +int main(int argc, char **argv) +{ + char *filename; + fz_obj *obj; + char buf[256]; + int c; + + char *password = ""; + + while ((c = getopt(argc, argv, "z:r:p:u:")) != -1) + { + switch (c) + { + case 'u': password = optarg; break; + case 'p': pageno = atoi(optarg); break; + case 'z': zoom = atof(optarg); break; + case 'r': rotate = atoi(optarg); break; + default: usage(); + } + } + + if (argc - optind == 0) + usage(); + + filename = argv[optind++]; + + xopen(); + pdfopen(filename, password); + showpage(); + + strlcpy(buf, filename, sizeof buf); + obj = fz_dictgets(xref->trailer, "Info"); + if (fz_isindirect(obj)) + { + pdf_resolve(&obj, xref); + obj = fz_dictgets(obj, "Title"); + if (obj) + { + int n = MIN(fz_tostringlen(obj) + 1, sizeof buf); + if (obj) + strlcpy(buf, fz_tostringbuf(obj), n); + printf("Title: %s\n", buf); + } + } + xtitle(buf); + + while (1) + { + int len; + unsigned char buf[128]; + KeySym keysym; + + XNextEvent(xdpy, &xevt); + switch (xevt.type) + { + case Expose: + if (xevt.xexpose.count == 0) + xblit(); + break; + + case KeyPress: + len = XLookupString(&xevt.xkey, buf, sizeof buf, &keysym, 0); + if (len) + handlekey(buf[0]); + break; + } + } + + pdf_closepdf(xref); + + return 0; +} + diff --git a/test/ximage.c b/test/ximage.c new file mode 100644 index 00000000..bcf8834b --- /dev/null +++ b/test/ximage.c @@ -0,0 +1,640 @@ +/* + * Blit ARGB images to X with X(Shm)Images + */ + +#include <fitz.h> + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/extensions/XShm.h> + +typedef void (*ximage_convert_func_t) + ( + const unsigned char *src, + int srcstride, + unsigned char *dst, + int dststride, + int w, + int h + ); + +#define POOLSIZE 6 +#define WIDTH 256 +#define HEIGHT 64 + +enum { + ARGB8888, + BGRA8888, + RGBA8888, + ABGR8888, + RGB888, + BGR888, + RGB565, + RGB565_BR, + RGB555, + RGB555_BR, + BGR233, + UNKNOWN +}; + +static char *modename[] = { + "ARGB8888", + "BGRA8888", + "RGBA8888", + "ABGR8888", + "RGB888", + "BGR888", + "RGB565", + "RGB565_BR", + "RGB555", + "RGB555_BR", + "BGR233", + "UNKNOWN" +}; + +extern ximage_convert_func_t ximage_convert_funcs[]; + +static struct +{ + Display *display; + int screen; + XVisualInfo visual; + Colormap colormap; + + int bitsperpixel; + int mode; + + XColor rgbcube[256]; + + ximage_convert_func_t convert_func; + + int useshm; + XImage *pool[POOLSIZE]; + int lastused; +} info; + +static XImage * +createximage(Display *dpy, Visual *vis, int depth, int w, int h) +{ + XImage *img; + XShmSegmentInfo xsi; + Status status; + +// XXX +goto fallback; + + img = XShmCreateImage(dpy, vis, depth, ZPixmap, 0, &xsi, w, h); + if (!img) + { + fprintf(stderr, "warn: could not XShmCreateImage\n"); + goto fallback; + } + + xsi.shmid = shmget(IPC_PRIVATE, + img->bytes_per_line * img->height, + IPC_CREAT | 0777); + if (xsi.shmid < 0) + { + fprintf(stderr, "warn: could not shmget\n"); + goto fallback; + } + + img->data = xsi.shmaddr = shmat(xsi.shmid, 0, 0); + if (img->data == (char*)-1) + { + fprintf(stderr, "warn: could not shmat\n"); + goto fallback; + } + + xsi.readOnly = False; + status = XShmAttach(dpy, &xsi); + if (!status) + { + fprintf(stderr, "warn: could not XShmAttach\n"); + goto fallback; + } + + XSync(dpy, False); + + shmctl(xsi.shmid, IPC_RMID, 0); + +printf("make xshm w=%d h=%d id=%d data=%p\n", + w, h, xsi.shmid, xsi.shmaddr); + + return img; + +fallback: + info.useshm = 0; + + img = XCreateImage(dpy, vis, depth, ZPixmap, 0, 0, w, h, 32, 0); + if (!img) + { + fprintf(stderr, "fail: could not XCreateImage"); + abort(); + } + + img->data = malloc(h * img->bytes_per_line); + if (!img->data) + { + fprintf(stderr, "fail: could not malloc"); + abort(); + } + + return img; +} + +static void +make_colormap(void) +{ + if (info.visual.class == PseudoColor && info.visual.depth == 8) + { + int i, r, g, b; + i = 0; + for (b = 0; b < 4; b++) { + for (g = 0; g < 8; g++) { + for (r = 0; r < 8; r++) { + info.rgbcube[i].pixel = i; + info.rgbcube[i].red = (r * 36) << 8; + info.rgbcube[i].green = (g * 36) << 8; + info.rgbcube[i].blue = (b * 85) << 8; + info.rgbcube[i].flags = + DoRed | DoGreen | DoBlue; + i++; + } + } + } + info.colormap = XCreateColormap(info.display, + RootWindow(info.display, info.screen), + info.visual.visual, + AllocAll); + XStoreColors(info.display, info.colormap, info.rgbcube, 256); + return; + } + else if (info.visual.class == TrueColor) + { + info.colormap = 0; + return; + } + fprintf(stderr, "Cannot handle visual class %d with depth: %d\n", + info.visual.class, info.visual.depth); + return; +} + +static void +select_mode(void) +{ + + int byteorder; + int byterev; + unsigned long rm, gm, bm; + unsigned long rs, gs, bs; + + byteorder = ImageByteOrder(info.display); +#if BYTE_ORDER == BIG_ENDIAN + byterev = byteorder != MSBFirst; +#else + byterev = byteorder != LSBFirst; +#endif + + rm = info.visual.red_mask; + gm = info.visual.green_mask; + bm = info.visual.blue_mask; + + rs = ffs(rm) - 1; + gs = ffs(gm) - 1; + bs = ffs(bm) - 1; + + printf("mode %d/%d %08lx %08lx %08lx (%ld,%ld,%ld) %s%s\n", + info.visual.depth, + info.bitsperpixel, + rm, gm, bm, rs, gs, bs, + byteorder == MSBFirst ? "msb" : "lsb", + byterev ? " <swap>":""); + + info.mode = UNKNOWN; + if (info.bitsperpixel == 8) { + /* Either PseudoColor with BGR233 colormap, or TrueColor */ + info.mode = BGR233; + } + else if (info.bitsperpixel == 16) { + if (rm == 0xF800 && gm == 0x07E0 && bm == 0x001F) + info.mode = !byterev ? RGB565 : RGB565_BR; + if (rm == 0x7C00 && gm == 0x03E0 && bm == 0x001F) + info.mode = !byterev ? RGB555 : RGB555_BR; + } + else if (info.bitsperpixel == 24) { + if (rs == 0 && gs == 8 && bs == 16) + info.mode = byteorder == MSBFirst ? RGB888 : BGR888; + if (rs == 16 && gs == 8 && bs == 0) + info.mode = byteorder == MSBFirst ? BGR888 : RGB888; + } + else if (info.bitsperpixel == 32) { + if (rs == 0 && gs == 8 && bs == 16) + info.mode = byteorder == MSBFirst ? ABGR8888 : RGBA8888; + if (rs == 8 && gs == 16 && bs == 24) + info.mode = byteorder == MSBFirst ? BGRA8888 : ARGB8888; + if (rs == 16 && gs == 8 && bs == 0) + info.mode = byteorder == MSBFirst ? ARGB8888 : BGRA8888; + if (rs == 24 && gs == 16 && bs == 8) + info.mode = byteorder == MSBFirst ? RGBA8888 : ABGR8888; + } + + printf("rgba:8888 -> %s\n", modename[info.mode]); + + /* select conversion function */ + info.convert_func = ximage_convert_funcs[info.mode]; +} + +static int +create_pool(void) +{ + int i; + + info.lastused = 0; + + for (i = 0; i < POOLSIZE; i++) { + info.pool[i] = nil; + } + + for (i = 0; i < POOLSIZE; i++) { + info.pool[i] = createximage(info.display, + info.visual.visual, info.visual.depth, + WIDTH, HEIGHT); + if (info.pool[i] == nil) { + return 0; + } + } + + return 1; +} + +static XImage * +next_pool_image(void) +{ + if (info.lastused + 1 >= POOLSIZE) { + if (info.useshm) + XSync(info.display, False); + else + XFlush(info.display); + info.lastused = 0; + } + return info.pool[info.lastused ++]; +} + +int +ximage_init(Display *display, int screen, Visual *visual) +{ + XVisualInfo template; + XVisualInfo *visuals; + int nvisuals; + XPixmapFormatValues *formats; + int nformats; + int ok; + int i; + + info.display = display; + info.screen = screen; + info.colormap = 0; + + /* Get XVisualInfo for this visual */ + template.visualid = XVisualIDFromVisual(visual); + visuals = XGetVisualInfo(display, VisualIDMask, &template, &nvisuals); + if (nvisuals != 1) { + fprintf(stderr, "Visual not found!\n"); + XFree(visuals); + return 0; + } + memcpy(&info.visual, visuals, sizeof (XVisualInfo)); + XFree(visuals); + + /* Get appropriate PixmapFormat for this visual */ + formats = XListPixmapFormats(info.display, &nformats); + for (i = 0; i < nformats; i++) { + if (formats[i].depth == info.visual.depth) { + info.bitsperpixel = formats[i].bits_per_pixel; + break; + } + } + XFree(formats); + if (i == nformats) { + fprintf(stderr, "PixmapFormat not found!\n"); + return 0; + } + + /* extract mode */ + select_mode(); + + /* prepare colormap */ + make_colormap(); + + /* prepare pool of XImages */ + info.useshm = 1; + ok = create_pool(); + if (!ok) + return 0; + + printf("Using %sPutImage\n", info.useshm ? "XShm" : "X"); + + return 1; +} + +int +ximage_get_depth(void) +{ + return info.visual.depth; +} + +Visual * +ximage_get_visual(void) +{ + return info.visual.visual; +} + +Colormap +ximage_get_colormap(void) +{ + return info.colormap; +} + +void +ximage_blit(Drawable d, GC gc, + int dstx, int dsty, + unsigned char *srcdata, + int srcx, int srcy, + int srcw, int srch, + int srcstride) +{ + XImage *image; + int ax, ay; + int w, h; + unsigned char *srcptr; + + for (ay = 0; ay < srch; ay += HEIGHT) + { + h = MIN(srch - ay, HEIGHT); + for (ax = 0; ax < srcw; ax += WIDTH) + { + w = MIN(srcw - ax, WIDTH); + + image = next_pool_image(); + + srcptr = srcdata + + (ay + srcy) * srcstride + + (ax + srcx) * 4; + + info.convert_func(srcptr, srcstride, + image->data, + image->bytes_per_line, w, h); + + if (info.useshm) + { + XShmPutImage(info.display, d, gc, image, + 0, 0, dstx + ax, dsty + ay, + w, h, False); + } + else + { + XPutImage(info.display, d, gc, image, + 0, 0, + dstx + ax, + dsty + ay, + w, h); + } + } + } +} + +/* + * + */ + +#define PARAMS \ + const unsigned char * src, \ + int srcstride, \ + unsigned char * dst, \ + int dststride, \ + int w, \ + int h + +/* + * Convert byte:ARGB8888 to various formats + */ + +static void +ximage_convert_argb8888(PARAMS) +{ + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + dst[x * 4 + 0] = src[x * 4 + 0]; + dst[x * 4 + 1] = src[x * 4 + 1]; + dst[x * 4 + 2] = src[x * 4 + 2]; + dst[x * 4 + 3] = src[x * 4 + 3]; + } + dst += dststride; + src += srcstride; + } +} + +static void +ximage_convert_bgra8888(PARAMS) +{ + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + dst[x * 4 + 0] = src[x * 4 + 3]; + dst[x * 4 + 1] = src[x * 4 + 2]; + dst[x * 4 + 2] = src[x * 4 + 1]; + dst[x * 4 + 3] = src[x * 4 + 0]; + } + dst += dststride; + src += srcstride; + } +} + +static void +ximage_convert_abgr8888(PARAMS) +{ + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + dst[x * 4 + 0] = src[x * 4 + 0]; + dst[x * 4 + 1] = src[x * 4 + 3]; + dst[x * 4 + 2] = src[x * 4 + 2]; + dst[x * 4 + 3] = src[x * 4 + 1]; + } + dst += dststride; + src += srcstride; + } +} + +static void +ximage_convert_rgba8888(PARAMS) +{ + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + dst[x * 4 + 0] = src[x * 4 + 1]; + dst[x * 4 + 1] = src[x * 4 + 2]; + dst[x * 4 + 2] = src[x * 4 + 3]; + dst[x * 4 + 3] = src[x * 4 + 0]; + } + dst += dststride; + src += srcstride; + } +} + +/* bgr/rgb have yet to recieve some MMX love ;-) */ + +static void +ximage_convert_bgr888(PARAMS) +{ + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + dst[3*x + 0] = src[4*x + 3]; + dst[3*x + 1] = src[4*x + 2]; + dst[3*x + 2] = src[4*x + 1]; + } + src += srcstride; + dst += dststride; + } +} + +static void +ximage_convert_rgb888(PARAMS) +{ + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + dst[3*x + 0] = src[4*x + 1]; + dst[3*x + 1] = src[4*x + 2]; + dst[3*x + 2] = src[4*x + 3]; + } + src += srcstride; + dst += dststride; + } +} + +static void +ximage_convert_rgb565(PARAMS) +{ + unsigned char r, g, b; + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + r = src[4*x + 1]; + g = src[4*x + 2]; + b = src[4*x + 3]; + ((unsigned short *)dst)[x] = + ((r & 0xF8) << 8) | + ((g & 0xFC) << 3) | + (b >> 3); + } + src += srcstride; + dst += dststride; + } +} + +static void +ximage_convert_rgb565_br(PARAMS) +{ + unsigned char r, g, b; + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + r = src[4*x + 1]; + g = src[4*x + 2]; + b = src[4*x + 3]; + /* final word is: + g4 g3 g2 b7 b6 b5 b4 b3 r7 r6 r5 r4 r3 g7 g6 g5 + */ + ((unsigned short *)dst)[x] = + (r & 0xF8) | + ((g & 0xE0) >> 5) | + ((g & 0x1C) << 11) | + ((b & 0xF8) << 5); + } + src += srcstride; + dst += dststride; + } +} + +static void +ximage_convert_rgb555(PARAMS) +{ + unsigned char r, g, b; + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + r = src[4*x + 1]; + g = src[4*x + 2]; + b = src[4*x + 3]; + ((unsigned short *)dst)[x] = + ((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3); + } + src += srcstride; + dst += dststride; + } +} + +static void +ximage_convert_rgb555_br(PARAMS) +{ + unsigned char r, g, b; + int x, y; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + r = src[4*x + 1]; + g = src[4*x + 2]; + b = src[4*x + 3]; + /* final word is: + g5 g4 g3 b7 b6 b5 b4 b3 0 r7 r6 r5 r4 r3 g7 g6 + */ + ((unsigned short *)dst)[x] = + ((r & 0xF8) >> 1) | + ((g & 0xC0) >> 6) | + ((g & 0x38) << 10) | + ((b & 0xF8) << 5); + } + src += srcstride; + dst += dststride; + } +} + +static void +ximage_convert_bgr233(PARAMS) +{ + unsigned char r, g, b; + int x,y; + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) { + r = src[4*x + 1]; + g = src[4*x + 2]; + b = src[4*x + 3]; + /* format: b7 b6 g7 g6 g5 r7 r6 r5 */ + dst[x] = (b&0xC0) | ((g>>2)&0x38) | ((r>>5)&0x7); + } + src += srcstride; + dst += dststride; + } +} + +ximage_convert_func_t ximage_convert_funcs[] = { + ximage_convert_argb8888, + ximage_convert_bgra8888, + ximage_convert_rgba8888, + ximage_convert_abgr8888, + ximage_convert_rgb888, + ximage_convert_bgr888, + ximage_convert_rgb565, + ximage_convert_rgb565_br, + ximage_convert_rgb555, + ximage_convert_rgb555_br, + ximage_convert_bgr233, +}; + |