Exemple #1
0
bool loadJPEGScaled(QImage& image, const QString& path, int maximumSize)
{
    FileReadLocker lock(path);

    if (!isJpegImage(path))
    {
        return false;
    }

    FILE* const inputFile = fopen(QFile::encodeName(path).constData(), "rb");

    if (!inputFile)
    {
        return false;
    }

    struct jpeg_decompress_struct   cinfo;

    struct jpegutils_jpeg_error_mgr jerr;

    // JPEG error handling - thanks to Marcus Meissner
    cinfo.err                 = jpeg_std_error(&jerr);
    cinfo.err->error_exit     = jpegutils_jpeg_error_exit;
    cinfo.err->emit_message   = jpegutils_jpeg_emit_message;
    cinfo.err->output_message = jpegutils_jpeg_output_message;

    if (setjmp(jerr.setjmp_buffer))
    {
        jpeg_destroy_decompress(&cinfo);
        fclose(inputFile);
        return false;
    }

    jpeg_create_decompress(&cinfo);

#ifdef Q_OS_WIN

    QFile inFile(path);
    QByteArray buffer;

    if (inFile.open(QIODevice::ReadOnly))
    {
        buffer = inFile.readAll();
        inFile.close();
    }

    jpeg_memory_src(&cinfo, (JOCTET*)buffer.data(), buffer.size());

#else  // Q_OS_WIN

    jpeg_stdio_src(&cinfo, inputFile);

#endif // Q_OS_WIN

    jpeg_read_header(&cinfo, true);

    int imgSize = qMax(cinfo.image_width, cinfo.image_height);

    // libjpeg supports 1/1, 1/2, 1/4, 1/8
    int scale=1;

    while(maximumSize*scale*2 <= imgSize)
    {
        scale *= 2;
    }

    if (scale > 8)
    {
        scale = 8;
    }

    //cinfo.scale_num = 1;
    //cinfo.scale_denom = scale;
    cinfo.scale_denom *= scale;

    switch (cinfo.jpeg_color_space)
    {
        case JCS_UNKNOWN:
            break;
        case JCS_GRAYSCALE:
        case JCS_RGB:
        case JCS_YCbCr:
            cinfo.out_color_space = JCS_RGB;
            break;
        case JCS_CMYK:
        case JCS_YCCK:
            cinfo.out_color_space = JCS_CMYK;
            break;
        default:
            break;
    }

    jpeg_start_decompress(&cinfo);

    QImage img;

    // We only take RGB with 1 or 3 components, or CMYK with 4 components
    if (!(
            (cinfo.out_color_space == JCS_RGB  && (cinfo.output_components == 3 || cinfo.output_components == 1)) ||
            (cinfo.out_color_space == JCS_CMYK &&  cinfo.output_components == 4)
        ))
    {
        jpeg_destroy_decompress(&cinfo);
        fclose(inputFile);
        return false;
    }

    switch (cinfo.output_components)
    {
        case 3:
        case 4:
            img = QImage(cinfo.output_width, cinfo.output_height, QImage::Format_RGB32);
            break;
        case 1: // B&W image
            img = QImage(cinfo.output_width, cinfo.output_height, QImage::Format_Indexed8);
            img.setColorCount(256);

            for (int i = 0 ; i < 256 ; ++i)
            {
                img.setColor(i, qRgb(i, i, i));
            }

            break;
    }

    uchar* const data = img.bits();
    int bpl           = img.bytesPerLine();

    while (cinfo.output_scanline < cinfo.output_height)
    {
        uchar* d = data + cinfo.output_scanline * bpl;
        jpeg_read_scanlines(&cinfo, &d, 1);
    }

    jpeg_finish_decompress(&cinfo);

    if (cinfo.output_components == 3)
    {
        // Expand 24->32 bpp.
        for (uint j=0; j<cinfo.output_height; ++j)
        {
            uchar* in       = img.scanLine(j) + cinfo.output_width * 3;
            QRgb* const out = reinterpret_cast<QRgb*>(img.scanLine(j));

            for (uint i = cinfo.output_width; --i; )
            {
                in     -= 3;
                out[i] = qRgb(in[0], in[1], in[2]);
            }
        }
    }
    else if (cinfo.out_color_space == JCS_CMYK)
    {
        for (uint j = 0; j < cinfo.output_height; ++j)
        {
            uchar* in       = img.scanLine(j) + cinfo.output_width * 4;
            QRgb* const out = reinterpret_cast<QRgb*>(img.scanLine(j));

            for (uint i = cinfo.output_width; --i; )
            {
                in     -= 4;
                int k  = in[3];
                out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255);
            }
        }
    }

    if (cinfo.density_unit == 1)
    {
        img.setDotsPerMeterX(int(100. * cinfo.X_density / 2.54));
        img.setDotsPerMeterY(int(100. * cinfo.Y_density / 2.54));
    }
    else if (cinfo.density_unit == 2)
    {
        img.setDotsPerMeterX(int(100. * cinfo.X_density));
        img.setDotsPerMeterY(int(100. * cinfo.Y_density));
    }

    //int newMax = qMax(cinfo.output_width, cinfo.output_height);
    //int newx = maximumSize*cinfo.output_width / newMax;
    //int newy = maximumSize*cinfo.output_height / newMax;

    jpeg_destroy_decompress(&cinfo);
    fclose(inputFile);

    image = img;

    return true;
}
bool QVideoEncoder::convertImage(const QImage &img)
{
   // Check if the image matches the size
   if(img.width()!=getWidth() || img.height()!=getHeight())
   {
      printf("Wrong image size!\n");
      return false;
   }
   if(img.format()!=QImage::Format_RGB32	&& img.format() != QImage::Format_ARGB32)
   {
      printf("Wrong image format\n");
      return false;
   }

   // RGB32 to YUV420

   int size = getWidth()*getHeight();
   // Y
   for(unsigned y=0;y<getHeight();y++)
   {

      unsigned char *s = (unsigned char*)img.scanLine(y);
      unsigned char *d = (unsigned char*)&picture_buf[y*getWidth()];
      //printf("Line %d. d: %p. picture_buf: %p\n",y,d,picture_buf);

      for(unsigned x=0;x<getWidth();x++)
      {
         unsigned int r=s[2];
         unsigned int g=s[1];
         unsigned int b=s[0];

         unsigned Y = (r*2104 + g*4130 + b*802 + 4096 + 131072) >> 13;
         if(Y>235) Y=235;

         *d = Y;

         d+=1;
         s+=4;
      }
   }

   // U,V
   for(unsigned y=0;y<getHeight();y+=2)
   {
      unsigned char *s = (unsigned char*)img.scanLine(y);
      unsigned int ss = img.bytesPerLine();
      unsigned char *d = (unsigned char*)&picture_buf[size+y/2*getWidth()/2];

      //printf("Line %d. d: %p. picture_buf: %p\n",y,d,picture_buf);

      for(unsigned x=0;x<getWidth();x+=2)
      {
         // Cr = 128 + 1/256 * ( 112.439 * R'd -  94.154 * G'd -  18.285 * B'd)
         // Cb = 128 + 1/256 * (- 37.945 * R'd -  74.494 * G'd + 112.439 * B'd)

         // Get the average RGB in a 2x2 block
         int r=(s[2] + s[6] + s[ss+2] + s[ss+6] + 2) >> 2;
         int g=(s[1] + s[5] + s[ss+1] + s[ss+5] + 2) >> 2;
         int b=(s[0] + s[4] + s[ss+0] + s[ss+4] + 2) >> 2;

         int Cb = (-1214*r - 2384*g + 3598*b + 4096 + 1048576)>>13;
         if(Cb<16)
            Cb=16;
         if(Cb>240)
            Cb=240;

         int Cr = (3598*r - 3013*g - 585*b + 4096 + 1048576)>>13;
         if(Cr<16)
            Cr=16;
         if(Cr>240)
            Cr=240;

         *d = Cb;
         *(d+size/4) = Cr;

         d+=1;
         s+=8;
      }
   }
   return true;
}
Exemple #3
0
/**
 * Return icon for a window by name
 *
 * @param n - resource name of window
 */
