void MCCachedImageRep::ReleaseFrames() { if (m_lock_count > 0 || m_frames == nil) return; s_cache_size -= GetFrameByteCount(); MCImageFreeFrames(m_frames, m_frame_count); m_frames = nil; }
bool MCResampledImageRep::LoadImageFrames(MCBitmapFrame *&r_frames, uindex_t &r_frame_count, bool &r_frames_premultiplied) { uindex_t t_src_width, t_src_height; if (!m_source->GetGeometry(t_src_width, t_src_height)) return false; bool t_success = true; MCBitmapFrame *t_frames = nil; uindex_t t_frame_count = 0; t_frame_count = m_source->GetFrameCount(); // IM-2013-07-03: [[ Bug 11018 ]] fail here if the source has no frames t_success = t_frame_count != 0; if (t_success) t_success = MCMemoryNewArray(t_frame_count, t_frames); MCGFloat t_scale; t_scale = MCMax(m_target_width / (float)t_src_width, m_target_height / (float)t_src_height); for (uindex_t i = 0; t_success && i < t_frame_count; i++) { MCBitmapFrame *t_src_frame = nil; t_success = m_source->LockBitmapFrame(i, t_scale, t_src_frame); if (t_success) { t_frames[i].duration = t_src_frame->duration; t_success = MCImageScaleBitmap(t_src_frame->image, m_target_width, m_target_height, INTERPOLATION_BICUBIC, t_frames[i].image); if (t_success) MCImageFlipBitmapInPlace(t_frames[i].image, m_h_flip, m_v_flip); } m_source->UnlockBitmapFrame(i, t_src_frame); } if (t_success) { r_frames = t_frames; r_frame_count = t_frame_count; r_frames_premultiplied = false; } else MCImageFreeFrames(t_frames, t_frame_count); return t_success; }
bool MCCompressedImageRep::LoadImageFrames(MCImageFrame *&r_frames, uindex_t &r_frame_count, bool &r_frames_premultiplied) { bool t_success = true; MCImageFrame *t_frame = nil; t_success = MCMemoryNewArray(1, t_frame); if (t_success) t_success = MCImageDecompressRLE(m_compressed, t_frame->image); if (t_success) { t_frame->density = 1.0; r_frames = t_frame; r_frame_count = 1; r_frames_premultiplied = false; } else MCImageFreeFrames(t_frame, 1); return t_success; }
bool MCGIFImageLoader::LoadFrames(MCBitmapFrame *&r_frames, uint32_t &r_count) { bool t_success; t_success = true; MCImageBitmap *t_canvas; t_canvas = nil; // restoration info MCImageBitmap *t_restore_image = nil; int t_disposal_mode = DISPOSAL_UNSPECIFIED; MCRectangle t_disposal_region = kMCEmptyRectangle; // The list of frames. MCBitmapFrame *t_frames = nil; t_success = GIF_OK == DGifSlurp(m_gif); // Fetch the width and height of the virtual canvas. int32_t t_width, t_height; if (t_success) { t_width = m_gif -> SWidth; t_height = m_gif -> SHeight; // create the canvas image t_success = MCImageBitmapCreate(t_width, t_height, t_canvas); } // The current frame count. The number of frames is the same as the // number of images in the GIF. uint32_t t_frame_count; t_frame_count = 0; // If true, the new image will be merged with the old - otherwise the mask // replaces it. bool t_overlay; t_overlay = false; // Loop through all the images, making frames as we go. for(uindex_t i = 0; t_success && i < m_gif -> ImageCount; i++) { // Process the disposal. switch (t_disposal_mode) { case DISPOSE_BACKGROUND: gif_fill_image_region(t_canvas, t_disposal_region, 0); break; case DISPOSE_PREVIOUS: if (t_restore_image != nil) gif_paste_image(t_canvas, t_restore_image, t_disposal_region.x, t_disposal_region.y); break; case DISPOSE_DO_NOT: t_overlay = true; break; default: t_overlay = false; break; } // Fetch the image information. GraphicsControlBlock t_image_gcb; MCRectangle t_image_region; ColorMapObject *t_image_colors = nil; int32_t t_image_transparency; int32_t t_image_delay; int32_t t_image_disposal; GifByteType *t_image_raster; // First the information from the image description. t_image_region.x = m_gif -> SavedImages[i] . ImageDesc . Left; t_image_region.y = m_gif -> SavedImages[i] . ImageDesc . Top; t_image_region.width = m_gif -> SavedImages[i] . ImageDesc . Width; t_image_region.height = m_gif -> SavedImages[i] . ImageDesc . Height; t_image_colors = m_gif -> SavedImages[i] . ImageDesc . ColorMap; t_image_raster = m_gif -> SavedImages[i] . RasterBits; if (t_image_colors == nil) t_image_colors = m_gif -> SColorMap; // Then the information from the GCB. if (GIF_OK == DGifSavedExtensionToGCB(m_gif, i, &t_image_gcb)) { t_image_transparency = t_image_gcb . TransparentColor; t_image_delay = t_image_gcb . DelayTime; t_image_disposal = t_image_gcb . DisposalMode; } else { t_image_transparency = -1; t_image_delay = 0; t_image_disposal = DISPOSAL_UNSPECIFIED; } // If disposal is 'previous' then cache the portion of the canvas we are // about to affect. if (t_image_disposal == DISPOSE_PREVIOUS) { if (t_restore_image != nil) { if (t_disposal_mode != DISPOSE_PREVIOUS || !MCU_equal_rect(t_disposal_region, t_image_region)) { MCImageFreeBitmap(t_restore_image); t_restore_image = nil; } } if (t_restore_image == nil) t_success = MCImageCopyBitmapRegion(t_canvas, t_image_region, t_restore_image); } if (t_success) { // Render the image into the canvas. gif_draw_image_into_canvas(t_canvas, t_image_raster, t_image_region.x, t_image_region.y, t_image_region.width, t_image_region.height, t_image_colors, t_image_transparency, t_overlay); // Generate our frame. t_success = MCMemoryResizeArray(t_frame_count + 1, t_frames, t_frame_count); } MCImageBitmap *t_frame_bitmap = nil; if (t_success) t_success = MCImageCopyBitmap(t_canvas, t_frame_bitmap); if (t_success) { MCImageBitmapCheckTransparency(t_frame_bitmap); t_frames[t_frame_count - 1].image = t_frame_bitmap; t_frames[t_frame_count - 1].duration = t_image_delay * 10; // convert 1/100 seconds to milliseconds t_frames[t_frame_count - 1].x_scale = t_frames[t_frame_count - 1].y_scale = 1.0; } t_disposal_region = t_image_region; t_disposal_mode = t_image_disposal; } MCImageFreeBitmap(t_canvas); MCImageFreeBitmap(t_restore_image); if (t_success) { r_frames = t_frames; r_count = t_frame_count; } else MCImageFreeFrames(t_frames, t_frame_count); return t_success; }
// if the image is in a directly supported format return the raw data otherwise decode & return the bitmap bool MCImageImport(IO_handle p_stream, IO_handle p_mask_stream, MCPoint &r_hotspot, MCStringRef&r_name, MCImageCompressedBitmap *&r_compressed, MCImageBitmap *&r_bitmap) { bool t_success; t_success = true; // IM-2014-07-31: [[ ImageLoader ]] Update to use MCImageLoader class MCImageLoaderFormat t_format; if (t_success) t_success = MCImageLoader::IdentifyFormat(p_stream, t_format); if (t_success) { uint32_t t_compression; if (MCImageLoaderFormatToCompression(t_format, t_compression)) { t_success = MCImageCreateCompressedBitmap(t_compression, r_compressed); if (t_success) { uint32_t t_width, t_height; t_width = t_height = 0; if (t_success && t_compression == F_PICT) t_success = MCImageGetMetafileGeometry(p_stream, t_width, t_height); if (t_success) t_success = read_all(p_stream, r_compressed->data, r_compressed->size); r_compressed->width = t_width; r_compressed->height = t_height; } } else { MCImageLoader *t_loader; t_loader = nil; t_success = MCImageLoader::LoaderForStreamWithFormat(p_stream, t_format, t_loader); uint32_t t_xhot, t_yhot; MCAutoStringRef t_name; MCBitmapFrame *t_frames; t_frames = nil; uint32_t t_count; t_count = 0; if (t_success) t_success = t_loader->GetHotSpot(t_xhot, t_yhot); if (t_success) t_success = t_loader->GetName(&t_name); if (t_success) t_success = t_loader->TakeFrames(t_frames, t_count); if (t_success && p_mask_stream != nil && t_loader->GetFormat() == kMCImageFormatNetPBM) { MCImageBitmap *t_mask = nil; t_success = MCImageDecodeNetPBM(p_mask_stream, t_mask) && MCImageBitmapApplyMask(t_frames[0].image, t_mask); MCImageFreeBitmap(t_mask); } if (t_success) { r_hotspot.x = t_xhot; r_hotspot.y = t_yhot; r_name = MCValueRetain(*t_name); r_bitmap = t_frames[0].image; t_frames[0].image = nil; } else r_name = MCValueRetain(kMCEmptyString); MCImageFreeFrames(t_frames, t_count); if (t_loader != nil) delete t_loader; } } return t_success; }
bool MCTransformedImageRep::LoadImageFrames(MCImageFrame *&r_frames, uindex_t &r_frame_count) { uindex_t t_target_width, t_target_height; if (!GetGeometry(t_target_width, t_target_height)) return false; bool t_success = true; MCImageFrame *t_frames = nil; uindex_t t_frame_count = 0; t_frame_count = m_source->GetFrameCount(); t_success = MCMemoryNewArray(t_frame_count, t_frames); for (uindex_t i = 0; t_success && i < t_frame_count; i++) { MCImageFrame *t_src_frame = nil; t_success = m_source->LockImageFrame(i, t_src_frame); if (t_success) { t_frames[i].duration = t_src_frame->duration; if (m_angle != 0) { // rotate MCImageBitmap *t_bitmap = nil; MCImageBitmap *t_rotated = nil; t_success = MCImageCopyBitmap(t_src_frame->image, t_bitmap); if (t_success) { MCImageBitmapPremultiply(t_bitmap); t_success = MCImageRotateBitmap(t_bitmap, m_angle, m_quality, 0x0, t_rotated); } MCImageFreeBitmap(t_bitmap); bool t_scaled = false; if (t_success && (t_rotated->width != t_target_width || t_rotated->height != t_target_height)) { MCImageBitmap *t_sbitmap = nil; t_success = MCImageScaleBitmap(t_rotated, t_target_width, t_target_height, m_quality, t_sbitmap); MCImageFreeBitmap(t_rotated); t_rotated = t_sbitmap; t_scaled = true; } if (t_success) { if (t_scaled && (m_quality == INTERPOLATION_BICUBIC)) MCImageBitmapUnpremultiplyChecking(t_rotated); else MCImageBitmapUnpremultiply(t_rotated); t_frames[i].image = t_rotated; } else MCImageFreeBitmap(t_rotated); } else { // resize if (t_src_frame->image->width == t_target_width && t_src_frame->image->height == t_target_height) t_success = MCImageCopyBitmap(t_src_frame->image, t_frames[i].image); else t_success = MCImageScaleBitmap(t_src_frame->image, t_target_width, t_target_height, m_quality, t_frames[i].image); } } m_source->UnlockImageFrame(i, t_src_frame); } if (t_success) { r_frames = t_frames; r_frame_count = t_frame_count; } else MCImageFreeFrames(t_frames, t_frame_count); return t_success; }