void ZLEwlImageData::copyFrom(const ZLImageData &source, unsigned int targetX __UNUSED__, unsigned int targetY __UNUSED__) {
	int sW = source.width();
	int sH = source.height();

	ZLEwlImageData *source_image = (ZLEwlImageData *)&source;

	memcpy(myImageData, source_image->getImageData(), sW * sH);
}
void ZLGtkImageData::copyFrom(const ZLImageData &source, unsigned int targetX, unsigned int targetY) {
	gdk_pixbuf_copy_area(
		((const ZLGtkImageData&)source).myPixbuf,
		0, 0,
		source.width(), source.height(),
		myPixbuf,
		targetX, targetY
	);
}
void ZLWin32PaintContext::drawImage(int x, int y, const ZLImageData &image) {
	ZLWin32ImageData &win32Image = (ZLWin32ImageData&)image;
	const BYTE *pixels = win32Image.pixels(myBackgroundColor);
	if (pixels != 0) {
		const int width = image.width();
		const int height = image.height();
		StretchDIBits(myDisplayContext,
			x, y - height, width, height,
			0, 0, width, height,
			pixels, win32Image.info(), DIB_RGB_COLORS, SRCCOPY);
	}
}
void ZLWin32ImageData::copyFrom(const ZLImageData &source, unsigned int targetX, unsigned int targetY) {
	ZLWin32ImageData &win32source = (ZLWin32ImageData&)source;
	if ((myArray == 0) || (win32source.myArray == 0)) {
		return;
	}
	int height = source.height();
	int bytes = source.width() * myBytesPerPixel;
	BYTE *src = win32source.myArray + win32source.myBytesPerLine * (win32source.myHeight - 1);
	BYTE *dst = myArray + (myHeight - targetY - 1) * myBytesPerLine + targetX * myBytesPerPixel;
	for (int i = 0; i < height; ++i) {
		memcpy(dst, src, bytes);
		dst -= myBytesPerLine;
		src -= win32source.myBytesPerLine;
	}
}
示例#5
0
int ZLPaintContext::imageHeight(const ZLImageData &image, int width, int height, ScalingType type) const {
	const int origWidth = image.width();
	const int origHeight = image.height();
	if (origWidth == 0 || origHeight == 0) {
		return 0;
	}

	if ((origWidth <= width) && (origHeight <= height)) {
		if (type == SCALE_REDUCE_SIZE) {
			return origHeight;
		}
	} else {
		width = std::min(width, origWidth);
		height = std::min(height, origHeight);
	}
	if (origWidth * height > origHeight * width) {
		return (origHeight * width + origWidth / 2) / origWidth;
	}
	return height;
}
bool ZLEwlImageManager::convertImageDirect(const std::string &stringData, ZLImageData &data) const {
	unsigned char m0, m1;
	m0 = *(stringData.data());
	m1 = *(stringData.data()+1);

	if((m0 == 0xff) && (m1 == 0xd8))
		convertImageDirectJpeg(stringData, data);
	else if(!png_sig_cmp((unsigned char *)stringData.data(), (png_size_t)0, 4) )
		convertImageDirectPng(stringData, data);
	else if(!strncmp(stringData.c_str(), "GIF", 3))
		convertImageDirectGif(stringData, data);
	else if(!strncmp(stringData.c_str(), "BM", 2))
		convertImageDirectBmp(stringData, data);
	else {
		/*
		printf("unsupported image format: %d %d\n", m0, m1);

		FILE *f;
		f = fopen("/tmp/unknown_img", "w+");
		fwrite(stringData.data(), 1, stringData.length(), f);
		fclose(f);

		printf("image dumped to /tmp/unknown_img\n");
		*/

		data.init(10, 10);
		bzero(((ZLEwlImageData&)data).getImageData(), 25);

		return false;
	}

	ZLIntegerOption myDitherAlgo(ZLCategoryKey::LOOK_AND_FEEL, "Options", "DitherAlgo", 0);
	if(myDitherAlgo.value() == 2)
		floyd_steinberg_dither(data);

    return true;
}
void ZLMirroredPaintContext::drawImage(int x, int y, const ZLImageData &image) {
	myBase.drawImage(mirroredX(x) - image.width(), y, image);
}
void ZLEwlImageManager::convertImageDirectBmp(const std::string &stringData, ZLImageData &data) const {
	int xres, yres, w, h, spp, bps;

	const char *p = stringData.c_str();

	BMPFileHeader file_hdr;
	BMPInfoHeader info_hdr;
	enum BMPType bmp_type;

	uint32  clr_tbl_size, n_clr_elems = 3;
	unsigned char *clr_tbl;

	uint32	row, stride;

	unsigned char* xdata = 0;

	ZLIntegerOption myDitherAlgo(ZLCategoryKey::LOOK_AND_FEEL, "Options", "DitherAlgo", 0);
	register int dalgo = myDitherAlgo.value();

	memcpy(file_hdr.bType, p, 2);

	if(file_hdr.bType[0] != 'B' || file_hdr.bType[1] != 'M') {
		fprintf(stderr, "File is not a BMP\n");
		goto bad;
	}

	/* -------------------------------------------------------------------- */
	/*      Read the BMPFileHeader. We need iOffBits value only             */
	/* -------------------------------------------------------------------- */
	memcpy(&file_hdr.iOffBits, p+10, 4);

	file_hdr.iSize = stringData.length();

	/* -------------------------------------------------------------------- */
	/*      Read the BMPInfoHeader.                                         */
	/* -------------------------------------------------------------------- */

	memcpy(&info_hdr.iSize, p+BFH_SIZE, 4);

	if (info_hdr.iSize == BIH_WIN4SIZE)
		bmp_type = BMPT_WIN4;
	else if (info_hdr.iSize == BIH_OS21SIZE)
		bmp_type = BMPT_OS21;
	else if (info_hdr.iSize == BIH_OS22SIZE || info_hdr.iSize == 16)
		bmp_type = BMPT_OS22;
	else
		bmp_type = BMPT_WIN5;

	if (bmp_type == BMPT_WIN4 || bmp_type == BMPT_WIN5 || bmp_type == BMPT_OS22) {
		p = stringData.c_str() + BFH_SIZE + 4;
		memcpy(&info_hdr.iWidth, p, 4);
		p += 4;
		memcpy(&info_hdr.iHeight, p, 4);
		p += 4;
		memcpy(&info_hdr.iPlanes, p, 2);
		p += 2;
		memcpy(&info_hdr.iBitCount, p, 2);
		p += 2;
		memcpy(&info_hdr.iCompression, p, 4);
		p += 4;
		memcpy(&info_hdr.iSizeImage, p, 4);
		p += 4;
		memcpy(&info_hdr.iXPelsPerMeter, p, 4);
		p += 4;
		memcpy(&info_hdr.iYPelsPerMeter, p, 4);
		p += 4;
		memcpy(&info_hdr.iClrUsed, p, 4);
		p += 4;
		memcpy(&info_hdr.iClrImportant, p, 4);
		p += 4;
		memcpy(&info_hdr.iRedMask, p, 4);
		p += 4;
		memcpy(&info_hdr.iGreenMask, p, 4);
		p += 4;
		memcpy(&info_hdr.iBlueMask, p, 4);
		p += 4;
		memcpy(&info_hdr.iAlphaMask, p, 4);
		p += 4;
		n_clr_elems = 4;
		xres = ((double)info_hdr.iXPelsPerMeter * 2.54 + 0.05) / 100;
		yres = ((double)info_hdr.iYPelsPerMeter * 2.54 + 0.05) / 100;
	}

	if (bmp_type == BMPT_OS22) {
		/* 
		 * FIXME: different info in different documents
		 * regarding this!
		 */
		n_clr_elems = 3;
	}

	if (bmp_type == BMPT_OS21) {
		int16  iShort;

		memcpy(&iShort, p, 2);
		p += 2;
		info_hdr.iWidth = iShort;
		memcpy(&iShort, p, 2);
		p += 2;
		info_hdr.iHeight = iShort;
		memcpy(&iShort, p, 2);
		p += 2;
		info_hdr.iPlanes = iShort;
		memcpy(&iShort, p, 2);
		p += 2;
		info_hdr.iBitCount = iShort;
		info_hdr.iCompression = BMPC_RGB;
		n_clr_elems = 3;
	}

	if (info_hdr.iBitCount != 1  && info_hdr.iBitCount != 4  &&
			info_hdr.iBitCount != 8  && info_hdr.iBitCount != 16 &&
			info_hdr.iBitCount != 24 && info_hdr.iBitCount != 32) {
		fprintf(stderr, "Cannot process BMP file with bit count %d\n",
				info_hdr.iBitCount);
		//   close(fd);
		return;
	}

	w = info_hdr.iWidth;
	h = (info_hdr.iHeight > 0) ? info_hdr.iHeight : -info_hdr.iHeight;

	data.init(w, h);

	switch (info_hdr.iBitCount)
	{
		case 1:
		case 4:
		case 8:
			spp = 1;
			bps = info_hdr.iBitCount;

			/* Allocate memory for colour table and read it. */
			if (info_hdr.iClrUsed)
				clr_tbl_size = ((uint32)(1 << bps) < info_hdr.iClrUsed) ?
					1 << bps : info_hdr.iClrUsed;
			else
				clr_tbl_size = 1 << bps;
			clr_tbl = (unsigned char *)
				_TIFFmalloc(n_clr_elems * clr_tbl_size);
			if (!clr_tbl) {
				fprintf(stderr, "Can't allocate space for color table\n");
				goto bad;
			}

			/*printf ("n_clr_elems: %d, clr_tbl_size: %d\n",
			  n_clr_elems, clr_tbl_size); */

			p = stringData.c_str() + BFH_SIZE + info_hdr.iSize;
			memcpy(clr_tbl, p, n_clr_elems * clr_tbl_size);

			/*for(clr = 0; clr < clr_tbl_size; ++clr) {
			  printf ("%d: r: %d g: %d b: %d\n",
			  clr,
			  clr_tbl[clr*n_clr_elems+2],
			  clr_tbl[clr*n_clr_elems+1],
			  clr_tbl[clr*n_clr_elems]);
			  }*/
			break;

		case 16:
		case 24:
			spp = 3;
			bps = info_hdr.iBitCount / spp;
			break;

		case 32:
			spp = 3;
			bps = 8;
			break;

		default:
			break;
	}

	stride = (w * spp * bps + 7) / 8;
	/*printf ("w: %d, h: %d, spp: %d, bps: %d, colorspace: %d\n",
	 *w, *h, *spp, *bps, info_hdr.iCompression); */

	// detect old style bitmask images
	if (info_hdr.iCompression == BMPC_RGB && info_hdr.iBitCount == 16)
	{
		/*printf ("implicit non-RGB image\n"); */
		info_hdr.iCompression = BMPC_BITFIELDS;
		info_hdr.iBlueMask = 0x1f;
		info_hdr.iGreenMask = 0x1f << 5;
		info_hdr.iRedMask = 0x1f << 10;
	}

	/* -------------------------------------------------------------------- */
	/*  Read uncompressed image data.                                       */
	/* -------------------------------------------------------------------- */

	switch (info_hdr.iCompression) {
		case BMPC_BITFIELDS:
			// we convert those to RGB for easier use
			bps = 8;
			stride = (w * spp * bps + 7) / 8;
		case BMPC_RGB:
			{
				uint32 file_stride = ((w * info_hdr.iBitCount + 7) / 8 + 3) / 4 * 4;

				/*printf ("bitcount: %d, stride: %d, file stride: %d\n",
				  info_hdr.iBitCount, stride, file_stride);

				  printf ("red mask: %x, green mask: %x, blue mask: %x\n",
				  info_hdr.iRedMask, info_hdr.iGreenMask, info_hdr.iBlueMask); */

				xdata = (unsigned char*)_TIFFmalloc (stride * h);

				if (!xdata) {
					fprintf(stderr, "Can't allocate space for image buffer\n");
					goto bad1;
				}

				for (row = 0; row < (unsigned)h; row++) {
					uint32 offset;

					if (info_hdr.iHeight > 0)
						offset = file_hdr.iOffBits + (h - row - 1) * file_stride;
					else
						offset = file_hdr.iOffBits + row * file_stride;

					//	if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
					//	  fprintf(stderr, "scanline %lu: Seek error\n", (unsigned long) row);
					//	}
					p = stringData.c_str() + offset;

					memcpy(xdata + stride*row, p, stride);

					// convert to RGB
					if (info_hdr.iCompression == BMPC_BITFIELDS)
					{

						unsigned char* row_ptr = xdata + stride*row;
						unsigned char* r16_ptr = row_ptr + file_stride - 2;
						unsigned char* rgb_ptr = row_ptr + stride - 3;

						int r_shift = last_bit_set (info_hdr.iRedMask) - 7;
						int g_shift = last_bit_set (info_hdr.iGreenMask) - 7;
						int b_shift = last_bit_set (info_hdr.iBlueMask) - 7;


						char *c = ((ZLEwlImageData&)data).getImageData() + w * row;
						for (int i=0 ; rgb_ptr >= row_ptr; r16_ptr -= 2, rgb_ptr -= 3, i++)
						{
							int val = (r16_ptr[0] << 0) + (r16_ptr[1] << 8);
							if (r_shift > 0)
								rgb_ptr[0] = (val & info_hdr.iRedMask) >> r_shift;
							else
								rgb_ptr[0] = (val & info_hdr.iRedMask) << -r_shift;
							if (g_shift > 0)
								rgb_ptr[1] = (val & info_hdr.iGreenMask) >> g_shift;
							else
								rgb_ptr[1] = (val & info_hdr.iGreenMask) << -g_shift;
							if (b_shift > 0)
								rgb_ptr[2] = (val & info_hdr.iBlueMask) >> b_shift;
							else
								rgb_ptr[2] = (val & info_hdr.iBlueMask) << -b_shift;


							unsigned char x = rgb_ptr[0] * 0.299 +
								rgb_ptr[1] * 0.587 +
								rgb_ptr[2] * 0.114;

							if(dalgo == 1)
								*c++ = Dither2BitColor(x, i, row);
							else
								*c++ = x;
						}
					}
void ZLEwlImageManager::convertImageDirectGif(const std::string &stringData, ZLImageData &data) const {
	static std::map<std::string, ImageData> imgCache;
	if(stringData.length() < 300) {
		std::map<std::string, ImageData>::const_iterator it = imgCache.find(stringData);
		if(it != imgCache.end()) {
			data.init(it->second.w, it->second.h);
			memcpy(((ZLEwlImageData&)data).getImageData(), it->second.d, it->second.len);
			return;
		}
	}

	GifFileType *GifFile;

	struct gif_info gi;

	gi.length = stringData.length();
	gi.cpos = 0;
	gi.data = stringData.c_str();

	if((GifFile = DGifOpen((void*)&gi, readGif)) == NULL) {
		data.init(10,10);
		bzero(((ZLEwlImageData&)data).getImageData(), 25);

		return;
	}


	data.init(GifFile->SWidth, GifFile->SHeight);

	int 
		ColorMapSize = 0,
		BackGround = 0,
		InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
		InterlacedJumps[] = { 8, 8, 4, 2 };    /* be read - offsets and jumps... */

	int	i, j, Size, Row, Col, Width, Height, ExtCode, Count;
	GifRecordType RecordType;
	GifByteType *Extension;
	GifRowType *ScreenBuffer;
	ColorMapObject *ColorMap;

	ScreenBuffer = (GifRowType *) malloc(GifFile->SHeight * sizeof(GifRowType *));

	Size = GifFile->SWidth * sizeof(GifPixelType);/* Size in bytes one row.*/
	ScreenBuffer[0] = (GifRowType) malloc(Size); /* First row. */

	for (i = 0; i < GifFile->SWidth; i++)  /* Set its color to BackGround. */
		ScreenBuffer[0][i] = GifFile->SBackGroundColor;
	for (i = 1; i < GifFile->SHeight; i++) {
		/* Allocate the other rows, and set their color to background too: */
		ScreenBuffer[i] = (GifRowType) malloc(Size);

		memcpy(ScreenBuffer[i], ScreenBuffer[0], Size);
	}

	do {
		if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
			memset(((ZLEwlImageData&)data).getImageData(), 0x02, GifFile->SWidth * GifFile->SHeight / 4);

			DGifCloseFile(GifFile);
			return;			
		}

		if(RecordType == EXTENSION_RECORD_TYPE) {
			/* Skip any extension blocks in file: */
			if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) {
				break;
			}
			/*			printf("%d\n", *Extension);
						if(ExtCode == GRAPHICS_EXT_FUNC_CODE)
						if(Extension[0] == 4 ) {
						int flag = Extension[1];
						transparent = (flag & 0x1) ? Extension[4] : -1;
						}
						*/				
			while (Extension != NULL) {
				if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) {
					break;
				}
				/*			printf("ExtCode: %d, %d\n", ExtCode, GRAPHICS_EXT_FUNC_CODE);
							if(ExtCode == GRAPHICS_EXT_FUNC_CODE)
							if(Extension[0] == 4 ) {
							int flag = Extension[1];
							transparent = (flag & 0x1) ? Extension[4] : -1;
							}
							*/
			}
		}
	} while((RecordType != IMAGE_DESC_RECORD_TYPE) && (RecordType != TERMINATE_RECORD_TYPE));

	DGifGetImageDesc(GifFile);

	Row = GifFile->Image.Top; /* Image Position relative to Screen. */
	Col = GifFile->Image.Left;
	Width = GifFile->Image.Width;
	Height = GifFile->Image.Height;

	if (GifFile->Image.Interlace) {
		/* Need to perform 4 passes on the images: */
		for (Count = i = 0; i < 4; i++)
			for (j = Row + InterlacedOffset[i]; j < Row + Height;
					j += InterlacedJumps[i])
				DGifGetLine(GifFile, &ScreenBuffer[j][Col], Width);
	} else
		for (i = 0; i < Height; i++)
			DGifGetLine(GifFile, &ScreenBuffer[Row++][Col], Width);

	/* Lets display it - set the global variables required and do it: */
	BackGround = GifFile->SBackGroundColor;
	ColorMap = (GifFile->Image.ColorMap
			? GifFile->Image.ColorMap
			: GifFile->SColorMap);
	ColorMapSize = ColorMap->ColorCount;

	char *c;	
	int p;

	GifColorType *ColorMapEntry = ColorMap->Colors;

	/* Let find out what are the intensities in the color map: */
	/*    int MinIntensity, MaxIntensity, AvgIntensity;
		  unsigned long ValueMask;
		  MinIntensity = 256 * 100;
		  for (i = 0; i < ColorMapSize; i++) {
		  p = ColorMapEntry[i].Red * 30 +
		  ColorMapEntry[i].Green * 59 +
		  ColorMapEntry[i].Blue * 11;
		  if (p > MaxIntensity) MaxIntensity = p;
		  if (p < MinIntensity) MinIntensity = p;
		  }
		  AvgIntensity = (MinIntensity + MaxIntensity) / 2;
		  */	

	Width = GifFile->SWidth;
	Height = GifFile->SHeight;

	ZLIntegerOption myDitherAlgo(ZLCategoryKey::LOOK_AND_FEEL, "Options", "DitherAlgo", 0);
	register int dalgo = myDitherAlgo.value();
	for (j = 0; j < Height; j++) {
		c = ((ZLEwlImageData&)data).getImageData() + Width * j;
		for (i = 0; i < Width; i++) {
			p = ScreenBuffer[j][i];
			//			p = ColorMapEntry[p].Red * 30 +
			//				ColorMapEntry[p].Green * 59 +
			//				ColorMapEntry[p].Blue * 11 > AvgIntensity;			

			unsigned char x = ColorMapEntry[p].Red * 0.299 +
				ColorMapEntry[p].Green * 0.587 +
				ColorMapEntry[p].Blue * 0.114;			

			if(dalgo == 1)
				*c++ = Dither2BitColor(x, i, j);
			else
				*c++ = x;
		}
	}

	if(stringData.length() < 300) {
		ImageData id;

		id.w = Width;
		id.h = Height;
		id.len = Width * Height;


		id.d = (char*)malloc(Width * Height);
		memcpy(id.d, ((ZLEwlImageData&)data).getImageData(), id.len);

		imgCache.insert(std::pair<std::string, ImageData>(stringData, id));
	}

	for (i = GifFile->SHeight - 1 ; i >= 0 ; i--)
		free( ScreenBuffer[ i ] );
	free( ScreenBuffer );

	DGifCloseFile(GifFile);
}
void ZLEwlImageManager::convertImageDirectPng(const std::string &stringData, ZLImageData &data) const {
	struct s_my_png my_png;
	my_png.p = (char*)stringData.data();
	my_png.size = stringData.length();

	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	unsigned int *row = NULL;

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
			(png_voidp)&my_png, mypng_error_func, mypng_warning_func);
	if ( !png_ptr )
		return;

	if (setjmp( png_ptr->jmpbuf )) {
		data.init(0, 0);
		if (png_ptr)
		{
			png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
		}
		if ( row )
			delete row;
		return;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
		mypng_error_func(png_ptr, "cannot create png info struct");
	png_set_read_fn(png_ptr,
			(voidp)&my_png, mypng_read_func);
	png_read_info( png_ptr, info_ptr );


	png_uint_32 width, height;
	int bit_depth, color_type, interlace_type;
	png_get_IHDR(png_ptr, info_ptr, &width, &height,
			&bit_depth, &color_type, &interlace_type,
			NULL, NULL);

	data.init(width, height);

	row = new unsigned int[ width ];

	// SET TRANSFORMS
	if (color_type & PNG_COLOR_MASK_PALETTE)
		png_set_palette_to_rgb(png_ptr);

	if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
		png_set_gray_1_2_4_to_8(png_ptr);

	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png_ptr);

	if (bit_depth == 16) png_set_strip_16(png_ptr);


	if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
		png_set_invert_alpha(png_ptr);
	} else {
		png_color_16 bg = {0, 0xffff, 0xffff, 0xffff, 0xffff};
		png_set_background(png_ptr, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 0.0);

		png_set_strip_alpha(png_ptr);
	}

	if (bit_depth < 8)
		png_set_packing(png_ptr);

	//if (color_type == PNG_COLOR_TYPE_RGB)
	//png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);

	//if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	//    png_set_swap_alpha(png_ptr);

	if (! (color_type == PNG_COLOR_TYPE_GRAY ||
			color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
		png_set_rgb_to_gray(png_ptr, 1, -1, -1);

	int number_passes = png_set_interlace_handling(png_ptr);
	//if (color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
	//    color_type == PNG_COLOR_TYPE_GRAY_ALPHA)

	//if (color_type == PNG_COLOR_TYPE_RGB ||
	//    color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	png_set_bgr(png_ptr);


	ZLIntegerOption myDitherAlgo(ZLCategoryKey::LOOK_AND_FEEL, "Options", "DitherAlgo", 0);
	register int dalgo = myDitherAlgo.value();
	char *c;	
	for(int pass = 0; pass < number_passes; pass++) {
		for(unsigned int y = 0; y < height; y++) {

			png_read_rows(png_ptr, (unsigned char **)&row, png_bytepp_NULL, 1);

			c = ((ZLEwlImageData&)data).getImageData() + width * y;


			if ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) {
				unsigned char *s = (unsigned char*)row;
				if(dalgo == 1)
					for(unsigned int i = 0; i < width; i++)
						*c++ = Dither2BitColor(*(++s)++, i, y);
				else
					for(unsigned int i = 0; i < width; i++)
						*c++ = *(++s)++;
			} else if(dalgo == 1) {
				unsigned char *s = (unsigned char*)row;
				for(unsigned int i = 0; i < width; i++)
					*c++ = Dither2BitColor(*s++, i, y);
			} else 
				memcpy(c, (char*)row, width);
		}
	}

	png_read_end(png_ptr, info_ptr);

	png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
}
void ZLEwlImageManager::convertImageDirectJpeg(const std::string &stringData, ZLImageData &data) const {
	struct jpeg_decompress_struct cinfo;
	JSAMPARRAY buffer;		/* Output row buffer */
	int row_stride;		/* physical row width in output buffer */

	struct my_error_mgr jerr;

	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.length() + 2;
	src->buffer = new JOCTET[src->len];

	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;
	src->pub.skip_input_data = my_skip_input_data;
	src->pub.resync_to_restart = my_resync_to_restart;
	src->pub.term_source = my_term_source;
	src->pub.bytes_in_buffer = src->len;
	src->pub.next_input_byte = src->buffer;

	(void) jpeg_read_header(&cinfo, true);

	data.init(cinfo.image_width, cinfo.image_height);

	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);
 
	ZLIntegerOption myDitherAlgo(ZLCategoryKey::LOOK_AND_FEEL, "Options", "DitherAlgo", 0);
	register int dalgo = myDitherAlgo.value();
	char *c;
	while (cinfo.output_scanline < cinfo.output_height) {
		(void) jpeg_read_scanlines(&cinfo, buffer, 1);

		c = ((ZLEwlImageData&)data).getImageData() + cinfo.output_width * (cinfo.output_scanline - 1);

		if(dalgo == 1) {
			unsigned char *s = (unsigned char*)buffer[0];
			for(unsigned int i = 0; i < cinfo.output_width; i++)
				*c++ = Dither2BitColor(*s++, i, cinfo.output_scanline - 1);
		} else
			memcpy(c, (char*)buffer[0], cinfo.output_width);
	}

	(void) jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
}
void floyd_steinberg_dither(ZLImageData &data)
{
	ZLEwlImageData &i = (ZLEwlImageData&)data;
	int w = data.width();
	int h = data.height();

	unsigned char *c = (unsigned char*)i.getImageData();
	int xi;
	unsigned char *x;

	int oldpixel, newpixel;
	int quant_error;

	extern int xcb_pal_colours;
	int factor = 255 / (xcb_pal_colours - 1);
	int factor_half = factor>>1;

	for(int j = 0; j < h; j++)
		for(int i = 0; i < w; i++) {
			x = c + j * w + i;

			oldpixel = *x;

			newpixel = (oldpixel + factor_half) / factor;
			newpixel *= factor;
			if(newpixel > 255)
				newpixel = 255;
			if(newpixel < 0)
				newpixel = 0;
			*x = newpixel;

			quant_error = oldpixel - newpixel;

			if(i < w - 1) {
				x++;

				xi = *x;
				xi = xi + 7 * quant_error / 16;
				if(xi <= 0)
					*x = 0;
				else if (xi >= 255)
					*x = 255;
				else
					*x = xi;
			}

			x = c + (j+1) * w + i - 1;

			if(j < h - 1) {
				if(i > 0) {
					xi = *x;
					xi = xi + 3 * quant_error / 16;
					if(xi <= 0)
						*x = 0;
					else if (xi >= 255)
						*x = 255;
					else
						*x = xi;
				}

				x++;

				xi = *x;
				xi = xi + 5 * quant_error / 16;
				if(xi <= 0)
					*x = 0;
				else if (xi >= 255)
					*x = 255;
				else
					*x = xi;

				if(i < w - 1) {
					x++;

					xi = *x;
					xi = xi + quant_error / 16;
					if(xi <= 0)
						*x = 0;
					else if (xi >= 255)
						*x = 255;
					else
						*x = xi;
				}
			}
		}
}