Icon *IconMap::getIconByName( std::string n )
{
	// try to resolve alias
	{
		AliasToFile::iterator i;

		if( (i = nameToFile.find( n )) != nameToFile.end() )
			n = (*i).second;
	}

	// cache look up
	{
		FileToIcon::iterator i;

		if( (i = cache.find( n )) != cache.end() )
			return (*i).second;
	}

	// load PNG file from disk
	{
		std::string file = n+".png";
		std::transform(
			file.begin(),
			file.end(),
			file.begin(),
			::tolower );

		for( Paths::const_iterator i = paths.begin();
			i != paths.end();
			++i )
		{
			std::string path = *i+file;
			struct stat buf;

			if( stat( path.c_str(), &buf ) > -1 )
			{
				ArgbSurface *s = Png::load( path );
				Icon *icon = createIcon( s, n, Icon::File );
				delete s;
				return icon;
			}
		}
	}

#ifdef HAVE_GTK
	// ask GNOME for icon
	{
		GtkIconTheme *theme = gtk_icon_theme_get_for_screen(
			gdk_screen_get_default() );
		GdkPixbuf *pixbuf = 0;

		// theme look up
		{
			GtkIconInfo *iconInfo = gtk_icon_theme_lookup_icon(
				theme,
				n.c_str(),
				128,
				GTK_ICON_LOOKUP_USE_BUILTIN );

			if( iconInfo )
			{
				pixbuf = gdk_pixbuf_new_from_file_at_size(
					gtk_icon_info_get_filename( iconInfo ),
					128,
					-1,
					0 );

				gtk_icon_info_free( iconInfo );
			}
		}

		// otherwise try to load the icon blindly
		if( !pixbuf )
			pixbuf = gtk_icon_theme_load_icon(
				theme,
				n.c_str(),
				128,
				GTK_ICON_LOOKUP_FORCE_SVG,
				0 );

		if( pixbuf &&
			gdk_pixbuf_get_colorspace( pixbuf ) == GDK_COLORSPACE_RGB &&
			gdk_pixbuf_get_bits_per_sample( pixbuf ) == 8 &&
			gdk_pixbuf_get_n_channels( pixbuf ) == 4 &&
			gdk_pixbuf_get_has_alpha( pixbuf ) )
		{
			unsigned char *src = reinterpret_cast<unsigned char *>(
				gdk_pixbuf_get_pixels( pixbuf ) );
			int w = gdk_pixbuf_get_width( pixbuf );
			int h = gdk_pixbuf_get_height( pixbuf );
			int p = gdk_pixbuf_get_rowstride( pixbuf )-(w<<2);
			ArgbSurface s( w, h );
			unsigned char *dest = reinterpret_cast<unsigned char *>(
				s.getData() );
			int dp = s.getPadding();

			// only 4-byte alignments are sane for 32 bits per pixel
			if( p%4 ||
				dp%4 )
				return 0;

			for( int y = s.getHeight(); y--; src += p, dest += dp )
				for( int x = s.getWidth(); x--; src += 4, dest += 4 )
				{
					// swap Red with Blue; GdkPixbuf has BGR order
					dest[0] = src[2];
					dest[1] = src[1];
					dest[2] = src[0];
					dest[3] = src[3];
				}

			return createIcon( &s, n, Icon::File );
		}
	}
#endif

#ifdef HAVE_KDE
	// ask KDE for icon
	{
		KIconLoader *loader;

		if( loader = KIconLoader::global() )
		{
			QPixmap pixmap = loader->loadIcon(
				n.c_str(),
				KIconLoader::Desktop,
				128,
				KIconLoader::DefaultState,
				QStringList(),
				0L,
				true );

			if( !pixmap.isNull() )
			{
				QImage image = pixmap.toImage();

				if( image.format() == QImage::Format_ARGB32_Premultiplied )
				{
					ArgbSurface s( image.width(), image.height() );
					unsigned char *dest = reinterpret_cast<unsigned char *>(
						s.getData() );
					unsigned char *src = reinterpret_cast<unsigned char *>(
						image.bits() );
					int p = image.bytesPerLine()-(image.width()<<2);
					int dp = s.getPadding();

					if( s.getBytesPerLine() == image.bytesPerLine() )
						memcpy( dest, src, s.getSize() );
					else
					{
						// only 4-byte alignments are sane for 32 bits per pixel
						if( p%4 ||
							dp%4 )
							return 0;

						for( int y = s.getHeight();
							y--;
							src += p, dest += dp )
							for( int x = s.getWidth();
								x--;
								src += 4, dest += 4 )
								*reinterpret_cast<uint32_t *>( dest ) =
									*reinterpret_cast<uint32_t *>( src );
					}

					return createIcon( &s, n, Icon::File );
				}
			}
		}
	}
#endif

	return 0;
}
QImage HistogramGenerator::calculateHistogram(const QSize &paradeSize, const QImage &image, const int &components,
                                              HistogramGenerator::Rec rec, const bool &unscaled, const uint &accelFactor) const
{
    if (paradeSize.height() <= 0 || paradeSize.width() <= 0 || image.width() <= 0 || image.height() <= 0) {
        return QImage();
    }

    bool drawY = (components & HistogramGenerator::ComponentY) != 0;
    bool drawR = (components & HistogramGenerator::ComponentR) != 0;
    bool drawG = (components & HistogramGenerator::ComponentG) != 0;
    bool drawB = (components & HistogramGenerator::ComponentB) != 0;
    bool drawSum = (components & HistogramGenerator::ComponentSum) != 0;

    int r[256], g[256], b[256], y[256], s[766];
    // Initialize the values to zero
    std::fill(r, r+256, 0);
    std::fill(g, g+256, 0);
    std::fill(b, b+256, 0);
    std::fill(y, y+256, 0);
    std::fill(s, s+766, 0);

    const uint iw = image.bytesPerLine();
    const uint ih = image.height();
    const uint ww = paradeSize.width();
    const uint wh = paradeSize.height();
    const uint byteCount = iw*ih;
    const uint stepsize = 4*accelFactor;

    const uchar *bits = image.bits();
    QRgb *col;


    // Read the stats from the input image
    for (uint i = 0; i < byteCount; i += stepsize) {
        col = (QRgb *)bits;

        r[qRed(*col)]++;
        g[qGreen(*col)]++;
        b[qBlue(*col)]++;
        if (drawY) {
            // Use if branch to avoid expensive multiplication if Y disabled
            if (rec == HistogramGenerator::Rec_601) {
                y[(int)floor(.299*qRed(*col) + .587*qGreen(*col) + .114*qBlue(*col))]++;
            } else {
                y[(int)floor(.2125*qRed(*col) + .7154*qGreen(*col) + .0721*qBlue(*col))]++;
            }
        }
        if (drawSum) {
            // Use an if branch here because the sum takes more operations than rgb
            s[qRed(*col)]++;
            s[qGreen(*col)]++;
            s[qBlue(*col)]++;
        }

        bits += stepsize;
    }


    const int nParts = (drawY ? 1 : 0) + (drawR ? 1 : 0) + (drawG ? 1 : 0) + (drawB ? 1 : 0) + (drawSum ? 1 : 0);
    if (nParts == 0) {
        // Nothing to draw
        return QImage();
    }

    const int d = 20; // Distance for text
    const int partH = (wh-nParts*d)/nParts;
    const float scaling = (float)partH/(byteCount >> 7);
    const int dist = 40;

    int wy = 0; // Drawing position

    QImage histogram(paradeSize, QImage::Format_ARGB32);
    QPainter davinci(&histogram);
    davinci.setPen(QColor(220, 220, 220, 255));
    histogram.fill(qRgba(0, 0, 0, 0));

    if (drawY) {
        drawComponentFull(&davinci, y, scaling, QRect(0, wy, ww, partH + dist), QColor(220, 220, 210, 255), dist, unscaled, 256);

        wy += partH + d;
    }

    if (drawSum) {
        drawComponentFull(&davinci, s, scaling/3, QRect(0, wy, ww, partH + dist), QColor(220, 220, 210, 255), dist, unscaled, 256);

        wy += partH + d;
    }

    if (drawR) {
        drawComponentFull(&davinci, r, scaling, QRect(0, wy, ww, partH + dist), QColor(255, 128, 0, 255), dist, unscaled, 256);

        wy += partH + d;
    }

    if (drawG) {
        drawComponentFull(&davinci, g, scaling, QRect(0, wy, ww, partH + dist), QColor(128, 255, 0, 255), dist, unscaled, 256);
        wy += partH + d;
    }

    if (drawB) {
        drawComponentFull(&davinci, b, scaling, QRect(0, wy, ww, partH + dist), QColor(0, 128, 255, 255), dist, unscaled, 256);

        wy += partH + d;
    }

    return histogram;
}
static cairo_status_t
_cairo_qt_surface_acquire_dest_image (void *abstract_surface,
				      cairo_rectangle_int_t *interest_rect,
				      cairo_image_surface_t **image_out,
				      cairo_rectangle_int_t *image_rect,
				      void **image_extra)
{
    cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
    QImage *qimg = NULL;

    D(fprintf(stderr, "q[%p] acquire_dest_image\n", abstract_surface));

    *image_extra = NULL;

    if (qs->image_equiv) {
        *image_out = (cairo_image_surface_t*)
                     cairo_surface_reference (qs->image_equiv);

        image_rect->x = qs->window.x();
        image_rect->y = qs->window.y();
        image_rect->width = qs->window.width();
        image_rect->height = qs->window.height();

        return CAIRO_STATUS_SUCCESS;
    }

    QPoint offset;

    if (qs->pixmap) {
        qimg = new QImage(qs->pixmap->toImage());
    } else {
        // Try to figure out what kind of QPaintDevice we have, and
        // how we can grab an image from it
        QPaintDevice *pd = qs->p->device();
	if (!pd)
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);

	QPaintDevice *rpd = QPainter::redirected(pd, &offset);
	if (rpd)
	    pd = rpd;

        if (pd->devType() == QInternal::Image) {
            qimg = new QImage(((QImage*) pd)->copy());
        } else if (pd->devType() == QInternal::Pixmap) {
            qimg = new QImage(((QPixmap*) pd)->toImage());
        } else if (pd->devType() == QInternal::Widget) {
            qimg = new QImage(QPixmap::grabWindow(((QWidget*)pd)->winId()).toImage());
        }
    }

    if (qimg == NULL)
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    *image_out = (cairo_image_surface_t*)
                 cairo_image_surface_create_for_data (qimg->bits(),
                                                      _cairo_format_from_qimage_format (qimg->format()),
                                                      qimg->width(), qimg->height(),
                                                      qimg->bytesPerLine());
    *image_extra = qimg;

    image_rect->x = qs->window.x() + offset.x();
    image_rect->y = qs->window.y() + offset.y();
    image_rect->width = qs->window.width() - offset.x();
    image_rect->height = qs->window.height() - offset.y();

    return CAIRO_STATUS_SUCCESS;
}
/*!
    This function decodes some data into image changes.

    Returns the number of bytes consumed.
*/
int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
                       int *nextFrameDelay, int *loopCount)
{
    // We are required to state that
    //    "The Graphics Interchange Format(c) is the Copyright property of
    //    CompuServe Incorporated. GIF(sm) is a Service Mark property of
    //    CompuServe Incorporated."

    if (!stack) {
        stack = new short[(1 << max_lzw_bits) * 4];
        table[0] = &stack[(1 << max_lzw_bits) * 2];
        table[1] = &stack[(1 << max_lzw_bits) * 3];
    }

    image->detach();
    int bpl = image->bytesPerLine();
    unsigned char *bits = image->bits();

#define LM(l, m) (((m)<<8)|l)
    digress = false;
    const int initial = length;
    while (!digress && length) {
        length--;
        unsigned char ch=*buffer++;
        switch (state) {
          case Header:
            hold[count++]=ch;
            if (count==6) {
                // Header
                gif89=(hold[3]!='8' || hold[4]!='7');
                state=LogicalScreenDescriptor;
                count=0;
            }
            break;
          case LogicalScreenDescriptor:
            hold[count++]=ch;
            if (count==7) {
                // Logical Screen Descriptor
                swidth=LM(hold[0], hold[1]);
                sheight=LM(hold[2], hold[3]);
                gcmap=!!(hold[4]&0x80);
                //UNUSED: bpchan=(((hold[4]&0x70)>>3)+1);
                //UNUSED: gcmsortflag=!!(hold[4]&0x08);
                gncols=2<<(hold[4]&0x7);
                bgcol=(gcmap) ? hold[5] : -1;
                //aspect=hold[6] ? double(hold[6]+15)/64.0 : 1.0;

                trans_index = -1;
                count=0;
                ncols=gncols;
                if (gcmap) {
                    ccount=0;
                    state=GlobalColorMap;
                    globalcmap = new QRgb[gncols+1]; // +1 for trans_index
                    globalcmap[gncols] = Q_TRANSPARENT;
                } else {
                    state=Introducer;
                }
            }
            break;
          case GlobalColorMap: case LocalColorMap:
            hold[count++]=ch;
            if (count==3) {
                QRgb rgb = qRgb(hold[0], hold[1], hold[2]);
                if (state == LocalColorMap) {
                    if (ccount < lncols)
                        localcmap[ccount] =  rgb;
                } else {
                    globalcmap[ccount] = rgb;
                }
                if (++ccount >= ncols) {
                    if (state == LocalColorMap)
                        state=TableImageLZWSize;
                    else
                        state=Introducer;
                }
                count=0;
            }
            break;
          case Introducer:
            hold[count++]=ch;
            switch (ch) {
              case ',':
                state=ImageDescriptor;
                break;
              case '!':
                state=ExtensionLabel;
                break;
              case ';':
                  // ### Changed: QRect(0, 0, swidth, sheight)
                state=Done;
                break;
              default:
                digress=true;
                // Unexpected Introducer - ignore block
                state=Error;
            }
            break;
          case ImageDescriptor:
            hold[count++]=ch;
            if (count==10) {
                int newleft=LM(hold[1], hold[2]);
                int newtop=LM(hold[3], hold[4]);
                int newwidth=LM(hold[5], hold[6]);
                int newheight=LM(hold[7], hold[8]);

                // disbelieve ridiculous logical screen sizes,
                // unless the image frames are also large.
                if (swidth/10 > qMax(newwidth,200))
                    swidth = -1;
                if (sheight/10 > qMax(newheight,200))
                    sheight = -1;

                if (swidth <= 0)
                    swidth = newleft + newwidth;
                if (sheight <= 0)
                    sheight = newtop + newheight;

                QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32;
                if (image->isNull()) {
                    (*image) = QImage(swidth, sheight, format);
                    bpl = image->bytesPerLine();
                    bits = image->bits();
                    memset(bits, 0, image->byteCount());
                }

                // Check if the previous attempt to create the image failed. If it
                // did then the image is broken and we should give up.
                if (image->isNull()) {
                    state = Error;
                    return -1;
                }

                disposePrevious(image);
                disposed = false;

                left = newleft;
                top = newtop;
                width = newwidth;
                height = newheight;

                right=qMax(0, qMin(left+width, swidth)-1);
                bottom=qMax(0, qMin(top+height, sheight)-1);
                lcmap=!!(hold[9]&0x80);
                interlace=!!(hold[9]&0x40);
                //bool lcmsortflag=!!(hold[9]&0x20);
                lncols=lcmap ? (2<<(hold[9]&0x7)) : 0;
                if (lncols) {
                    if (localcmap)
                        delete [] localcmap;
                    localcmap = new QRgb[lncols+1];
                    localcmap[lncols] = Q_TRANSPARENT;
                    ncols = lncols;
                } else {
                    ncols = gncols;
                }
                frame++;
                if (frame == 0) {
                    if (left || top || width<swidth || height<sheight) {
                        // Not full-size image - erase with bg or transparent
                        if (trans_index >= 0) {
                            fillRect(image, 0, 0, swidth, sheight, color(trans_index));
                            // ### Changed: QRect(0, 0, swidth, sheight)
                        } else if (bgcol>=0) {
                            fillRect(image, 0, 0, swidth, sheight, color(bgcol));
                            // ### Changed: QRect(0, 0, swidth, sheight)
                        }
                    }
                }

                if (disposal == RestoreImage) {
                    int l = qMin(swidth-1,left);
                    int r = qMin(swidth-1,right);
                    int t = qMin(sheight-1,top);
                    int b = qMin(sheight-1,bottom);
                    int w = r-l+1;
                    int h = b-t+1;

                    if (backingstore.width() < w
                        || backingstore.height() < h) {
                        // We just use the backing store as a byte array
                        backingstore = QImage(qMax(backingstore.width(), w),
                                              qMax(backingstore.height(), h),
                                              QImage::Format_RGB32);
                        memset(bits, 0, image->byteCount());
                    }
                    const int dest_bpl = backingstore.bytesPerLine();
                    unsigned char *dest_data = backingstore.bits();
                    for (int ln=0; ln<h; ln++) {
                        memcpy(FAST_SCAN_LINE(dest_data, dest_bpl, ln),
                               FAST_SCAN_LINE(bits, bpl, t+ln) + l, w*sizeof(QRgb));
                    }
                }

                count=0;
                if (lcmap) {
                    ccount=0;
                    state=LocalColorMap;
                } else {
                    state=TableImageLZWSize;
                }
                x = left;
                y = top;
                accum = 0;
                bitcount = 0;
                sp = stack;
                firstcode = oldcode = 0;
                needfirst = true;
                out_of_bounds = left>=swidth || y>=sheight;
            }
            break;
          case TableImageLZWSize: {
            lzwsize=ch;
            if (lzwsize > max_lzw_bits) {
                state=Error;
            } else {
                code_size=lzwsize+1;
                clear_code=1<<lzwsize;
                end_code=clear_code+1;
                max_code_size=2*clear_code;
                max_code=clear_code+2;
                int i;
                for (i=0; i<clear_code; i++) {
                    table[0][i]=0;
                    table[1][i]=i;
                }
                state=ImageDataBlockSize;
            }
            count=0;
            break;
          } case ImageDataBlockSize:
            expectcount=ch;
            if (expectcount) {
                state=ImageDataBlock;
            } else {
                state=Introducer;
                digress = true;
                newFrame = true;
            }
            break;
          case ImageDataBlock:
            count++;
            accum|=(ch<<bitcount);
            bitcount+=8;
            while (bitcount>=code_size && state==ImageDataBlock) {
                int code=accum&((1<<code_size)-1);
                bitcount-=code_size;
                accum>>=code_size;

                if (code==clear_code) {
                    if (!needfirst) {
                        code_size=lzwsize+1;
                        max_code_size=2*clear_code;
                        max_code=clear_code+2;
                    }
                    needfirst=true;
                } else if (code==end_code) {
                    bitcount = -32768;
                    // Left the block end arrive
                } else {
                    if (needfirst) {
                        firstcode=oldcode=code;
                        if (!out_of_bounds && image->height() > y && ((frame == 0) || (firstcode != trans_index)))
                            ((QRgb*)FAST_SCAN_LINE(bits, bpl, y))[x] = color(firstcode);
                        x++;
                        if (x>=swidth) out_of_bounds = true;
                        needfirst=false;
                        if (x>=left+width) {
                            x=left;
                            out_of_bounds = left>=swidth || y>=sheight;
                            nextY(bits, bpl);
                        }
                    } else {
                        incode=code;
                        if (code>=max_code) {
                            *sp++=firstcode;
                            code=oldcode;
                        }
                        while (code>=clear_code+2) {
                            if (code >= max_code) {
                                state = Error;
                                return -1;
                            }
                            *sp++=table[1][code];
                            if (code==table[0][code]) {
                                state=Error;
                                return -1;
                            }
                            if (sp-stack>=(1<<(max_lzw_bits))*2) {
                                state=Error;
                                return -1;
                            }
                            code=table[0][code];
                        }
                        if (code < 0) {
                            state = Error;
                            return -1;
                        }

                        *sp++=firstcode=table[1][code];
                        code=max_code;
                        if (code<(1<<max_lzw_bits)) {
                            table[0][code]=oldcode;
                            table[1][code]=firstcode;
                            max_code++;
                            if ((max_code>=max_code_size)
                             && (max_code_size<(1<<max_lzw_bits)))
                            {
                                max_code_size*=2;
                                code_size++;
                            }
                        }
                        oldcode=incode;
                        const int h = image->height();
                        QRgb *line = 0;
                        if (!out_of_bounds && h > y)
                            line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y);
                        while (sp>stack) {
                            const uchar index = *(--sp);
                            if (!out_of_bounds && h > y && ((frame == 0) || (index != trans_index))) {
                                line[x] = color(index);
                            }
                            x++;
                            if (x>=swidth) out_of_bounds = true;
                            if (x>=left+width) {
                                x=left;
                                out_of_bounds = left>=swidth || y>=sheight;
                                nextY(bits, bpl);
                                if (!out_of_bounds && h > y)
                                    line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y);
                            }
                        }
                    }
                }
            }
            partialNewFrame = true;
            if (count==expectcount) {
                count=0;
                state=ImageDataBlockSize;
            }
            break;
          case ExtensionLabel:
            switch (ch) {
            case 0xf9:
                state=GraphicControlExtension;
                break;
            case 0xff:
                state=ApplicationExtension;
                break;
#if 0
            case 0xfe:
                state=CommentExtension;
                break;
            case 0x01:
                break;
#endif
            default:
                state=SkipBlockSize;
            }
            count=0;
            break;
          case ApplicationExtension:
            if (count<11) hold[count]=ch;
            count++;
            if (count==hold[0]+1) {
                if (qstrncmp((char*)(hold+1), "NETSCAPE", 8)==0) {
                    // Looping extension
                    state=NetscapeExtensionBlockSize;
                } else {
                    state=SkipBlockSize;
                }
                count=0;
            }
            break;
          case NetscapeExtensionBlockSize:
            expectcount=ch;
            count=0;
            if (expectcount) state=NetscapeExtensionBlock;
            else state=Introducer;
            break;
          case NetscapeExtensionBlock:
            if (count<3) hold[count]=ch;
            count++;
            if (count==expectcount) {
                *loopCount = hold[1]+hold[2]*256;
                state=SkipBlockSize; // Ignore further blocks
            }
            break;
          case GraphicControlExtension:
            if (count<5) hold[count]=ch;
            count++;
            if (count==hold[0]+1) {
                disposePrevious(image);
                disposal=Disposal((hold[1]>>2)&0x7);
                //UNUSED: waitforuser=!!((hold[1]>>1)&0x1);
                int delay=count>3 ? LM(hold[2], hold[3]) : 1;
                // IE and mozilla use a minimum delay of 10. With the minimum delay of 10
                // we are compatible to them and avoid huge loads on the app and xserver.
                *nextFrameDelay = (delay < 2 ? 10 : delay) * 10;

                bool havetrans=hold[1]&0x1;
                trans_index = havetrans ? hold[4] : -1;

                count=0;
                state=SkipBlockSize;
            }
            break;
          case SkipBlockSize:
            expectcount=ch;
            count=0;
            if (expectcount) state=SkipBlock;
            else state=Introducer;
            break;
          case SkipBlock:
            count++;
            if (count==expectcount) state=SkipBlockSize;
            break;
          case Done:
            digress=true;
            /* Netscape ignores the junk, so we do too.
            length++; // Unget
            state=Error; // More calls to this is an error
            */
            break;
          case Error:
            return -1; // Called again after done.
        }
    }
