Ejemplo n.º 1
0
static void copyBGRDataFromMMBitmap(MMBitmapRef bitmap, uint8_t *dest)
{
	if (MMRGB_IS_BGR && (bitmap->bytewidth % 4) == 0) { /* No conversion needed. */
		memcpy(dest, bitmap->imageBuffer, bitmap->bytewidth * bitmap->height);
	} else { /* Convert to RGB with other-than-4-byte alignment. */
		const size_t bytewidth = (bitmap->width * bitmap->bytesPerPixel + 3) & ~3;
		size_t y;

		/* Copy image data row by row. */
		for (y = 0; y < bitmap->height; ++y) {
			uint8_t *rowptr = dest + (y * bytewidth);
			size_t x;
			for (x = 0; x < bitmap->width; ++x) {
				MMRGBColor *color = MMRGBColorRefAtPoint(bitmap, x, y);

				/* BMP files are stored in BGR format. */
				rowptr[0] = color->blue;
				rowptr[1] = color->green;
				rowptr[2] = color->red;

				rowptr += bitmap->bytesPerPixel;
			}
		}
	}
}
Ejemplo n.º 2
0
/* Returns pointer to PNGWriteInfo struct containing data ready to be used with
 * functions such as png_write_png().
 *
 * It is the caller's responsibility to destroy() the returned structure with
 * destroyPNGWriteInfo(). */
static PNGWriteInfoRef createPNGWriteInfo(MMBitmapRef bitmap)
{
	PNGWriteInfoRef info = malloc(sizeof(PNGWriteInfo));
	png_uint_32 y;

	if (info == NULL) return NULL;
	info->png_ptr = NULL;
	info->info_ptr = NULL;
	info->row_pointers = NULL;

	assert(bitmap != NULL);

	/* Initialize the write struct. */
	info->png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
	                                        NULL, NULL, NULL);
	if (info->png_ptr == NULL) goto bail;

	/* Set up error handling. */
	if (setjmp(png_jmpbuf(info->png_ptr))) {
		png_destroy_write_struct(&(info->png_ptr), &(info->info_ptr));
		goto bail;
	}

	/* Initialize the info struct. */
	info->info_ptr = png_create_info_struct(info->png_ptr);
	if (info->info_ptr == NULL) {
		png_destroy_write_struct(&(info->png_ptr), NULL);
		goto bail;
	}

	/* Set image attributes. */
	png_set_IHDR(info->png_ptr,
	             info->info_ptr,
	             bitmap->width,
	             bitmap->height,
	             8,
	             PNG_COLOR_TYPE_RGB,
	             PNG_INTERLACE_NONE,
	             PNG_COMPRESSION_TYPE_DEFAULT,
	             PNG_FILTER_TYPE_DEFAULT);

	info->row_count = bitmap->height;
	info->row_pointers = png_malloc(info->png_ptr,
	                                sizeof(png_byte *) * info->row_count);

	if (bitmap->bytesPerPixel == 3) {
		/* No alpha channel; image data can be copied directly. */
		for (y = 0; y < info->row_count; ++y) {
			info->row_pointers[y] = bitmap->imageBuffer + (bitmap->bytewidth * y);
		}
		info->free_row_pointers = false;

		/* Convert BGR to RGB if necessary. */
		if (MMRGB_IS_BGR) {
			png_set_bgr(info->png_ptr);
		}
	} else {
		/* Ignore alpha channel; copy image data row by row. */
		const size_t bytesPerPixel = 3;
		const size_t bytewidth = ADD_PADDING(bitmap->width * bytesPerPixel);

		for (y = 0; y < info->row_count; ++y) {
			png_uint_32 x;
			png_byte *row_ptr = png_malloc(info->png_ptr, bytewidth);
			info->row_pointers[y] = row_ptr;
			for (x = 0; x < bitmap->width; ++x) {
				MMRGBColor *color = MMRGBColorRefAtPoint(bitmap, x, y);
				row_ptr[0] = color->red;
				row_ptr[1] = color->green;
				row_ptr[2] = color->blue;

				row_ptr += bytesPerPixel;
			}
		}
		info->free_row_pointers = true;
	}

	png_set_rows(info->png_ptr, info->info_ptr, info->row_pointers);
	return info;

bail:
	if (info != NULL) free(info);
	return NULL;
}