From 0f13141bcb36f24ab95fd47b9c7f29dd37082ad5 Mon Sep 17 00:00:00 2001 From: Alexander Egorov Date: Wed, 12 Mar 2008 02:44:52 +0100 Subject: [PATCH] jpeg support --- makefiles/arch/desktop.mk | 2 +- zlibrary/ui/src/nanox/image/ZLNXImageManager.cpp | 175 +++++++++++++++++------ zlibrary/ui/src/nanox/image/ZLNXImageManager.h | 7 +- zlibrary/ui/src/nanox/view/ZLNXPaintContext.cpp | 18 +-- 4 files changed, 148 insertions(+), 54 deletions(-) diff --git a/makefiles/arch/desktop.mk b/makefiles/arch/desktop.mk index 61df9bf..6204bce 100644 --- a/makefiles/arch/desktop.mk +++ b/makefiles/arch/desktop.mk @@ -36,7 +36,7 @@ ifeq "$(UI_TYPE)" "gtk" endif ifeq "$(UI_TYPE)" "nanox" - UILIBS = -lrt -L$(ROOTDIR)/v3/i386/lib -lfreetype -ljpeg + UILIBS = -ljpeg -lrt -L$(ROOTDIR)/v3/i386/lib -lfreetype NXINCLUDE = -I$(ROOTDIR)/v3/include/ ZLSHARED = no endif diff --git a/zlibrary/ui/src/nanox/image/ZLNXImageManager.cpp b/zlibrary/ui/src/nanox/image/ZLNXImageManager.cpp index 34d5085..a22882f 100644 --- a/zlibrary/ui/src/nanox/image/ZLNXImageManager.cpp +++ b/zlibrary/ui/src/nanox/image/ZLNXImageManager.cpp @@ -1,6 +1,10 @@ /* * Copyright (C) 2008 Alexander Egorov * + * dithering algorithm from coolreader engine + * Copyright (C) Vadim Lopatin, 2000-2006 + * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -17,18 +21,43 @@ * 02110-1301, USA. */ -#include -#include -#include - #include #include "ZLNXImageManager.h" +extern "C" { +#include +#include +#include +} +static const short dither_2bpp_8x8[] = { +0, 32, 12, 44, 2, 34, 14, 46, +48, 16, 60, 28, 50, 18, 62, 30, +8, 40, 4, 36, 10, 42, 6, 38, +56, 24, 52, 20, 58, 26, 54, 22, +3, 35, 15, 47, 1, 33, 13, 45, +51, 19, 63, 31, 49, 17, 61, 29, +11, 43, 7, 39, 9, 41, 5, 37, +59, 27, 55, 23, 57, 25, 53, 21, +}; - - +int Dither2BitColor( int color, int x, int y ) +{ + int cl = ((((color>>16) & 255) + ((color>>8) & 255) + ((color) & 255)) * (256/3)) >> 8; + if (cl<5) + return 0; + else if (cl>=250) + return 3<<6; + int d = dither_2bpp_8x8[(x&7) | ( (y&7) << 3 )] - 1; + + cl = ( cl + d - 32 ); + if (cl<5) + return 0; + else if (cl>=250) + return 3<<6; + return cl & 0xc0; +} typedef struct { struct jpeg_source_mgr pub; /* public fields */ @@ -80,7 +109,6 @@ boolean my_fill_input_buffer (j_decompress_ptr cinfo) my_jpeg_source_mgr * src = (my_jpeg_source_mgr *) cinfo->src; - src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = src->len; @@ -90,26 +118,32 @@ boolean my_fill_input_buffer (j_decompress_ptr cinfo) } void my_skip_input_data (j_decompress_ptr cinfo, long num_bytes) { + printf("my_skip_input_data %d\n", num_bytes); + my_jpeg_source_mgr * src = (my_jpeg_source_mgr *) cinfo->src; + src->pub.next_input_byte += num_bytes; + src->pub.bytes_in_buffer -= num_bytes; } boolean my_resync_to_restart (j_decompress_ptr cinfo, int desired) { + printf("my_resync_to_restart\n"); return false; } void my_term_source (j_decompress_ptr cinfo) { + printf("my_term_source\n"); } - - - - - - - - - - - +void +my_jpeg_src_free (j_decompress_ptr cinfo) +{ + my_jpeg_source_mgr * src = (my_jpeg_source_mgr *) cinfo->src; + if ( src && src->buffer ) + { + delete[] src->buffer; + src->buffer = NULL; + } + delete src; +} unsigned int ZLNXImageData::width() const { @@ -125,49 +159,58 @@ void ZLNXImageData::init(unsigned int width, unsigned int height) { myWidth = width; myHeight = height; - myImageData = (char*)malloc((myHeight * myWidth + 3) / 4); + myImageData = (char*)malloc(myHeight * myWidth); } void ZLNXImageData::setPosition(unsigned int x, unsigned int y) { + printf("setPosition %d %d\n", x, y); + myX = x; + myY = y; + myPosition = myImageData + x / 4 + myWidth * y / 4; myShift = (x & 3) << 1; } void ZLNXImageData::moveX(int delta) { - myPosition += delta / 4; - myShift = (((myShift >> 1) + delta) & 3) << 1; + printf("moveX %d\n", delta); + setPosition(myX + delta, myY); } void ZLNXImageData::moveY(int delta) { - myPosition += myWidth * delta / 4; + printf("moveY %d\n", delta); + setPosition(myX, myY + delta); } void ZLNXImageData::setPixel(unsigned char r, unsigned char g, unsigned char b) { + printf("setPixel %d %d\n", myX, myY); + int pixel = (0.299 * r + 0.587 * g + 0.114 * b ) / 64; - pixel = (pixel & 3) << 6; + pixel = (~pixel & 3) << 6; *myPosition &= ~(0xc0 >> myShift); *myPosition |= (pixel >> myShift); } void ZLNXImageData::copyFrom(const ZLImageData &source, unsigned int targetX, unsigned int targetY) { - printf("copyFrom\n"); + printf("copyFrom %d %d\n", targetX, targetY); char *c; char *c_src; int s, s_src; + int sW = source.width(); + int sH = source.height(); ZLNXImageData *source_image = (ZLNXImageData *)&source; char *src = source_image->getImageData(); - for(int i = 0; i < source.width(); i++) - for(int j = 0; j < source.height(); j++) { - c_src = src + i / 4 + source.width() * j / 4; + for(int j = 0; j < sH; j++) + for(int i = 0; i < sW; i++) { + c_src = src + i / 4 + sW * j / 4; s_src = (i & 3) << 1; - c = myImageData + (i + targetX) / 4 + myWidth * (j + targetY) / 4; + c = myImageData + (i + targetX) / 4 + myWidth * (j + (targetY - sH)) / 4; s = ((i + targetX) & 3) << 1; *c &= ~(0xc0 >> s); @@ -180,39 +223,51 @@ shared_ptr ZLNXImageManager::createData() const { return new ZLNXImageData(); } + + void ZLNXImageManager::convertImageDirect(const std::string &stringData, ZLImageData &data) const { - printf("convertImageDirect\n"); - return; - + struct jpeg_decompress_struct cinfo; + JSAMPARRAY buffer; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ printf("=> %d\n", sizeof(struct jpeg_decompress_struct)); struct my_error_mgr jerr; - cinfo.err = jpeg_std_error(&jerr.pub); - jerr.pub.error_exit = my_jpeg_error; + jpeg_create_decompress(&cinfo); + + + jpeg_error_mgr errmgr; + cinfo.err = jpeg_std_error(&errmgr); + errmgr.error_exit = my_jpeg_error; + /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ + + my_jpeg_src_free (&cinfo); jpeg_destroy_decompress(&cinfo); return; } + my_jpeg_source_mgr *src; src = (my_jpeg_source_mgr *) new my_jpeg_source_mgr; cinfo.src = (struct jpeg_source_mgr *) src; - src->len = stringData.size() + 2; + + src->len = stringData.length() + 2; src->buffer = new JOCTET[src->len]; - memcpy(src->buffer, stringData.c_str(), stringData.size()); - src->buffer[stringData.size()] = (JOCTET) 0xFF; - src->buffer[stringData.size() + 1] = (JOCTET) JPEG_EOI; + + printf("len: %d\n", stringData.length()); + memcpy(src->buffer, (const unsigned char*)stringData.data(), stringData.length()); + src->buffer[stringData.length()] = (JOCTET) 0xFF; + src->buffer[stringData.length() + 1] = (JOCTET) JPEG_EOI; src->pub.init_source = my_init_source; src->pub.fill_input_buffer = my_fill_input_buffer; @@ -221,16 +276,50 @@ void ZLNXImageManager::convertImageDirect(const std::string &stringData, ZLImage src->pub.term_source = my_term_source; src->pub.bytes_in_buffer = src->len; src->pub.next_input_byte = src->buffer; - - printf("convertImageDirect2\n"); - jpeg_create_decompress(&cinfo); - printf("convertImageDirect3"); + (void) jpeg_read_header(&cinfo, true); - printf("%d %d........\n", cinfo.image_width, cinfo.image_height); + + data.init(cinfo.image_width, cinfo.image_height); + + + cinfo.out_color_space = JCS_RGB; +// cinfo.out_color_space = JCS_GRAYSCALE; + + (void) jpeg_start_decompress(&cinfo); + + row_stride = cinfo.output_width * cinfo.output_components; + buffer = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + + while (cinfo.output_scanline < cinfo.output_height) { + (void) jpeg_read_scanlines(&cinfo, buffer, 1); + + char *p = (char*)buffer[0]; + char *c; + int pixel, s; + int j = cinfo.output_scanline; + for(int i = 0; i < cinfo.output_width; i++) { + pixel = Dither2BitColor( + p[0] << 16 | p[1] << 8 | p[2] << 0, + i, j); + + c = ((ZLNXImageData&)data).getImageData() + i / 4 + cinfo.output_width * j / 4; + s = (i & 3) << 1; + + *c &= ~(0xc0 >> s); + *c |= (pixel >> s); + + p += 3; + } + } + + + (void) jpeg_finish_decompress(&cinfo); if(src->buffer) - delete src->buffer; + delete[] src->buffer; if(src) delete src; + jpeg_destroy_decompress(&cinfo); } diff --git a/zlibrary/ui/src/nanox/image/ZLNXImageManager.h b/zlibrary/ui/src/nanox/image/ZLNXImageManager.h index db88194..b633856 100644 --- a/zlibrary/ui/src/nanox/image/ZLNXImageManager.h +++ b/zlibrary/ui/src/nanox/image/ZLNXImageManager.h @@ -26,8 +26,10 @@ class ZLNXImageData : public ZLImageData { public: - ZLNXImageData() : myImageData(0) {} - ~ZLNXImageData() { if(myImageData != 0) free(myImageData); } + ZLNXImageData() : myImageData(0), myX(0), myY(0) {} + ~ZLNXImageData() { + if(myImageData != 0) free(myImageData); + } unsigned int width() const; unsigned int height() const; @@ -47,6 +49,7 @@ class ZLNXImageData : public ZLImageData { int myRowStride; int myWidth, myHeight; + unsigned int myX, myY; char *myPosition; int myShift; diff --git a/zlibrary/ui/src/nanox/view/ZLNXPaintContext.cpp b/zlibrary/ui/src/nanox/view/ZLNXPaintContext.cpp index 03990d1..fd526ae 100644 --- a/zlibrary/ui/src/nanox/view/ZLNXPaintContext.cpp +++ b/zlibrary/ui/src/nanox/view/ZLNXPaintContext.cpp @@ -356,24 +356,26 @@ void ZLNXPaintContext::drawString(int x, int y, const char *str, int len) { } void ZLNXPaintContext::drawImage(int x, int y, const ZLImageData &image) { - //printf("drawImage: %d %d\n", image.width(), image.height()); - if((image.width() + x) > myWidth || (image.height() + y) > myHeight) - return; - +// printf("drawImage: %d %d %d %d\n", image.width(), image.height(), x, y); char *c; char *c_src; int s, s_src; + int iW = image.width(); + int iH = image.height(); + + if((iW + x) > myWidth || y > myHeight) + return; ZLNXImageData *source_image = (ZLNXImageData *)ℑ char *src = source_image->getImageData(); - for(int i = 0; i < image.width(); i++) - for(int j = 0; j < image.height(); j++) { - c_src = src + i / 4 + image.width() * j / 4; + for(int j = 0; j < iH; j++) + for(int i = 0; i < iW; i++) { + c_src = src + i / 4 + iW * j / 4; s_src = (i & 3) << 1; - c = buf + (i + x) / 4 + myWidth * (j + y) /4; + c = buf + (i + x) / 4 + myWidth * (j + (y - iH)) /4; s = ((i + x) & 3) << 1; *c &= ~(0xc0 >> s); -- 2.11.4.GIT