bool ParupaintPanvasInputOutput::exportGIF(ParupaintPanvas * panvas, const QString & filename, QString & errorStr)
{
	Q_ASSERT(panvas);
	if(filename.isEmpty())
		return (errorStr = "Enter a filename to save to.").isEmpty();

#ifndef PARUPAINT_NOGIF
	int error = 0;
	GifFileType * gif = EGifOpenFileName(filename.toStdString().c_str(), false, &error);

	foreach(const QImage & image, panvas->mergedImageFrames(true)){

		error = 0;
		bool alpha = false;
		QImage toWrite = convertToIndexed8(image, &alpha);

		QVector<QRgb> colorTable = toWrite.colorTable();
		ColorMapObject cmap;

		int numColors = 1 << BitSize(toWrite.colorCount());
		numColors = 256;

		cmap.ColorCount = numColors;
		cmap.BitsPerPixel = 8;	/// @todo based on numColors (or not? we did ask for Format_Indexed8, so the data is always 8-bit, right?)
		GifColorType* colorValues = (GifColorType*)malloc(cmap.ColorCount * sizeof(GifColorType));
		cmap.Colors = colorValues;
		int c = 0;
		for(; c < toWrite.colorCount(); ++c)
		{
			//qDebug("color %d has %02X%02X%02X", c, qRed(colorTable[c]), qGreen(colorTable[c]), qBlue(colorTable[c]));
			colorValues[c].Red = qRed(colorTable[c]);
			colorValues[c].Green = qGreen(colorTable[c]);
			colorValues[c].Blue = qBlue(colorTable[c]);
		}
		// In case we had an actual number of colors that's not a power of 2,
		// fill the rest with something (black perhaps).
		for (; c < numColors; ++c)
		{
			colorValues[c].Red = 0;
			colorValues[c].Green = 0;
			colorValues[c].Blue = 0;
		}

		/// @todo how to specify which version, or decide based on features in use
		// Because of this call, libgif is not re-entrant
		EGifSetGifVersion(gif, true);

		if ((error = EGifPutScreenDesc(gif, toWrite.width(), toWrite.height(), numColors, 0, &cmap)) == GIF_ERROR)
			qCritical("EGifPutScreenDesc returned error %d", error);

		int fps = (100.0/panvas->frameRate());

		char flags = 1 << 3;
		if(alpha) flags |= 1;

		char graphics_ext[] = {
			flags,
			(char)(fps % 256), (char)(fps / 256),
			(char)(alpha ? 0x00 : 0xff)
		};
		EGifPutExtension(gif, GRAPHICS_EXT_FUNC_CODE, 4, graphics_ext);

		if ((error = EGifPutImageDesc(gif, 0, 0, toWrite.width(), toWrite.height(), 0, &cmap)) == GIF_ERROR)
			qCritical("EGifPutImageDesc returned error %d", error);

		int lc = toWrite.height();
		int llen = toWrite.bytesPerLine();
		for (int l = 0; l < lc; ++l) {
			uchar* line = toWrite.scanLine(l);
			if ((error = EGifPutLine(gif, (GifPixelType*)line, llen)) == GIF_ERROR) {
				qCritical("EGifPutLine returned error %d", error);
			}
		}

		if(true){
			// loop forever
			unsigned char loopblock[3] = {1, 0, 0};
			EGifPutExtensionLeader(gif, APPLICATION_EXT_FUNC_CODE);
			EGifPutExtensionBlock(gif, 11, "NETSCAPE2.0");
			EGifPutExtensionBlock(gif, 3, loopblock);
			EGifPutExtensionTrailer(gif);
		}
	}

	EGifCloseFile(gif, &error);
	return true;
#endif
	return (errorStr = "GIF export not available.").isEmpty();
}
void blur( QImage& image, int radius )
{
    int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
    int alpha = (radius < 1)  ? 16 : (radius > 17) ? 1 : tab[radius-1];

    int r1 = 0;
    int r2 = image.height() - 1;
    int c1 = 0;
    int c2 = image.width() - 1;

    int bpl = image.bytesPerLine();
    int rgba[4];
    unsigned char* p;

    int i1 = 0;
    int i2 = 3;

    for (int col = c1; col <= c2; col++) {
        p = image.scanLine(r1) + col * 4;
        for (int i = i1; i <= i2; i++)
            rgba[i] = p[i] << 4;

        p += bpl;
        for (int j = r1; j < r2; j++, p += bpl)
            for (int i = i1; i <= i2; i++)
                p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
    }

    for (int row = r1; row <= r2; row++) {
        p = image.scanLine(row) + c1 * 4;
        for (int i = i1; i <= i2; i++)
            rgba[i] = p[i] << 4;

        p += 4;
        for (int j = c1; j < c2; j++, p += 4)
            for (int i = i1; i <= i2; i++)
                p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
    }

    for (int col = c1; col <= c2; col++) {
        p = image.scanLine(r2) + col * 4;
        for (int i = i1; i <= i2; i++)
            rgba[i] = p[i] << 4;

        p -= bpl;
        for (int j = r1; j < r2; j++, p -= bpl)
            for (int i = i1; i <= i2; i++)
                p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
    }

    for (int row = r1; row <= r2; row++) {
        p = image.scanLine(row) + c2 * 4;
        for (int i = i1; i <= i2; i++)
            rgba[i] = p[i] << 4;

        p -= 4;
        for (int j = c1; j < c2; j++, p -= 4)
            for (int i = i1; i <= i2; i++)
                p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
    }

}
Exemple #9
0
static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QByteArray &sourceFormat)
{
    QByteArray str;
    QImage image = sourceImage;
    QByteArray format = sourceFormat;

    format = format.left(3);                        // ignore RAW part
    bool gray = format == "pgm";

    if (format == "pbm") {
        image = image.convertToFormat(QImage::Format_Mono);
    } else if (image.depth() == 1) {
        image = image.convertToFormat(QImage::Format_Indexed8);
    } else {
        switch (image.format()) {
        case QImage::Format_RGB16:
        case QImage::Format_RGB666:
        case QImage::Format_RGB555:
        case QImage::Format_RGB888:
        case QImage::Format_RGB444:
            image = image.convertToFormat(QImage::Format_RGB32);
            break;
        case QImage::Format_ARGB8565_Premultiplied:
        case QImage::Format_ARGB6666_Premultiplied:
        case QImage::Format_ARGB8555_Premultiplied:
        case QImage::Format_ARGB4444_Premultiplied:
            image = image.convertToFormat(QImage::Format_ARGB32);
            break;
        default:
            break;
        }
    }

    if (image.depth() == 1 && image.colorCount() == 2) {
        if (qGray(image.color(0)) < qGray(image.color(1))) {
            // 0=dark/black, 1=light/white - invert
            image.detach();
            for (int y=0; y<image.height(); y++) {
                uchar *p = image.scanLine(y);
                uchar *end = p + image.bytesPerLine();
                while (p < end)
                    *p++ ^= 0xff;
            }
        }
    }

    uint w = image.width();
    uint h = image.height();

    str = "P\n";
    str += QByteArray::number(w);
    str += ' ';
    str += QByteArray::number(h);
    str += '\n';

    switch (image.depth()) {
        case 1: {
            str.insert(1, '4');
            if (out->write(str, str.length()) != str.length())
                return false;
            w = (w+7)/8;
            for (uint y=0; y<h; y++) {
                uchar* line = image.scanLine(y);
                if (w != (uint)out->write((char*)line, w))
                    return false;
            }
            }
            break;

        case 8: {
            str.insert(1, gray ? '5' : '6');
            str.append("255\n");
            if (out->write(str, str.length()) != str.length())
                return false;
            QVector<QRgb> color = image.colorTable();
            uint bpl = w*(gray ? 1 : 3);
            uchar *buf   = new uchar[bpl];
            for (uint y=0; y<h; y++) {
                uchar *b = image.scanLine(y);
                uchar *p = buf;
                uchar *end = buf+bpl;
                if (gray) {
                    while (p < end) {
                        uchar g = (uchar)qGray(color[*b++]);
                        *p++ = g;
                    }
                } else {
                    while (p < end) {
                        QRgb rgb = color[*b++];
                        *p++ = qRed(rgb);
                        *p++ = qGreen(rgb);
                        *p++ = qBlue(rgb);
                    }
                }
                if (bpl != (uint)out->write((char*)buf, bpl))
                    return false;
            }
            delete [] buf;
            }
            break;

        case 32: {
            str.insert(1, gray ? '5' : '6');
            str.append("255\n");
            if (out->write(str, str.length()) != str.length())
                return false;
            uint bpl = w*(gray ? 1 : 3);
            uchar *buf = new uchar[bpl];
            for (uint y=0; y<h; y++) {
                QRgb  *b = (QRgb*)image.scanLine(y);
                uchar *p = buf;
                uchar *end = buf+bpl;
                if (gray) {
                    while (p < end) {
                        uchar g = (uchar)qGray(*b++);
                        *p++ = g;
                    }
                } else {
                    while (p < end) {
                        QRgb rgb = *b++;
                        *p++ = qRed(rgb);
                        *p++ = qGreen(rgb);
                        *p++ = qBlue(rgb);
                    }
                }
                if (bpl != (uint)out->write((char*)buf, bpl))
                    return false;
            }
            delete [] buf;
            }
            break;

    default:
        return false;
    }

    return true;
}
// Thanks StackOverflow for this algorithm (works like a charm without any changes)
QImage ImageUtils::blurred(const QImage& image, const QRect& rect, int radius, bool alphaOnly)
{
	int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
	int alpha = (radius < 1)  ? 16 : (radius > 17) ? 1 : tab[radius-1];

	QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
	int r1 = rect.top();
	int r2 = rect.bottom();
	int c1 = rect.left();
	int c2 = rect.right();

	int bpl = result.bytesPerLine();
	int rgba[4];
	unsigned char* p;

	int i1 = 0;
	int i2 = 3;

	if (alphaOnly)
		i1 = i2 = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3);

	for (int col = c1; col <= c2; col++) {
		p = result.scanLine(r1) + col * 4;
		for (int i = i1; i <= i2; i++)
			rgba[i] = p[i] << 4;

		p += bpl;
		for (int j = r1; j < r2; j++, p += bpl)
			for (int i = i1; i <= i2; i++)
				p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
	}

	for (int row = r1; row <= r2; row++) {
		p = result.scanLine(row) + c1 * 4;
		for (int i = i1; i <= i2; i++)
			rgba[i] = p[i] << 4;

		p += 4;
		for (int j = c1; j < c2; j++, p += 4)
			for (int i = i1; i <= i2; i++)
				p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
	}

	for (int col = c1; col <= c2; col++) {
		p = result.scanLine(r2) + col * 4;
		for (int i = i1; i <= i2; i++)
			rgba[i] = p[i] << 4;

		p -= bpl;
		for (int j = r1; j < r2; j++, p -= bpl)
			for (int i = i1; i <= i2; i++)
				p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
	}

	for (int row = r1; row <= r2; row++) {
		p = result.scanLine(row) + c2 * 4;
		for (int i = i1; i <= i2; i++)
			rgba[i] = p[i] << 4;

		p -= 4;
		for (int j = c1; j < c2; j++, p -= 4)
			for (int i = i1; i <= i2; i++)
				p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
	}

	return result;
}
Mat qimage2mat(QImage& qimage) {
    cv::Mat tmp(qimage.height(),qimage.width(),CV_8UC3,(uchar*)qimage.bits(),qimage.bytesPerLine());
    cv::Mat result; // deep copy just in case (my lack of knowledge with open cv)
    cvtColor(tmp, result,CV_BGR2RGB);
    return result;
}
Exemple #12
0
QImage Filter::process(const QImage &inputImage)
{
    if (inputImage.isNull() || inputImage.format() != QImage::Format_ARGB32)
        return inputImage;

    ImageHistogram histogram;
    double inputBlackPoint[3], inputWhitePoint[3], inputGamma[3], outputBlackPoint[3], outputWhitePoint[3];
    unsigned char mLuts[3][256];
    double clippingShadows = mClippingShadows / 100., clippingHighlights = mClippingHighlights / 100.;
    double mean;

    if (mEnhanceChannelsSeparately)
    {
        histogram.computeHistogram(inputImage.bits(), inputImage.width(), inputImage.height(), ImageHistogram::RGB,
                                   inputImage.bytesPerLine());

        for (int i = 0; i < 3; i++)
        {
            const ImageHistogram::Channel channel = (ImageHistogram::Channel)(1 << i);

            if (qFuzzyIsNull(clippingShadows))
                inputBlackPoint[i] = histogram.limit(channel, ProbabilityMassFunction::A);
            else
                inputBlackPoint[i] = histogram.integrate2(channel, clippingShadows);

            if (qFuzzyIsNull(clippingHighlights))
                inputWhitePoint[i] = histogram.limit(channel, ProbabilityMassFunction::B);
            else
                inputWhitePoint[i] = histogram.integrate2(channel, -clippingHighlights);

            if (mAdjustMidtones)
            {
                mean = (histogram.mean(channel) - inputBlackPoint[i]) /
                       (inputWhitePoint[i] - inputBlackPoint[i]);
                inputGamma[i] = AT_clamp(.1, 1. /
                                         (log(i == 0 ? mTargetColorMidtones.blueF() :
                                             i == 1 ? mTargetColorMidtones.greenF() : mTargetColorMidtones.redF()) /
                                         log(mean)),
                                         10.);
            }
            else
                inputGamma[i] = 1.;

            inputBlackPoint[i] /= 255.;
            inputWhitePoint[i] /= 255.;
        }
    }
    else
    {
        histogram.computeHistogram(inputImage.bits(), inputImage.width(), inputImage.height(), ImageHistogram::Luma,
                                   inputImage.bytesPerLine());

        if (qFuzzyIsNull(clippingShadows))
            inputBlackPoint[0] = inputBlackPoint[1] = inputBlackPoint[2] =
                    histogram.limit(ImageHistogram::Luma, ProbabilityMassFunction::A);
        else
            inputBlackPoint[0] = inputBlackPoint[1] = inputBlackPoint[2] =
                    histogram.integrate2(ImageHistogram::Luma, clippingShadows);

        if (qFuzzyIsNull(clippingHighlights))
            inputWhitePoint[0] = inputWhitePoint[1] = inputWhitePoint[2] =
                    histogram.limit(ImageHistogram::Luma, ProbabilityMassFunction::B);
        else
            inputWhitePoint[0] = inputWhitePoint[1] = inputWhitePoint[2] =
                    histogram.integrate2(ImageHistogram::Luma, -clippingHighlights);

        if (mAdjustMidtones)
        {
            mean = (histogram.mean(ImageHistogram::Luma) - inputBlackPoint[0]) /
                   (inputWhitePoint[0] - inputBlackPoint[0]);
            for (int i = 0; i < 3; i++)
            {
                inputGamma[i] = AT_clamp(.1, 1. /
                                         (log(i == 0 ? mTargetColorMidtones.blueF() :
                                             i == 1 ? mTargetColorMidtones.greenF() : mTargetColorMidtones.redF()) /
                                         log(mean)),
                                         10.);
            }
        }
        else
            inputGamma[0] = inputGamma[1] = inputGamma[2] = 1.;

        inputBlackPoint[0] = inputBlackPoint[1] = inputBlackPoint[2] = inputBlackPoint[0] / 255.;
        inputWhitePoint[0] = inputWhitePoint[1] = inputWhitePoint[2] = inputWhitePoint[0] / 255.;
    }

    outputBlackPoint[0] = mTargetColorShadows.blueF();
    outputBlackPoint[1] = mTargetColorShadows.greenF();
    outputBlackPoint[2] = mTargetColorShadows.redF();
    outputWhitePoint[0] = mTargetColorHighlights.blueF();
    outputWhitePoint[1] = mTargetColorHighlights.greenF();
    outputWhitePoint[2] = mTargetColorHighlights.redF();

    generateLevelsLUT(mLuts[0], inputGamma[0], inputBlackPoint[0], inputWhitePoint[0],
                      outputBlackPoint[0], outputWhitePoint[0]);
    generateLevelsLUT(mLuts[1], inputGamma[1], inputBlackPoint[1], inputWhitePoint[1],
                      outputBlackPoint[1], outputWhitePoint[1]);
    generateLevelsLUT(mLuts[2], inputGamma[2], inputBlackPoint[2], inputWhitePoint[2],
                      outputBlackPoint[2], outputWhitePoint[2]);

    QImage i = QImage(inputImage.width(), inputImage.height(), QImage::Format_ARGB32);

    register BGRA * bits = (BGRA*)inputImage.bits();
    register BGRA * bits2 = (BGRA*)i.bits();
    register int totalPixels = i.width() * i.height();

    while (totalPixels--)
    {
        bits2->b = mLuts[0][bits->b];
        bits2->g = mLuts[1][bits->g];
        bits2->r = mLuts[2][bits->r];
        bits2->a = bits->a;
        bits++;
        bits2++;
    }

    return i;
}
Exemple #13
0
/* You can also find a BSD version to this method from
 * http://gitorious.org/ofi-labs/x2/blobs/master/graphics/shadowblur/
 */
