Ejemplo n.º 1
0
void 
gfxPlatform::TransformPixel(const gfxRGBA& in, gfxRGBA& out, qcms_transform *transform)
{

    if (transform) {
        /* we want the bytes in RGB order */
#ifdef IS_LITTLE_ENDIAN
        /* ABGR puts the bytes in |RGBA| order on little endian */
        PRUint32 packed = in.Packed(gfxRGBA::PACKED_ABGR);
        qcms_transform_data(transform,
                       (PRUint8 *)&packed, (PRUint8 *)&packed,
                       1);
        out.~gfxRGBA();
        new (&out) gfxRGBA(packed, gfxRGBA::PACKED_ABGR);
#else
        /* ARGB puts the bytes in |ARGB| order on big endian */
        PRUint32 packed = in.Packed(gfxRGBA::PACKED_ARGB);
        /* add one to move past the alpha byte */
        qcms_transform_data(transform,
                       (PRUint8 *)&packed + 1, (PRUint8 *)&packed + 1,
                       1);
        out.~gfxRGBA();
        new (&out) gfxRGBA(packed, gfxRGBA::PACKED_ARGB);
#endif
    }

    else if (&out != &in)
        out = in;
}
Ejemplo n.º 2
0
template <J_COLOR_SPACE colorSpace> bool outputRows(JPEGImageReader* reader, ImageFrame& buffer)
{
    JSAMPARRAY samples = reader->samples();
    jpeg_decompress_struct* info = reader->info();
    int width = info->output_width;

    while (info->output_scanline < info->output_height) {
        // jpeg_read_scanlines will increase the scanline counter, so we
        // save the scanline before calling it.
        int y = info->output_scanline;
        // Request one scanline: returns 0 or 1 scanlines.
        if (jpeg_read_scanlines(info, samples, 1) != 1)
            return false;
#if USE(QCMSLIB)
        if (reader->colorTransform() && colorSpace == JCS_RGB)
            qcms_transform_data(reader->colorTransform(), *samples, *samples, width);
#endif
        ImageFrame::PixelData* pixel = buffer.getAddr(0, y);
        for (int x = 0; x < width; ++pixel, ++x)
            setPixel<colorSpace>(buffer, pixel, samples, x);
    }

    buffer.setPixelsChanged(true);
    return true;
}
Ejemplo n.º 3
0
bool JPEGImageDecoder::outputScanlines(ImageFrame& buffer)
{
    JSAMPARRAY samples = m_reader->samples();
    jpeg_decompress_struct* info = m_reader->info();
    int width = isScaled ? m_scaledColumns.size() : info->output_width;

    while (info->output_scanline < info->output_height) {
        // jpeg_read_scanlines will increase the scanline counter, so we
        // save the scanline before calling it.
        int sourceY = info->output_scanline;
        /* Request one scanline.  Returns 0 or 1 scanlines. */
        if (jpeg_read_scanlines(info, samples, 1) != 1)
            return false;

        int destY = scaledY(sourceY);
        if (destY < 0)
            continue;

#if USE(QCMSLIB)
        if (m_reader->colorTransform() && colorSpace == JCS_RGB)
            qcms_transform_data(m_reader->colorTransform(), *samples, *samples, info->output_width);
#endif

        ImageFrame::PixelData* currentAddress = buffer.getAddr(0, destY);
        for (int x = 0; x < width; ++x) {
            setPixel<colorSpace>(buffer, currentAddress, samples, isScaled ? m_scaledColumns[x] : x);
            ++currentAddress;
        }
    }
    return true;
}
Ejemplo n.º 4
0
// -----------------------------------------------------------------------------
// Color profile handling
static int ApplyColorProfile(const WebPData* const profile,
                             WebPDecBuffer* const rgba) {
#ifdef WEBP_HAVE_QCMS
  int i, ok = 0;
  uint8_t* line;
  uint8_t major_revision;
  qcms_profile* input_profile = NULL;
  qcms_profile* output_profile = NULL;
  qcms_transform* transform = NULL;
  const qcms_data_type input_type = QCMS_DATA_RGBA_8;
  const qcms_data_type output_type = QCMS_DATA_RGBA_8;
  const qcms_intent intent = QCMS_INTENT_DEFAULT;

  if (profile == NULL || rgba == NULL) return 0;
  if (profile->bytes == NULL || profile->size < 10) return 1;
  major_revision = profile->bytes[8];

  qcms_enable_iccv4();
  input_profile = qcms_profile_from_memory(profile->bytes, profile->size);
  // qcms_profile_is_bogus() is broken with ICCv4.
  if (input_profile == NULL ||
      (major_revision < 4 && qcms_profile_is_bogus(input_profile))) {
    fprintf(stderr, "Color profile is bogus!\n");
    goto Error;
  }

  output_profile = qcms_profile_sRGB();
  if (output_profile == NULL) {
    fprintf(stderr, "Error creating output color profile!\n");
    goto Error;
  }

  qcms_profile_precache_output_transform(output_profile);
  transform = qcms_transform_create(input_profile, input_type,
                                    output_profile, output_type,
                                    intent);
  if (transform == NULL) {
    fprintf(stderr, "Error creating color transform!\n");
    goto Error;
  }

  line = rgba->u.RGBA.rgba;
  for (i = 0; i < rgba->height; ++i, line += rgba->u.RGBA.stride) {
    qcms_transform_data(transform, line, line, rgba->width);
  }
  ok = 1;

 Error:
  if (input_profile != NULL) qcms_profile_release(input_profile);
  if (output_profile != NULL) qcms_profile_release(output_profile);
  if (transform != NULL) qcms_transform_release(transform);
  return ok;
#else
  (void)profile;
  (void)rgba;
  return 1;
#endif  // WEBP_HAVE_QCMS
}
Ejemplo n.º 5
0
static void
transform(qcms_profile* src_profile, qcms_profile* dst_profile, size_t size)
{
  // qcms supports GRAY and RGB profiles as input, and RGB as output.

  uint32_t src_color_space = qcms_profile_get_color_space(src_profile);
  qcms_data_type src_type = size & 1 ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8;
  if (src_color_space == icSigGrayData) {
    src_type = size & 1 ? QCMS_DATA_GRAYA_8 : QCMS_DATA_GRAY_8;
  } else if (src_color_space != icSigRgbData) {
    return;
  }

  uint32_t dst_color_space = qcms_profile_get_color_space(dst_profile);
  if (dst_color_space != icSigRgbData) {
    return;
  }
  qcms_data_type dst_type = size & 2 ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8;

  qcms_intent intent = qcms_profile_get_rendering_intent(src_profile);
  // Firefox calls this on the display profile to increase performance.
  // Skip with low probability to increase coverage.
  if (size % 15) {
    qcms_profile_precache_output_transform(dst_profile);
  }

  qcms_transform* transform =
    qcms_transform_create(src_profile, src_type, dst_profile, dst_type, intent);
  if (!transform) {
    return;
  }

  static uint8_t src[] = {
    0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x7F, 0x7F, 0xFF, 0x7F, 0x10, 0x20, 0x30,
    0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xB0, 0xBF, 0xEF, 0x6F,
    0x3F, 0xC0, 0x9F, 0xE0, 0x90, 0xCF, 0x40, 0xAF, 0x0F, 0x01, 0x60, 0xF0,
  };
  static uint8_t dst[sizeof(src) * 4]; // 4x in case of GRAY to RGBA

  int src_bytes_per_pixel = 4; // QCMS_DATA_RGBA_8
  if (src_type == QCMS_DATA_RGB_8) {
    src_bytes_per_pixel = 3;
  } else if (src_type == QCMS_DATA_GRAYA_8) {
    src_bytes_per_pixel = 2;
  } else if (src_type == QCMS_DATA_GRAY_8) {
    src_bytes_per_pixel = 1;
  }

  qcms_transform_data(transform, src, dst, sizeof(src) / src_bytes_per_pixel);
  qcms_transform_release(transform);
}
Ejemplo n.º 6
0
void test_gray(qcms_profile *output_profile)
{
	unsigned char srct[3] = { 221, 79, 129};
	unsigned char outt[3];
	qcms_transform *transform;
	qcms_profile *gray_profile = qcms_profile_from_memory(gray_icc, sizeof(gray_icc));
	if (gray_profile) {
		transform = qcms_transform_create(gray_profile, QCMS_DATA_GRAY_8, output_profile, QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL);
		if (transform) {
			qcms_transform_data(transform, srct, outt, 1);
			qcms_transform_release(transform);
		}
		qcms_profile_release(gray_profile);
	}

}
Ejemplo n.º 7
0
/// Expand the colormap from RGB to Packed ARGB as needed by Cairo.
/// And apply any LCMS transformation.
static void
ConvertColormap(uint32_t* aColormap, uint32_t aColors)
{
  // Apply CMS transformation if enabled and available
  if (gfxPlatform::GetCMSMode() == eCMSMode_All) {
    qcms_transform* transform = gfxPlatform::GetCMSRGBTransform();
    if (transform) {
      qcms_transform_data(transform, aColormap, aColormap, aColors);
    }
  }
  // Convert from the GIF's RGB format to the Cairo format.
  // Work from end to begin, because of the in-place expansion
  uint8_t* from = ((uint8_t*)aColormap) + 3 * aColors;
  uint32_t* to = aColormap + aColors;

  // Convert color entries to Cairo format

  // set up for loops below
  if (!aColors) {
    return;
  }
  uint32_t c = aColors;

  // copy as bytes until source pointer is 32-bit-aligned
  // NB: can't use 32-bit reads, they might read off the end of the buffer
  for (; (NS_PTR_TO_UINT32(from) & 0x3) && c; --c) {
    from -= 3;
    *--to = gfxPackedPixel(0xFF, from[0], from[1], from[2]);
  }

  // bulk copy of pixels.
  while (c >= 4) {
    from -= 12;
    to   -=  4;
    c    -=  4;
    GFX_BLOCK_RGB_TO_FRGB(from,to);
  }

  // copy remaining pixel(s)
  // NB: can't use 32-bit reads, they might read off the end of the buffer
  while (c--) {
    from -= 3;
    *--to = gfxPackedPixel(0xFF, from[0], from[1], from[2]);
  }
}
Ejemplo n.º 8
0
void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int)
{
    if (m_frameBufferCache.isEmpty())
        return;

    // Initialize the framebuffer if needed.
    ImageFrame& buffer = m_frameBufferCache[0];
    if (buffer.status() == ImageFrame::FrameEmpty) {
        png_structp png = m_reader->pngPtr();
        if (!buffer.setSize(size().width(), size().height())) {
            longjmp(JMPBUF(png), 1);
            return;
        }

        unsigned colorChannels = m_reader->hasAlpha() ? 4 : 3;
        if (PNG_INTERLACE_ADAM7 == png_get_interlace_type(png, m_reader->infoPtr())) {
            m_reader->createInterlaceBuffer(colorChannels * size().width() * size().height());
            if (!m_reader->interlaceBuffer()) {
                longjmp(JMPBUF(png), 1);
                return;
            }
        }

#if USE(QCMSLIB)
        if (m_reader->colorTransform()) {
            m_reader->createRowBuffer(colorChannels * size().width());
            if (!m_reader->rowBuffer()) {
                longjmp(JMPBUF(png), 1);
                return;
            }
        }
#endif
        buffer.setStatus(ImageFrame::FramePartial);
        buffer.setHasAlpha(false);

        // For PNGs, the frame always fills the entire image.
        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
    }

    /* libpng comments (here to explain what follows).
     *
     * this function is called for every row in the image. If the
     * image is interlacing, and you turned on the interlace handler,
     * this function will be called for every row in every pass.
     * Some of these rows will not be changed from the previous pass.
     * When the row is not changed, the new_row variable will be NULL.
     * The rows and passes are called in order, so you don't really
     * need the row_num and pass, but I'm supplying them because it
     * may make your life easier.
     */

    // Nothing to do if the row is unchanged, or the row is outside
    // the image bounds: libpng may send extra rows, ignore them to
    // make our lives easier.
    if (!rowBuffer)
        return;
    int y = rowIndex;
    if (y < 0 || y >= size().height())
        return;

    /* libpng comments (continued).
     *
     * For the non-NULL rows of interlaced images, you must call
     * png_progressive_combine_row() passing in the row and the
     * old row.  You can call this function for NULL rows (it will
     * just return) and for non-interlaced images (it just does the
     * memcpy for you) if it will make the code easier. Thus, you
     * can just do this for all cases:
     *
     *    png_progressive_combine_row(png_ptr, old_row, new_row);
     *
     * where old_row is what was displayed for previous rows. Note
     * that the first pass (pass == 0 really) will completely cover
     * the old row, so the rows do not have to be initialized. After
     * the first pass (and only for interlaced images), you will have
     * to pass the current row, and the function will combine the
     * old row and the new row.
     */

    bool hasAlpha = m_reader->hasAlpha();
    png_bytep row = rowBuffer;

    if (png_bytep interlaceBuffer = m_reader->interlaceBuffer()) {
        unsigned colorChannels = hasAlpha ? 4 : 3;
        row = interlaceBuffer + (rowIndex * colorChannels * size().width());
        png_progressive_combine_row(m_reader->pngPtr(), row, rowBuffer);
    }

#if USE(QCMSLIB)
    if (qcms_transform* transform = m_reader->colorTransform()) {
        qcms_transform_data(transform, row, m_reader->rowBuffer(), size().width());
        row = m_reader->rowBuffer();
    }
#endif

    // Write the decoded row pixels to the frame buffer. The repetitive
    // form of the row write loops is for speed.
    ImageFrame::PixelData* address = buffer.getAddr(0, y);
    unsigned alphaMask = 255;
    int width = size().width();

    png_bytep pixel = row;
    if (hasAlpha) {
        if (buffer.premultiplyAlpha()) {
            for (int x = 0; x < width; ++x, pixel += 4) {
                buffer.setRGBAPremultiply(address++, pixel[0], pixel[1], pixel[2], pixel[3]);
                alphaMask &= pixel[3];
            }
        } else {
            for (int x = 0; x < width; ++x, pixel += 4) {
                buffer.setRGBARaw(address++, pixel[0], pixel[1], pixel[2], pixel[3]);
                alphaMask &= pixel[3];
            }
        }
    } else {
        for (int x = 0; x < width; ++x, pixel += 3) {
            buffer.setRGBARaw(address++, pixel[0], pixel[1], pixel[2], 255);
        }
    }

    if (alphaMask != 255 && !buffer.hasAlpha())
        buffer.setHasAlpha(true);

    buffer.setPixelsChanged(true);
}
Ejemplo n.º 9
0
void
nsJPEGDecoder::OutputScanlines(bool* suspend)
{
  *suspend = false;

  const uint32_t top = mInfo.output_scanline;

  while ((mInfo.output_scanline < mInfo.output_height)) {
      // Use the Cairo image buffer as scanline buffer
      uint32_t* imageRow = ((uint32_t*)mImageData) +
                           (mInfo.output_scanline * mInfo.output_width);

      if (mInfo.out_color_space == MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB) {
        // Special case: scanline will be directly converted into packed ARGB
        if (jpeg_read_scanlines(&mInfo, (JSAMPARRAY)&imageRow, 1) != 1) {
          *suspend = true; // suspend
          break;
        }
        continue; // all done for this row!
      }

      JSAMPROW sampleRow = (JSAMPROW)imageRow;
      if (mInfo.output_components == 3) {
        // Put the pixels at end of row to enable in-place expansion
        sampleRow += mInfo.output_width;
      }

      // Request one scanline.  Returns 0 or 1 scanlines.
      if (jpeg_read_scanlines(&mInfo, &sampleRow, 1) != 1) {
        *suspend = true; // suspend
        break;
      }

      if (mTransform) {
        JSAMPROW source = sampleRow;
        if (mInfo.out_color_space == JCS_GRAYSCALE) {
          // Convert from the 1byte grey pixels at begin of row
          // to the 3byte RGB byte pixels at 'end' of row
          sampleRow += mInfo.output_width;
        }
        qcms_transform_data(mTransform, source, sampleRow, mInfo.output_width);
        // Move 3byte RGB data to end of row
        if (mInfo.out_color_space == JCS_CMYK) {
          memmove(sampleRow + mInfo.output_width,
                  sampleRow,
                  3 * mInfo.output_width);
          sampleRow += mInfo.output_width;
        }
      } else {
        if (mInfo.out_color_space == JCS_CMYK) {
          // Convert from CMYK to RGB
          // We cannot convert directly to Cairo, as the CMSRGBTransform
          // may wants to do a RGB transform...
          // Would be better to have platform CMSenabled transformation
          // from CMYK to (A)RGB...
          cmyk_convert_rgb((JSAMPROW)imageRow, mInfo.output_width);
          sampleRow += mInfo.output_width;
        }
        if (mCMSMode == eCMSMode_All) {
          // No embedded ICC profile - treat as sRGB
          qcms_transform* transform = gfxPlatform::GetCMSRGBTransform();
          if (transform) {
            qcms_transform_data(transform, sampleRow, sampleRow,
                                mInfo.output_width);
          }
        }
      }

      // counter for while() loops below
      uint32_t idx = mInfo.output_width;

      // copy as bytes until source pointer is 32-bit-aligned
      for (; (NS_PTR_TO_UINT32(sampleRow) & 0x3) && idx; --idx) {
        *imageRow++ = gfxPackedPixel(0xFF, sampleRow[0], sampleRow[1],
                                     sampleRow[2]);
        sampleRow += 3;
      }

      // copy pixels in blocks of 4
      while (idx >= 4) {
        GFX_BLOCK_RGB_TO_FRGB(sampleRow, imageRow);
        idx       -=  4;
        sampleRow += 12;
        imageRow  +=  4;
      }

      // copy remaining pixel(s)
      while (idx--) {
        // 32-bit read of final pixel will exceed buffer, so read bytes
        *imageRow++ = gfxPackedPixel(0xFF, sampleRow[0], sampleRow[1],
                                     sampleRow[2]);
        sampleRow += 3;
      }
  }

  if (top != mInfo.output_scanline) {
      nsIntRect r(0, top, mInfo.output_width, mInfo.output_scanline-top);
      PostInvalidation(r);
  }

}
Ejemplo n.º 10
0
void
nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
                           png_uint_32 row_num, int pass)
{
  /* libpng comments:
   *
   * this function is called for every row in the image.  If the
   * image is interlacing, and you turned on the interlace handler,
   * this function will be called for every row in every pass.
   * Some of these rows will not be changed from the previous pass.
   * When the row is not changed, the new_row variable will be
   * nullptr. The rows and passes are called in order, so you don't
   * really need the row_num and pass, but I'm supplying them
   * because it may make your life easier.
   *
   * For the non-nullptr rows of interlaced images, you must call
   * png_progressive_combine_row() passing in the row and the
   * old row.  You can call this function for nullptr rows (it will
   * just return) and for non-interlaced images (it just does the
   * memcpy for you) if it will make the code easier.  Thus, you
   * can just do this for all cases:
   *
   *    png_progressive_combine_row(png_ptr, old_row, new_row);
   *
   * where old_row is what was displayed for previous rows.  Note
   * that the first pass (pass == 0 really) will completely cover
   * the old row, so the rows do not have to be initialized.  After
   * the first pass (and only for interlaced images), you will have
   * to pass the current row, and the function will combine the
   * old row and the new row.
   */
  nsPNGDecoder* decoder =
               static_cast<nsPNGDecoder*>(png_get_progressive_ptr(png_ptr));

  // skip this frame
  if (decoder->mFrameIsHidden) {
    return;
  }

  if (row_num >= (png_uint_32) decoder->mFrameRect.height) {
    return;
  }

  if (new_row) {
    int32_t width = decoder->mFrameRect.width;
    uint32_t iwidth = decoder->mFrameRect.width;

    png_bytep line = new_row;
    if (decoder->interlacebuf) {
      line = decoder->interlacebuf + (row_num * decoder->mChannels * width);
      png_progressive_combine_row(png_ptr, line, new_row);
    }

    uint32_t bpr = width * sizeof(uint32_t);
    uint32_t* cptr32 = (uint32_t*)(decoder->mImageData + (row_num*bpr));

    if (decoder->mTransform) {
      if (decoder->mCMSLine) {
        qcms_transform_data(decoder->mTransform, line, decoder->mCMSLine,
                            iwidth);
        // copy alpha over
        uint32_t channels = decoder->mChannels;
        if (channels == 2 || channels == 4) {
          for (uint32_t i = 0; i < iwidth; i++)
            decoder->mCMSLine[4 * i + 3] = line[channels * i + channels - 1];
        }
        line = decoder->mCMSLine;
      } else {
        qcms_transform_data(decoder->mTransform, line, line, iwidth);
      }
    }

    switch (decoder->format) {
      case gfx::SurfaceFormat::B8G8R8X8: {
        // counter for while() loops below
        uint32_t idx = iwidth;

        // copy as bytes until source pointer is 32-bit-aligned
        for (; (NS_PTR_TO_UINT32(line) & 0x3) && idx; --idx) {
          *cptr32++ = gfxPackedPixel(0xFF, line[0], line[1], line[2]);
          line += 3;
        }

        // copy pixels in blocks of 4
        while (idx >= 4) {
          GFX_BLOCK_RGB_TO_FRGB(line, cptr32);
          idx    -=  4;
          line   += 12;
          cptr32 +=  4;
        }

        // copy remaining pixel(s)
        while (idx--) {
          // 32-bit read of final pixel will exceed buffer, so read bytes
          *cptr32++ = gfxPackedPixel(0xFF, line[0], line[1], line[2]);
          line += 3;
        }
      }
      break;
      case gfx::SurfaceFormat::B8G8R8A8: {
        if (!decoder->mDisablePremultipliedAlpha) {
          for (uint32_t x=width; x>0; --x) {
            *cptr32++ = gfxPackedPixel(line[3], line[0], line[1], line[2]);
            line += 4;
          }
        } else {
          for (uint32_t x=width; x>0; --x) {
            *cptr32++ = gfxPackedPixelNoPreMultiply(line[3], line[0], line[1],
                                                    line[2]);
            line += 4;
          }
        }
      }
      break;
      default:
        png_longjmp(decoder->mPNG, 1);
    }

    if (decoder->mNumFrames <= 1) {
      // Only do incremental image display for the first frame
      // XXXbholley - this check should be handled in the superclass
      nsIntRect r(0, row_num, width, 1);
      decoder->PostInvalidation(r);
    }
  }
}
Ejemplo n.º 11
0
bool JPEGImageDecoder::outputScanlines()
{
    if (m_frameBufferCache.isEmpty())
        return false;

    // Initialize the framebuffer if needed.
    ImageFrame& buffer = m_frameBufferCache[0];
    if (buffer.status() == ImageFrame::FrameEmpty) {
        if (!buffer.setSize(scaledSize().width(), scaledSize().height()))
            return setFailed();
        buffer.setStatus(ImageFrame::FramePartial);
        // The buffer is transparent outside the decoded area while the image is
        // loading. The completed image will be marked fully opaque in jpegComplete().
        buffer.setHasAlpha(true);
        buffer.setColorProfile(m_colorProfile);

        // For JPEGs, the frame always fills the entire image.
        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
    }

    jpeg_decompress_struct* info = m_reader->info();

#if !ENABLE(IMAGE_DECODER_DOWN_SAMPLING) && defined(TURBO_JPEG_RGB_SWIZZLE)
    if (turboSwizzled(info->out_color_space)) {
        ASSERT(!m_scaled);
        while (info->output_scanline < info->output_height) {
            unsigned char* row = reinterpret_cast<unsigned char*>(buffer.getAddr(0, info->output_scanline));
            if (jpeg_read_scanlines(info, &row, 1) != 1)
                return false;
#if USE(QCMSLIB)
            if (qcms_transform* transform = m_reader->colorTransform())
                qcms_transform_data_type(transform, row, row, info->output_width, rgbOutputColorSpace() == JCS_EXT_BGRA ? QCMS_OUTPUT_BGRX : QCMS_OUTPUT_RGBX);
#endif
         }
         return true;
     }
#endif

    JSAMPARRAY samples = m_reader->samples();

    while (info->output_scanline < info->output_height) {
        // jpeg_read_scanlines will increase the scanline counter, so we
        // save the scanline before calling it.
        int sourceY = info->output_scanline;
        /* Request one scanline.  Returns 0 or 1 scanlines. */
        if (jpeg_read_scanlines(info, samples, 1) != 1)
            return false;

        int destY = scaledY(sourceY);
        if (destY < 0)
            continue;
#if USE(QCMSLIB)
        if (m_reader->colorTransform() && info->out_color_space == JCS_RGB)
            qcms_transform_data(m_reader->colorTransform(), *samples, *samples, info->output_width);
#endif
        int width = m_scaled ? m_scaledColumns.size() : info->output_width;
        for (int x = 0; x < width; ++x) {
            JSAMPLE* jsample = *samples + (m_scaled ? m_scaledColumns[x] : x) * ((info->out_color_space == JCS_RGB) ? 3 : 4);
            if (info->out_color_space == JCS_RGB)
                buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF);
#if defined(TURBO_JPEG_RGB_SWIZZLE)
            else if (info->out_color_space == JCS_EXT_RGBA)
                buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF);
            else if (info->out_color_space == JCS_EXT_BGRA)
                buffer.setRGBA(x, destY, jsample[2], jsample[1], jsample[0], 0xFF);
#endif
            else if (info->out_color_space == JCS_CMYK) {
                // Source is 'Inverted CMYK', output is RGB.
                // See: http://www.easyrgb.com/math.php?MATH=M12#text12
                // Or:  http://www.ilkeratalay.com/colorspacesfaq.php#rgb
                // From CMYK to CMY:
                // X =   X    * (1 -   K   ) +   K  [for X = C, M, or Y]
                // Thus, from Inverted CMYK to CMY is:
                // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK
                // From CMY (0..1) to RGB (0..1):
                // R = 1 - C => 1 - (1 - iC*iK) => iC*iK  [G and B similar]
                unsigned k = jsample[3];
                buffer.setRGBA(x, destY, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF);
            } else {
                ASSERT_NOT_REACHED();
                return setFailed();
            }
        }
    }

    return true;
}
Ejemplo n.º 12
0
//
// All these routines will return NS_OK if they have a value,
// in which case the nsLookAndFeel should use that value;
// otherwise we'll return NS_ERROR_NOT_AVAILABLE, in which case, the
// platform-specific nsLookAndFeel should use its own values instead.
//
NS_IMETHODIMP
nsXPLookAndFeel::GetColor(const nsColorID aID, nscolor &aColor)
{
  if (!sInitialized)
    Init();

  // define DEBUG_SYSTEM_COLOR_USE if you want to debug system color
  // use in a skin that uses them.  When set, it will make all system
  // color pairs that are appropriate for foreground/background
  // pairing the same.  This means if the skin is using system colors
  // correctly you will not be able to see *any* text.
#undef DEBUG_SYSTEM_COLOR_USE

#ifdef DEBUG_SYSTEM_COLOR_USE
  {
    nsresult rv = NS_OK;
    switch (aID) {
        // css2  http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
      case eColor_activecaption:
          // active window caption background
      case eColor_captiontext:
          // text in active window caption
        aColor = NS_RGB(0xff, 0x00, 0x00);
        break;

      case eColor_highlight:
          // background of selected item
      case eColor_highlighttext:
          // text of selected item
        aColor = NS_RGB(0xff, 0xff, 0x00);
        break;

      case eColor_inactivecaption:
          // inactive window caption
      case eColor_inactivecaptiontext:
          // text in inactive window caption
        aColor = NS_RGB(0x66, 0x66, 0x00);
        break;

      case eColor_infobackground:
          // tooltip background color
      case eColor_infotext:
          // tooltip text color
        aColor = NS_RGB(0x00, 0xff, 0x00);
        break;

      case eColor_menu:
          // menu background
      case eColor_menutext:
          // menu text
        aColor = NS_RGB(0x00, 0xff, 0xff);
        break;

      case eColor_threedface:
      case eColor_buttonface:
          // 3-D face color
      case eColor_buttontext:
          // text on push buttons
        aColor = NS_RGB(0x00, 0x66, 0x66);
        break;

      case eColor_window:
      case eColor_windowtext:
        aColor = NS_RGB(0x00, 0x00, 0xff);
        break;

      // from the CSS3 working draft (not yet finalized)
      // http://www.w3.org/tr/2000/wd-css3-userint-20000216.html#color

      case eColor__moz_field:
      case eColor__moz_fieldtext:
        aColor = NS_RGB(0xff, 0x00, 0xff);
        break;

      case eColor__moz_dialog:
      case eColor__moz_dialogtext:
        aColor = NS_RGB(0x66, 0x00, 0x66);
        break;

      default:
        rv = NS_ERROR_NOT_AVAILABLE;
    }
    if (NS_SUCCEEDED(rv))
      return rv;
  }
#endif // DEBUG_SYSTEM_COLOR_USE

  if (IS_COLOR_CACHED(aID)) {
    aColor = sCachedColors[aID];
    return NS_OK;
  }

  // There are no system color settings for these, so set them manually
  if (aID == eColor_TextSelectBackgroundDisabled) {
    // This is used to gray out the selection when it's not focused
    // Used with nsISelectionController::SELECTION_DISABLED
    aColor = NS_RGB(0xb0, 0xb0, 0xb0);
    return NS_OK;
  }

  if (aID == eColor_TextSelectBackgroundAttention) {
    // This makes the selection stand out when typeaheadfind is on
    // Used with nsISelectionController::SELECTION_ATTENTION
    aColor = NS_RGB(0x38, 0xd8, 0x78);
    return NS_OK;
  }

  if (aID == eColor_TextHighlightBackground) {
    // This makes the matched text stand out when findbar highlighting is on
    // Used with nsISelectionController::SELECTION_FIND
    aColor = NS_RGB(0xef, 0x0f, 0xff);
    return NS_OK;
  }

  if (aID == eColor_TextHighlightForeground) {
    // The foreground color for the matched text in findbar highlighting
    // Used with nsISelectionController::SELECTION_FIND
    aColor = NS_RGB(0xff, 0xff, 0xff);
    return NS_OK;
  }

  if (sUseNativeColors && NS_SUCCEEDED(NativeGetColor(aID, aColor))) {
    if ((gfxPlatform::GetCMSMode() == eCMSMode_All) && !IsSpecialColor(aID, aColor)) {
      qcms_transform *transform = gfxPlatform::GetCMSInverseRGBTransform();
      if (transform) {
        PRUint8 color[3];
        color[0] = NS_GET_R(aColor);
        color[1] = NS_GET_G(aColor);
        color[2] = NS_GET_B(aColor);
        qcms_transform_data(transform, color, color, 1);
        aColor = NS_RGB(color[0], color[1], color[2]);
      }
    }

    CACHE_COLOR(aID, aColor);
    return NS_OK;
  }

  return NS_ERROR_NOT_AVAILABLE;
}