void KoShapeShadow::Private::blurShadow(QImage &image, int radius, const QColor& shadowColor)
{
    static const int BlurSumShift = 15;

    // Check http://www.w3.org/TR/SVG/filters.html#
    // As noted in the SVG filter specification, ru
    // approximates a real gaussian blur nicely.
    // See comments in http://webkit.org/b/40793, it seems sensible
    // to follow Skia's limit of 128 pixels for the blur radius.
    if (radius > 128)
        radius = 128;

    int channels[4] = { 3, 0, 1, 3 };
    int dmax = radius >> 1;
    int dmin = dmax - 1 + (radius & 1);
    if (dmin < 0)
        dmin = 0;

    // Two stages: horizontal and vertical
    for (int k = 0; k < 2; ++k) {

        unsigned char* pixels = image.bits();
        int stride = (k == 0) ? 4 : image.bytesPerLine();
        int delta = (k == 0) ? image.bytesPerLine() : 4;
        int jfinal = (k == 0) ? image.height() : image.width();
        int dim = (k == 0) ? image.width() : image.height();

        for (int j = 0; j < jfinal; ++j, pixels += delta) {

            // For each step, we blur the alpha in a channel and store the result
            // in another channel for the subsequent step.
            // We use sliding window algorithm to accumulate the alpha values.
            // This is much more efficient than computing the sum of each pixels
            // covered by the box kernel size for each x.

            for (int step = 0; step < 3; ++step) {
                int side1 = (step == 0) ? dmin : dmax;
                int side2 = (step == 1) ? dmin : dmax;
                int pixelCount = side1 + 1 + side2;
                int invCount = ((1 << BlurSumShift) + pixelCount - 1) / pixelCount;
                int ofs = 1 + side2;
                int alpha1 = pixels[channels[step]];
                int alpha2 = pixels[(dim - 1) * stride + channels[step]];
                unsigned char* ptr = pixels + channels[step + 1];
                unsigned char* prev = pixels + stride + channels[step];
                unsigned char* next = pixels + ofs * stride + channels[step];

                int i;
                int sum = side1 * alpha1 + alpha1;
                int limit = (dim < side2 + 1) ? dim : side2 + 1;
                for (i = 1; i < limit; ++i, prev += stride)
                    sum += *prev;
                if (limit <= side2)
                    sum += (side2 - limit + 1) * alpha2;

                limit = (side1 < dim) ? side1 : dim;
                for (i = 0; i < limit; ptr += stride, next += stride, ++i, ++ofs) {
                    *ptr = (sum * invCount) >> BlurSumShift;
                    sum += ((ofs < dim) ? *next : alpha2) - alpha1;
                }
                prev = pixels + channels[step];
                for (; ofs < dim; ptr += stride, prev += stride, next += stride, ++i, ++ofs) {
                    *ptr = (sum * invCount) >> BlurSumShift;
                    sum += (*next) - (*prev);
                }
                for (; i < dim; ptr += stride, prev += stride, ++i) {
                    *ptr = (sum * invCount) >> BlurSumShift;
                    sum += alpha2 - (*prev);
                }
            }
        }
    }

    // "Colorize" with the right shadow color.
    QPainter p(&image);
    p.setCompositionMode(QPainter::CompositionMode_SourceIn);
    p.fillRect(image.rect(), shadowColor);
    p.end();
}
Exemple #14
0
void GLWidget::paintGL()
{
	if (data.currentFile != data.nextFile) {
		if (data.nextFile == -1)
			loadShaders(data.filePath);
		else
			loadShaders(fileList[data.nextFile]);
		data.currentFile = data.nextFile;
		data.zoom = 0;
		data.moveX = 0;
		data.moveY = 0;
		data.pause = false;
		updateTitle();
	}
	double posX = (data.moveX + 1.) * float(DIM / 2);
	double posY = (data.moveY - 1.) * float(DIM / 2) * -1.;
	glUniform1ui(data.loc.dim, DIM);
	glUniform1f(data.loc.zoom, data.zoom);
	glUniform2d(data.loc.position, posX, posY);
	glVertexAttribPointer(data.loc.vertex, 2, GL_FLOAT, GL_FALSE, 0, data.vertex.constData());

	if (data.loc.animation != -1 && !data.pause) {
		glUniform1f((float)data.loc.animation,
			    (double)QTime::currentTime().msecsSinceStartOfDay() / 1000.);
		update();
	}

	render();
	if (!data.saving)
		return;
	data.saving = false;

	QImage *img = saveDialog->img;
	QImage imgRen(data.save.blockSize, QImage::Format_RGB888);
	if (img == 0) {
		saveDialog->failed(tr("img allocation failed"));
		return;
	}
	if (img->isNull()) {
		saveDialog->failed(tr("img is null"));
		return;
	}
	if (imgRen.isNull()) {
		saveDialog->failed(tr("imgRen is null"));
		return;
	}

	QOpenGLFramebufferObject fbo(data.save.blockSize);
	fbo.bind();
	glViewport(0, 0, data.save.blockSize.width(), data.save.blockSize.height());
	QPoint pos;
	int w = data.save.blockSize.width() * data.save.blockCount.width();
	int h = data.save.blockSize.height() * data.save.blockCount.height();
	float asp = (float)h / (float)w;
render:
	// Select region
	data.projection.setToIdentity();
	float left = float(2 * pos.x() - data.save.blockCount.width()) / data.save.blockCount.width();
	float top = float(2 * pos.y() - data.save.blockCount.height()) / data.save.blockCount.height();
	data.projection.ortho(left, left + 2. / data.save.blockCount.width(),
			      asp * top, asp * (top + 2. / data.save.blockCount.height()), -1., 1.);
	render();

	QPoint imgPos(pos.x() * data.save.blockSize.width(), pos.y() * data.save.blockSize.height());
	glReadPixels(0, 0, imgRen.width(), imgRen.height(), GL_RGB, GL_UNSIGNED_BYTE, imgRen.bits());
	unsigned char *imgPtr = img->scanLine(img->height() - imgPos.y() - 1) + imgPos.x() * 3;
	for (int i = 0; i < imgRen.height(); i++) {
		memcpy(imgPtr, imgRen.constScanLine(i), imgRen.bytesPerLine());
		imgPtr -= img->bytesPerLine();
	}

	if (pos.x() != data.save.blockCount.width() - 1)
		pos.setX(pos.x() + 1);
	else if (pos.y() != data.save.blockCount.height() - 1) {
		pos.setX(0);
		pos.setY(pos.y() + 1);
	} else {
		fbo.release();
		resizeGL(width(), height());
		saveDialog->done();
		return;
	}
	goto render;
}
Exemple #15
0
QPixmap QPixmap::fromImage(const QImage &img, Qt::ImageConversionFlags flags)
{
    QPixmap pixmap;
    if(img.isNull()) {
        qWarning("QPixmap::convertFromImage: Cannot convert a null image");
        return pixmap;
    }

    QImage image = img;
    int    d     = image.depth();
    int    dd    = defaultDepth();
    bool force_mono = (dd == 1 ||
                       (flags & Qt::ColorMode_Mask)==Qt::MonoOnly);
    if(force_mono) {                         // must be monochrome
        if(d != 1) {
            image = image.convertToFormat(QImage::Format_MonoLSB, flags);  // dither
            d = 1;
        }
    } else {                                    // can be both
        bool conv8 = false;
        if(d > 8 && dd <= 8) {               // convert to 8 bit
            if((flags & Qt::DitherMode_Mask) == Qt::AutoDither)
                flags = (flags & ~Qt::DitherMode_Mask)
                                   | Qt::PreferDither;
            conv8 = true;
        } else if((flags & Qt::ColorMode_Mask) == Qt::ColorOnly) {
            conv8 = d == 1;                     // native depth wanted
        } else if(d == 1) {
            if(image.numColors() == 2) {
                QRgb c0 = image.color(0);       // Auto: convert to best
                QRgb c1 = image.color(1);
                conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255);
            } else {
                // eg. 1-color monochrome images (they do exist).
                conv8 = true;
            }
        }
        if(conv8) {
            image = image.convertToFormat(QImage::Format_Indexed8, flags);
            d = 8;
        }
    }

    if(image.depth()==1) {
        image.setColor(0, QColor(Qt::color0).rgba());
        image.setColor(1, QColor(Qt::color1).rgba());
    }

    if (d == 16) {
        QImage im = image.convertToFormat(QImage::Format_RGB32, flags);
        return fromImage(im);
    }

    int w = image.width();
    int h = image.height();

    // different size or depth, make a new pixmap
    if (d == 1)
        pixmap = QBitmap(w, h);
    else
        pixmap = QPixmap(w, h);

    quint32 *dptr = pixmap.data->pixels, *drow;
    const uint dbpr = pixmap.data->nbytes / h;

    const QImage::Format sfmt = image.format();
    const unsigned short sbpr = image.bytesPerLine();
    uchar *sptr = image.bits(), *srow;

    for(int y=0;y<h;y++) {
        drow = dptr + (y * (dbpr / 4));
        srow = sptr + (y * sbpr);
        switch(sfmt) {
        case QImage::Format_MonoLSB:
        case QImage::Format_Mono:{
            for(int x=0;x<w;++x) {
                char one_bit = *(srow + (x / 8));
                if(sfmt == QImage::Format_Mono)
                    one_bit = one_bit >> (7 - (x % 8));
                else
                    one_bit = one_bit >> (x % 8);
                if((one_bit & 0x01))
                    *(drow+x) = 0x00000000;
                else
                    *(drow+x) = 0xFFFFFFFF;
            }
            break; }
        case QImage::Format_Indexed8:
            for(int x=0;x<w;++x) {
                *(drow+x) = PREMUL(image.color(*(srow + x)));
            }
            break;
        case QImage::Format_RGB32:
            for(int x=0;x<w;++x)
                *(drow+x) = *(((quint32*)srow) + x) | 0xFF000000;
            break;
        case QImage::Format_ARGB32:
        case QImage::Format_ARGB32_Premultiplied:
            for(int x=0;x<w;++x) {
                if(sfmt == QImage::Format_RGB32)
                    *(drow+x) = 0xFF000000 | (*(((quint32*)srow) + x) & 0x00FFFFFF);
                else if(sfmt == QImage::Format_ARGB32_Premultiplied)
                    *(drow+x) = *(((quint32*)srow) + x);
                else
                    *(drow+x) = PREMUL(*(((quint32*)srow) + x));
            }
            break;
        default:
            qWarning("Qt: internal: Oops: Forgot a format [%d] %s:%d", sfmt,
                     __FILE__, __LINE__);
            break;
        }
    }
Exemple #16
0
// mostly duplicated from qimage.cpp (QImageData::checkForAlphaPixels)
static bool checkForAlphaPixels(const QImage &img)
{
    const uchar *bits = img.bits();
    const int bytes_per_line = img.bytesPerLine();
    const uchar *end_bits = bits + bytes_per_line;
    const int width = img.width();
    const int height = img.height();
    switch (img.format()) {
    case QImage::Format_Indexed8:
        return img.hasAlphaChannel();
    case QImage::Format_ARGB32:
    case QImage::Format_ARGB32_Premultiplied:
        for (int y=0; y<height; ++y) {
            for (int x=0; x<width; ++x) {
                if ((((uint *)bits)[x] & 0xff000000) != 0xff000000) {
                    return true;
                }
            }
            bits += bytes_per_line;
        }
        break;

    case QImage::Format_ARGB8555_Premultiplied:
    case QImage::Format_ARGB8565_Premultiplied:
        for (int y=0; y<height; ++y) {
            while (bits < end_bits) {
                if (bits[0] != 0) {
                    return true;
                }
                bits += 3;
            }
            bits = end_bits;
            end_bits += bytes_per_line;
        }
        break;

    case QImage::Format_ARGB6666_Premultiplied:
        for (int y=0; y<height; ++y) {
            while (bits < end_bits) {
                if ((bits[0] & 0xfc) != 0) {
                    return true;
                }
                bits += 3;
            }
            bits = end_bits;
            end_bits += bytes_per_line;
        }
        break;

    case QImage::Format_ARGB4444_Premultiplied:
        for (int y=0; y<height; ++y) {
            while (bits < end_bits) {
                if ((bits[0] & 0xf0) != 0) {
                    return true;
                }
                bits += 2;
            }
            bits = end_bits;
            end_bits += bytes_per_line;
        }
        break;

    default:
        break;
    }

    return false;
}
Exemple #17
0
bool QWebpHandler::write(const QImage &image)
{
    if (image.isNull()) {
        qWarning() << "source image is null.";
        return false;
    }

    QImage srcImage = image;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
    if (srcImage.format() != QImage::Format_ARGB32)
        srcImage = srcImage.convertToFormat(QImage::Format_ARGB32);
#else /* Q_BIG_ENDIAN */
    if (srcImage.format() != QImage::Format_RGBA8888)
        srcImage = srcImage.convertToFormat(QImage::Format_RGBA8888);
#endif

    WebPPicture picture;
    WebPConfig config;

    if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) {
        qWarning() << "failed to init webp picture and config";
        return false;
    }

    picture.width = srcImage.width();
    picture.height = srcImage.height();
    picture.use_argb = 1;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
    if (!WebPPictureImportBGRA(&picture, srcImage.bits(), srcImage.bytesPerLine())) {
#else /* Q_BIG_ENDIAN */
    if (!WebPPictureImportRGBA(&picture, srcImage.bits(), srcImage.bytesPerLine())) {
#endif
        qWarning() << "failed to import image data to webp picture.";

        WebPPictureFree(&picture);
        return false;
    }

    config.lossless = m_lossless;
    config.quality = m_quality;
    picture.writer = pictureWriter;
    picture.custom_ptr = device();

    if (!WebPEncode(&config, &picture)) {
        qWarning() << "failed to encode webp picture, error code: " << picture.error_code;
        WebPPictureFree(&picture);
        return false;
    }

    WebPPictureFree(&picture);

    return true;
}

QVariant QWebpHandler::option(ImageOption option) const
{
    if (!supportsOption(option) || !ensureScanned())
        return QVariant();

    switch (option) {
    case Quality:
        return m_quality;
    case Size:
        return QSize(m_width, m_height);
    case Animation:
        return (m_flags & ANIMATION_FLAG) == ANIMATION_FLAG;
    default:
        return QVariant();
    }
}

void QWebpHandler::setOption(ImageOption option, const QVariant &value)
{
    switch (option) {
    case Quality:
        m_quality = qBound(0, value.toInt(), 100);
        m_lossless = (m_quality >= 100);
        return;
    default:
        break;
    }
    return QImageIOHandler::setOption(option, value);
}

bool QWebpHandler::supportsOption(ImageOption option) const
{
    return option == Quality
        || option == Size
        || option == Animation;
}

QByteArray QWebpHandler::name() const
{
    return QByteArrayLiteral("webp");
}

int QWebpHandler::imageCount() const
{
    if (!ensureScanned())
        return 0;

    if ((m_flags & ANIMATION_FLAG) == 0)
        return 1;

    return m_frameCount;
}

int QWebpHandler::currentImageNumber() const
{
    if (!ensureScanned())
        return 0;

    return m_iter.frame_num;
}

QRect QWebpHandler::currentImageRect() const
{
    if (!ensureScanned())
        return QRect();

    return QRect(m_iter.x_offset, m_iter.y_offset, m_iter.width, m_iter.height);
}

bool QWebpHandler::jumpToImage(int imageNumber)
{
    if (!ensureScanned())
        return false;

    WebPDemuxReleaseIterator(&m_iter);
    return WebPDemuxGetFrame(m_demuxer, imageNumber, &m_iter);
}

bool QWebpHandler::jumpToNextImage()
{
    if (!ensureScanned())
        return false;

    return WebPDemuxNextFrame(&m_iter);
}

int QWebpHandler::loopCount() const
{
    if (!ensureScanned() || (m_flags & ANIMATION_FLAG) == 0)
        return 0;

    return m_loop;
}

int QWebpHandler::nextImageDelay() const
{
    if (!ensureScanned())
        return 0;

    return m_iter.duration;
}
Exemple #18
0
VideoFrame::VideoFrame(const QImage& image)
    : Frame(new VideoFramePrivate(image.width(), image.height(), VideoFormat(image.format())))
{
    setBits((uchar*)image.constBits(), 0);
    setBytesPerLine(image.bytesPerLine(), 0);
}
/* Convert QImage to cv::Mat without data copy
 */
cv::Mat image2Mat_shared(const QImage &img, MatColorOrder *order)
{
    if (img.isNull())
        return cv::Mat();

    switch (img.format()) {
    case QImage::Format_Indexed8:
        break;
#if QT_VERSION >= 0x040400
    case QImage::Format_RGB888:
        if (order)
            *order = MCO_RGB;
        break;
#endif
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32:
    case QImage::Format_ARGB32_Premultiplied:
        if (order)
            *order = getColorOrderOfRGB32Format();
        break;
#if QT_VERSION >= 0x050200
    case QImage::Format_RGBX8888:
    case QImage::Format_RGBA8888:
    case QImage::Format_RGBA8888_Premultiplied:
        if (order)
            *order = MCO_RGBA;
        break;
#endif
#if QT_VERSION >= 0x050500
    case QImage::Format_Alpha8:
    case QImage::Format_Grayscale8:
        break;
#endif
    default:
        return cv::Mat();
    }
    return cv::Mat(img.height(), img.width(), CV_8UC(img.depth()/8), (uchar*)img.bits(), img.bytesPerLine());
}
void QAnimationWriter::appendFrame(const QImage& frm, const QPoint& offset)
{
    if (!dev)
        return;

    const QImage frame = frm.convertToFormat(QImage::Format_RGB32);
    const int alignx = 1;
    if (prev.isNull() || !d->canCompose()) {
        d->setImage(frame);
    } else {
        bool done;
        int minx, maxx, miny, maxy;
        int w = frame.width();
        int h = frame.height();

        const quint32 *framePtr = reinterpret_cast<const quint32*>(frame.bits());
        const quint32 *prevPtr = reinterpret_cast<const quint32*>(prev.bits());
        const int frameStride = frame.bytesPerLine() / sizeof(quint32);
        const int prevStride = prev.bytesPerLine() / sizeof(quint32);

        // Find left edge of change
        done = false;
        for (minx = 0; minx < w && !done; ++minx) {
            const quint32 *p1 = framePtr + minx;
            const quint32 *p2 = prevPtr + minx + offset.x();
            for (int y = 0; y < h; ++y) {
                if (*p1 != *p2) {
                    done = true;
                    break;
                }
                p1 += frameStride;
                p2 += prevStride;
            }
        }
        --minx;

        // Find right edge of change
        done = false;
        for (maxx = w-1; maxx >= 0 && !done; --maxx) {
            const quint32 *p1 = framePtr + maxx;
            const quint32 *p2 = prevPtr + maxx + offset.x();
            for (int y = 0; y < h; ++y) {
                if (*p1 != *p2) {
                    done = true;
                    break;
                }
                p1 += frameStride;
                p2 += prevStride;
            }
        }
        ++maxx;

        // Find top edge of change
        done = false;
        for (miny = 0; miny < h && !done; ++miny) {
            const quint32 *p1 = framePtr + miny * frameStride;
            const quint32 *p2 = prevPtr + miny * prevStride + offset.x();
            for (int x = 0; x < w; ++x) {
                if (*p1 != *p2) {
                    done = true;
                    break;
                }
                ++p1;
                ++p2;
            }
        }
        --miny;

        // Find right edge of change
        done = false;
        for (maxy = h-1; maxy >= 0 && !done; --maxy) {
            const quint32 *p1 = framePtr + maxy * frameStride;
            const quint32 *p2 = prevPtr + maxy * prevStride + offset.x();
            for (int x = 0; x < w; ++x) {
                if (*p1 != *p2) {
                    done = true;
                    break;
                }
                ++p1;
                ++p2;
            }
        }
        ++maxy;

        if (minx > maxx)
            minx = maxx = 0;
        if (miny > maxy)
            miny = maxy = 0;

        if (alignx > 1) {
            minx -= minx % alignx;
            maxx = maxx - maxx % alignx + alignx - 1;
        }

        int dw = maxx - minx + 1;
        int dh = maxy - miny + 1;

        QImage diff(dw, dh, QImage::Format_ARGB32);

        int x, y;
        for (y = 0; y < dh; ++y) {
            QRgb* li = (QRgb*)frame.scanLine(y+miny)+minx;
            QRgb* lp = (QRgb*)prev.scanLine(y+miny+offset.y())+minx+offset.x();
            QRgb* ld = (QRgb*)diff.scanLine(y);
            if (alignx) {
                for (x = 0; x < dw; x += alignx) {
                    int i;
                    for (i = 0; i < alignx; ++i) {
                        if (li[x+i] != lp[x+i])
                            break;
                    }
                    if (i == alignx) {
                        // All the same
                        for (i = 0; i < alignx; ++i)
                            ld[x+i] = qRgba(0,0,0,0);
                    } else {
                        // Some different
                        for (i = 0; i < alignx; ++i)
                            ld[x+i] = 0xff000000 | li[x+i];
                    }
                }
            } else {
                for (x = 0; x < dw; ++x) {
                    if (li[x] != lp[x])
                        ld[x] = 0xff000000 | li[x];
                    else
                        ld[x] = qRgba(0,0,0,0);
                }
            }
        }

        d->composeImage(diff, QPoint(minx, miny) + offset);
    }
    if (prev.isNull() || prev.size() == frame.size() && offset == QPoint(0,0)) {
        prev = frame;
    } else {
        QPainter p(&prev);
        p.drawImage(offset.x(), offset.y(), frame, 0, 0,
                    frame.width(), frame.height());
    }
}
Exemple #21
0
    void flushImage(const QPoint &pos, const QImage &image, const QRect &destinationRect)
    {
        checkPauseApplication();
        QMutexLocker locker(&m_surfaceMutex);
        if (!m_surface)
            return;
        AttachedJNIEnv env;
        if (!env.jniEnv)
            return;

        int bpp = 2;
        AndroidBitmapInfo info;
        int ret;

        if ((ret = AndroidBitmap_getInfo(env.jniEnv, m_surface, &info)) < 0) {
            qWarning() << "AndroidBitmap_getInfo() failed ! error=" << ret;
            m_javaVM->DetachCurrentThread();
            return;
        }

        if (info.format != ANDROID_BITMAP_FORMAT_RGB_565) {
            qWarning() << "Bitmap format is not RGB_565!";
            m_javaVM->DetachCurrentThread();
            return;
        }

        void *pixels;
        unsigned char *screenBits;
        if ((ret = AndroidBitmap_lockPixels(env.jniEnv, m_surface, &pixels)) < 0) {
            qWarning() << "AndroidBitmap_lockPixels() failed! error=" << ret;
            m_javaVM->DetachCurrentThread();
            return;
        }

        screenBits = static_cast<unsigned char *>(pixels);
        int sbpl = info.stride;
        int swidth = info.width;
        int sheight = info.height;

        unsigned sposx = pos.x() + destinationRect.x();
        unsigned sposy = pos.y() + destinationRect.y();

        screenBits += sposy * sbpl;

        unsigned ibpl = image.bytesPerLine();
        unsigned iposx = destinationRect.x();
        unsigned iposy = destinationRect.y();

        const unsigned char *imageBits = static_cast<const unsigned char *>(image.bits());
        imageBits += iposy * ibpl;

        unsigned width = swidth - sposx < unsigned(destinationRect.width())
                         ? (swidth-sposx)
                         : destinationRect.width();
        unsigned height = sheight - sposy < unsigned(destinationRect.height())
                          ? (sheight - sposy)
                          : destinationRect.height();

        for (unsigned y = 0; y < height; y++) {
            memcpy(screenBits + y*sbpl + sposx*bpp,
                   imageBits + y*ibpl + iposx*bpp,
                   width*bpp);
        }
        AndroidBitmap_unlockPixels(env.jniEnv, m_surface);

        env.jniEnv->CallStaticVoidMethod(m_applicationClass,
                                         m_redrawSurfaceMethodID,
                                         jint(destinationRect.left()),
                                         jint(destinationRect.top()),
                                         jint(destinationRect.right() + 1),
                                         jint(destinationRect.bottom() + 1));
#warning FIXME dirty hack, figure out why it needs to add 1 to right and bottom !!!!
    }
Exemple #22
0
// See https://code.woboq.org/qt5/qtbase/src/gui/image/qimage.cpp.html#_ZNK6QImage5pixelEii
inline QRgb getPixel(const QImage& image, int x, int y)
{
    uchar* line = const_cast<uchar*>(image.constBits()) + y * image.bytesPerLine();

    return reinterpret_cast<QRgb*>(line)[x];
}
Exemple #23
0
void QPF::addGlyphs(QFontEngine *fe, const QList<CharacterRange> &ranges)
{
    const quint16 glyphCount = fe->glyphCount();

    QByteArray gmap;
    gmap.resize(glyphCount * sizeof(quint32));
    gmap.fill(char(0xff));
    //qDebug() << "glyphCount" << glyphCount;

    QByteArray glyphs;
    if (options & RenderGlyphs) {
        // this is only a rough estimation
        glyphs.reserve(glyphCount 
                * (sizeof(QFontEngineQPF::Glyph) 
                    + qRound(fe->maxCharWidth() * (fe->ascent() + fe->descent()).toReal())));

        QGlyphLayout layout[10];

        foreach (CharacterRange range, ranges) {
            if (debugVerbosity > 2)
                qDebug() << "rendering range from" << range.start << "to" << range.end;
            for (uint uc = range.start; uc < range.end; ++uc) {
                QChar ch(uc);
                int nglyphs = 10;
                if (!fe->stringToCMap(&ch, 1, &layout[0], &nglyphs, /*flags*/ 0))
                    continue;

                if (nglyphs != 1)
                    continue;

                const quint32 glyphIndex = layout[0].glyph;

                if (!glyphIndex)
                    continue;

                Q_ASSERT(glyphIndex < glyphCount);

                QImage img = fe->alphaMapForGlyph(glyphIndex).convertToFormat(QImage::Format_Indexed8);
                glyph_metrics_t metrics = fe->boundingBox(glyphIndex);

                const quint32 oldSize = glyphs.size();
                glyphs.resize(glyphs.size() + sizeof(QFontEngineQPF::Glyph) + img.numBytes());
                uchar *data = reinterpret_cast<uchar *>(glyphs.data() + oldSize);

                uchar *gmapPtr = reinterpret_cast<uchar *>(gmap.data() + glyphIndex * sizeof(quint32));
                qToBigEndian(oldSize, gmapPtr);

                QFontEngineQPF::Glyph *glyph = reinterpret_cast<QFontEngineQPF::Glyph *>(data);
                glyph->width = img.width();
                glyph->height = img.height();
                glyph->bytesPerLine = img.bytesPerLine();
                glyph->x = qRound(metrics.x);
                glyph->y = qRound(metrics.y);
                glyph->advance = qRound(metrics.xoff);
                data += sizeof(QFontEngineQPF::Glyph);

                if (debugVerbosity && uc >= 'A' && uc <= 'z' || debugVerbosity > 1) {
                    qDebug() << "adding glyph with index" << glyphIndex << " uc =" << char(uc) << ":\n"
                        << "    glyph->x =" << glyph->x << "rounded from" << metrics.x << "\n"
                        << "    glyph->y =" << glyph->y << "rounded from" << metrics.y << "\n"
                        << "    width =" << glyph->width << "height =" << glyph->height
                        << "    advance =" << glyph->advance << "rounded from" << metrics.xoff
                        ;
                }

                qMemCopy(data, img.bits(), img.numBytes());
            }
        }
    }
Exemple #24
0
 cv::Mat qimg2img(const QImage &qimg)
 {
     cv::Mat img;
     img = cv::Mat(qimg.height(), qimg.width(), CV_8UC4, const_cast<uchar*>(qimg.bits()), qimg.bytesPerLine());
     return img;
 }
Exemple #25
0
Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image)
{
    QGLShareContextScope ctx(qt_gl_share_widget()->context());

    QMeeGoExtensions::ensureInitialized();

    GLuint textureId;

    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    if (image.hasAlphaChannel() && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()) {
        void *converted = convertBGRA32_to_RGBA32(image.bits(), image.width(), image.height(), image.bytesPerLine());
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, converted);
        free(converted);
    } else {
        void *converted = convertRGB32_to_RGB565(image.bits(), image.width(), image.height(), image.bytesPerLine());
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, converted);
        free(converted);
    }

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    EGLImageKHR eglimage = QEgl::eglCreateImageKHR(QEgl::display(), QEglContext::currentContext(QEgl::OpenGL)->context(),
                                                                                                EGL_GL_TEXTURE_2D_KHR,
                                                                                                (EGLClientBuffer) textureId,
                                                                                                preserved_image_attribs);
    glDeleteTextures(1, &textureId);
    if (eglimage) {
        EGLNativeSharedImageTypeNOK handle = QMeeGoExtensions::eglCreateSharedImageNOK(QEgl::display(), eglimage, NULL);
        QEgl::eglDestroyImageKHR(QEgl::display(), eglimage);
        return (Qt::HANDLE) handle;
    } else {
        qWarning("Failed to create shared image from pixmap/texture!");
        return 0;
    }
}
Exemple #26
0
QVector<QRectF> SubtitleDrawer::draw(QImage &image, int &gap, const RichTextDocument &text, const QRectF &area, double dpr) {
	QVector<QRectF> bboxes;
	gap = 0;
	if (!(m_drawn = text.hasWords()))
		return bboxes;
	const double scale = this->scale(area)*dpr;
	const double fscale = m_style.font.height()*scale;
	auto make = [this, text, scale, area, dpr] (RichTextDocument &doc, const RichTextDocument &from) {
		doc = from; doc += text; doc.updateLayoutInfo(); doc.doLayout(area.width()/(scale/dpr));
	};
	RichTextDocument front, back; make(front, m_front); make(back, m_back);
	QPoint thick = m_style.bbox.enabled ? (fscale*m_style.bbox.padding).toPoint() : QPoint(0, 0);
	QPoint soffset = m_style.shadow.enabled ? (fscale*m_style.shadow.offset).toPoint() : QPoint(0, 0);
	QPoint offset(0, 0);
	const int blur = m_style.shadow.blur ? qRound(fscale*0.01) : 0;
	const auto nsize = front.naturalSize()*scale;
	QSize imageSize(nsize.width() + 1, nsize.height() + 1);
	QPoint pad = soffset;
	if (soffset.x() < 0) {
		pad.rx() = offset.rx() = -soffset.x();
		soffset.rx() = 0;
	}
	if (soffset.y() < 0) {
		pad.ry() = offset.ry() = -soffset.y();
		soffset.ry() = 0;
	}
	imageSize += {pad.rx() + (blur+thick.x())*2, pad.ry() + (blur+thick.y())*2};
	const QPoint pblur(blur, blur);
	offset += pblur;
	offset += thick;
	image = QImage(imageSize, QImage::Format_ARGB32_Premultiplied);
	if (!image.isNull()) {
		QPointF origin(-(area.width()*dpr - nsize.width())*0.5 + offset.x(), offset.y());
		image.setDevicePixelRatio(dpr);
		image.fill(0x0);
		QPainter painter(&image);
		painter.translate(origin/dpr);
		painter.scale(scale/dpr, scale/dpr);
		back.draw(&painter, QPointF(0, 0));
		front.draw(&painter, QPointF(0, 0));
		painter.end();
		if (m_style.shadow.enabled) {
			QImage bg(image.size(), QImage::Format_ARGB32_Premultiplied);
			bg.setDevicePixelRatio(dpr);
			auto dest = bg.bits();
			const quint32 sr = m_style.shadow.color.red();
			const quint32 sg = m_style.shadow.color.green();
			const quint32 sb = m_style.shadow.color.blue();
			const quint32 sa = m_style.shadow.color.alpha();
			for (int y=0; y<bg.height(); ++y) {
				const int ys = y - soffset.y();
				if (ys < 0) {
					memset(dest, 0, bg.bytesPerLine());
					dest += bg.bytesPerLine();
				} else {
					auto src = image.bits() + image.bytesPerLine()*ys;
					for (int x=0; x<bg.width(); ++x) {
						const int xs = x-soffset.x();
						if (xs < 0) {
							*dest++ = 0;
							*dest++ = 0;
							*dest++ = 0;
							*dest++ = 0;
						} else {
							*dest++ = sr*sa*src[3] >> 16;
							*dest++ = sg*sa*src[3] >> 16;
							*dest++ = sb*sa*src[3] >> 16;
							*dest++ = sa*   src[3] >> 8;
							src += 4;
						}
					}
				}
			}
			if (blur)
				m_blur.applyTo(bg, Qt::black, blur);
			painter.begin(&bg);
			painter.drawImage(QPoint(0, 0), image);
			painter.end();
			image.swap(bg);
		}
/* convert QImage to cv Mat, return the converted image */
cv::Mat ScribbleArea::QImage2CvMat(const QImage &inImage, bool inCloneImageData) {
	switch (inImage.format()) {
		// 8-bit, 4 channel
		case QImage::Format_RGB32: {
			cv::Mat mat(inImage.height(), inImage.width(), CV_8UC4, const_cast<uchar*>(inImage.bits()), inImage.bytesPerLine());
			return (inCloneImageData ? mat.clone() : mat);
		}

		// 8-bit, 3 channel
		case QImage::Format_RGB888: {
			if (!inCloneImageData)
				qWarning() << "ASM::QImageToCvMat() - Conversion requires cloning since we use a temporary QImage";

			QImage swapped = inImage.rgbSwapped();
			return cv::Mat(swapped.height(), swapped.width(), CV_8UC3, const_cast<uchar*>(swapped.bits()), swapped.bytesPerLine()).clone();
		}

		// 8-bit, 1 channel
		case QImage::Format_Indexed8: {
			cv::Mat mat(inImage.height(), inImage.width(), CV_8UC1, const_cast<uchar*>(inImage.bits()), inImage.bytesPerLine());
			return (inCloneImageData ? mat.clone() : mat);
		}

		default:
			qWarning() << "ASM::QImageToCvMat() - QImage format not handled in switch:" << inImage.format();
			break;
	}
	return cv::Mat();
}
QImage VectorscopeGenerator::calculateVectorscope(const QSize &vectorscopeSize, const QImage &image, const float &gain,
                                                  const VectorscopeGenerator::PaintMode &paintMode,
                                                  const VectorscopeGenerator::ColorSpace &colorSpace,
                                                  bool, uint accelFactor) const
{
    if (vectorscopeSize.width() <= 0 || vectorscopeSize.height() <= 0 || image.width() <= 0 || image.height() <= 0) {
        // Invalid size
        return QImage();
    }

    // Prepare the vectorscope data
    const int cw = (vectorscopeSize.width() < vectorscopeSize.height()) ? vectorscopeSize.width() : vectorscopeSize.height();
    QImage scope = QImage(cw, cw, QImage::Format_ARGB32);
    scope.fill(qRgba(0,0,0,0));

    const uchar *bits = image.bits();

    double dy, dr, dg, db, dmax;
    double /*y,*/ u, v;
    QPoint pt;
    QRgb px;

    const int stepsize = image.depth() / 8 * accelFactor;

    // Just an average for the number of image pixels per scope pixel.
    // NOTE: byteCount() has to be replaced by (img.bytesPerLine()*img.height()) for Qt 4.5 to compile, see: http://doc.trolltech.org/4.6/qimage.html#bytesPerLine
    double avgPxPerPx = (double) image.depth() / 8 *(image.bytesPerLine()*image.height())/scope.size().width()/scope.size().height()/accelFactor;

    for (int i = 0; i < (image.bytesPerLine()*image.height()); i+= stepsize) {
        QRgb *col = (QRgb *) bits;

        int r = qRed(*col);
        int g = qGreen(*col);
        int b = qBlue(*col);

        switch (colorSpace) {
        case VectorscopeGenerator::ColorSpace_YUV:
//             y = (double)  0.001173 * r +0.002302 * g +0.0004471* b;
            u = (double) -0.0005781* r -0.001135 * g +0.001713 * b;
            v = (double)  0.002411 * r -0.002019 * g -0.0003921* b;
            break;
        case VectorscopeGenerator::ColorSpace_YPbPr:
        default:
//             y = (double)  0.001173 * r +0.002302 * g +0.0004471* b;
            u = (double) -0.0006671* r -0.001299 * g +0.0019608* b;
            v = (double)  0.001961 * r -0.001642 * g -0.0003189* b;
            break;
        }


        pt = mapToCircle(vectorscopeSize, QPointF(SCALING*gain*u, SCALING*gain*v));

        if (pt.x() >= scope.width() || pt.x() < 0
            || pt.y() >= scope.height() || pt.y() < 0) {
            // Point lies outside (because of scaling), don't plot it

        } else {

            // Draw the pixel using the chosen draw mode.
            switch (paintMode) {
            case PaintMode_YUV:
                // see yuvColorWheel
                dy = 128; // Default Y value. Lower = darker.

                // Calculate the RGB values from YUV/YPbPr
                switch (colorSpace) {
                case VectorscopeGenerator::ColorSpace_YUV:
                    dr = dy + 290.8*v;
                    dg = dy - 100.6*u - 148*v;
                    db = dy + 517.2*u;
                    break;
                case VectorscopeGenerator::ColorSpace_YPbPr:
                default:
                    dr = dy + 357.5*v;
                    dg = dy - 87.75*u - 182*v;
                    db = dy + 451.9*u;
                    break;
                }


                if (dr < 0) dr = 0;
                if (dg < 0) dg = 0;
                if (db < 0) db = 0;
                if (dr > 255) dr = 255;
                if (dg > 255) dg = 255;
                if (db > 255) db = 255;

                scope.setPixel(pt, qRgba(dr, dg, db, 255));
                break;

            case PaintMode_Chroma:
                dy = 200; // Default Y value. Lower = darker.

                // Calculate the RGB values from YUV/YPbPr
                switch (colorSpace) {
                case VectorscopeGenerator::ColorSpace_YUV:
                    dr = dy + 290.8*v;
                    dg = dy - 100.6*u - 148*v;
                    db = dy + 517.2*u;
                    break;
                case VectorscopeGenerator::ColorSpace_YPbPr:
                default:
                    dr = dy + 357.5*v;
                    dg = dy - 87.75*u - 182*v;
                    db = dy + 451.9*u;
                    break;
                }

                // Scale the RGB values back to max 255
                dmax = dr;
                if (dg > dmax) dmax = dg;
                if (db > dmax) dmax = db;
                dmax = 255/dmax;

                dr *= dmax;
                dg *= dmax;
                db *= dmax;

                scope.setPixel(pt, qRgba(dr, dg, db, 255));
                break;
            case PaintMode_Original:
                scope.setPixel(pt, *col);
                break;
            case PaintMode_Green:
                px = scope.pixel(pt);
                scope.setPixel(pt, qRgba(qRed(px)+(255-qRed(px))/(3*avgPxPerPx), qGreen(px)+20*(255-qGreen(px))/(avgPxPerPx),
                                         qBlue(px)+(255-qBlue(px))/(avgPxPerPx), qAlpha(px)+(255-qAlpha(px))/(avgPxPerPx)));
                break;
            case PaintMode_Green2:
                px = scope.pixel(pt);
                scope.setPixel(pt, qRgba(qRed(px)+ceil((255-(float)qRed(px))/(4*avgPxPerPx)), 255,
                                         qBlue(px)+ceil((255-(float)qBlue(px))/(avgPxPerPx)), qAlpha(px)+ceil((255-(float)qAlpha(px))/(avgPxPerPx))));
                break;
            case PaintMode_Black:
                px = scope.pixel(pt);
                scope.setPixel(pt, qRgba(0,0,0, qAlpha(px)+(255-qAlpha(px))/20));
                break;
            }
        }

        bits += stepsize;
    }
    return scope;
}
Exemple #29
0
void QMacPixmapData::fromImage(const QImage &img,
                               Qt::ImageConversionFlags flags)
{
    setSerialNumber(++qt_pixmap_serial);

    // the conversion code only handles format >=
    // Format_ARGB32_Premultiplied at the moment..
    if (img.format() > QImage::Format_ARGB32_Premultiplied) {
        QImage image;
        if (img.hasAlphaChannel())
            image = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
        else
            image = img.convertToFormat(QImage::Format_RGB32);
        fromImage(image, flags);
        return;
    }

    w = img.width();
    h = img.height();
    is_null = (w <= 0 || h <= 0);
    d = (pixelType() == BitmapType ? 1 : img.depth());

    QImage image = img;
    int dd = QPixmap::defaultDepth();
    bool force_mono = (dd == 1 ||
                       (flags & Qt::ColorMode_Mask)==Qt::MonoOnly);
    if (force_mono) {                         // must be monochrome
        if (d != 1) {
            image = image.convertToFormat(QImage::Format_MonoLSB, flags);  // dither
            d = 1;
        }
    } else {                                    // can be both
        bool conv8 = false;
        if(d > 8 && dd <= 8) {               // convert to 8 bit
            if ((flags & Qt::DitherMode_Mask) == Qt::AutoDither)
                flags = (flags & ~Qt::DitherMode_Mask)
                                   | Qt::PreferDither;
            conv8 = true;
        } else if ((flags & Qt::ColorMode_Mask) == Qt::ColorOnly) {
            conv8 = d == 1;                     // native depth wanted
        } else if (d == 1) {
            if (image.colorCount() == 2) {
                QRgb c0 = image.color(0);       // Auto: convert to best
                QRgb c1 = image.color(1);
                conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255);
            } else {
                // eg. 1-color monochrome images (they do exist).
                conv8 = true;
            }
        }
        if (conv8) {
            image = image.convertToFormat(QImage::Format_Indexed8, flags);
            d = 8;
        }
    }

    if (image.depth()==1) {
        image.setColor(0, QColor(Qt::color0).rgba());
        image.setColor(1, QColor(Qt::color1).rgba());
    }

    if (d == 16 || d == 24) {
        image = image.convertToFormat(QImage::Format_RGB32, flags);
        fromImage(image, flags);
        return;
    }

    // different size or depth, make a new pixmap
    resize(w, h);

    quint32 *dptr = pixels, *drow;
    const uint dbpr = bytesPerRow;

    const QImage::Format sfmt = image.format();
    const unsigned short sbpr = image.bytesPerLine();

    // use const_cast to prevent a detach
    const uchar *sptr = const_cast<const QImage &>(image).bits(), *srow;

    for (int y = 0; y < h; ++y) {
        drow = dptr + (y * (dbpr / 4));
        srow = sptr + (y * sbpr);
        switch(sfmt) {
        case QImage::Format_MonoLSB:
        case QImage::Format_Mono:{
            for (int x = 0; x < w; ++x) {
                char one_bit = *(srow + (x / 8));
                if (sfmt == QImage::Format_Mono)
                    one_bit = one_bit >> (7 - (x % 8));
                else
                    one_bit = one_bit >> (x % 8);
                if ((one_bit & 0x01))
                    *(drow+x) = 0xFF000000;
                else
                    *(drow+x) = 0xFFFFFFFF;
            }
            break;
        }
        case QImage::Format_Indexed8: {
            int numColors = image.numColors();
            if (numColors > 0) {
                for (int x = 0; x < w; ++x) {
                    int index = *(srow + x);
                    *(drow+x) = PREMUL(image.color(qMin(index, numColors)));
                }
            }
        } break;
        case QImage::Format_RGB32:
            for (int x = 0; x < w; ++x)
                *(drow+x) = *(((quint32*)srow) + x) | 0xFF000000;
            break;
        case QImage::Format_ARGB32:
        case QImage::Format_ARGB32_Premultiplied:
            for (int x = 0; x < w; ++x) {
                if(sfmt == QImage::Format_RGB32)
                    *(drow+x) = 0xFF000000 | (*(((quint32*)srow) + x) & 0x00FFFFFF);
                else if(sfmt == QImage::Format_ARGB32_Premultiplied)
                    *(drow+x) = *(((quint32*)srow) + x);
                else
                    *(drow+x) = PREMUL(*(((quint32*)srow) + x));
            }
            break;
        default:
            qWarning("Qt: internal: Oops: Forgot a format [%d] %s:%d", sfmt,
                     __FILE__, __LINE__);
            break;
        }
    }
Exemple #30
0
bool loadPGFScaled(QImage& img, const QString& path, int maximumSize)
{
    FILE* const file = fopen(QFile::encodeName(path), "rb");

    if (!file)
    {
        kDebug() << "Error: Could not open source file.";
        return false;
    }

    unsigned char header[3];

    if (fread(&header, 3, 1, file) != 1)
    {
        fclose(file);
        return false;
    }

    unsigned char pgfID[3] = { 0x50, 0x47, 0x46 };

    if (memcmp(&header[0], &pgfID, 3) != 0)
    {
        // not a PGF file
        fclose(file);
        return false;
    }

    fclose(file);

    // -------------------------------------------------------------------
    // Initialize PGF API.

#ifdef WIN32
#ifdef UNICODE
    HANDLE fd = CreateFile((LPCWSTR)(QFile::encodeName(path).constData()), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
#else
    HANDLE fd = CreateFile(QFile::encodeName(path), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
#endif

    if (fd == INVALID_HANDLE_VALUE)
    {
        return false;
    }

#else
    int fd = open(QFile::encodeName(path), O_RDONLY);

    if (fd == -1)
    {
        return false;
    }

#endif

    try
    {
        CPGFFileStream stream(fd);
        CPGFImage      pgf;
        pgf.Open(&stream);

        // Try to find the right PGF level to get reduced image accordingly
        // with preview size wanted.
        int i = 0;

        if (pgf.Levels() > 0)
        {
            for (i=pgf.Levels()-1 ; i>=0 ; --i)
            {
                if (qMin((int)pgf.Width(i), (int)pgf.Height(i)) >= maximumSize)
                {
                    break;
                }
            }
        }

        if (i < 0)
        {
            i = 0;
        }

        pgf.Read(i);  // Read PGF image at reduced level i.
        img = QImage(pgf.Width(i), pgf.Height(i), QImage::Format_RGB32);

/*
        const PGFHeader* header = pgf.GetHeader();
        kDebug() << "PGF width    = " << header->width;
        kDebug() << "PGF height   = " << header->height;
        kDebug() << "PGF bbp      = " << header->bpp;
        kDebug() << "PGF channels = " << header->channels;
        kDebug() << "PGF quality  = " << header->quality;
        kDebug() << "PGF mode     = " << header->mode;
        kDebug() << "PGF levels   = " << header->nLevels;
        kDebug() << "Level (w x h)= " << i << "(" << pgf.Width(i)
                                      << " x " << pgf.Height(i) << ")";
        kDebug() << "QImage depth = " << img.depth();
*/

        if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
        {
            int map[] = {3, 2, 1, 0};
            pgf.GetBitmap(img.bytesPerLine(), (UINT8*)img.bits(), img.depth(), map);
        }
        else
        {
            int map[] = {0, 1, 2, 3};
            pgf.GetBitmap(img.bytesPerLine(), (UINT8*)img.bits(), img.depth(), map);
        }
    }
    catch (IOException& e)
    {
        int err = e.error;

        if (err >= AppError)
        {
            err -= AppError;
        }

        kDebug() << "Error running libpgf (" << err << ")!";
        return false;
    }

    return true;
}