I have a number of images that are sotred as blob data in my database.
I am aware this isn't a good idea, but it's what I'm using.
I have following code in my Peer class:
public function getImagesPath()
{
$file_srcs = false;
$fp = $this->getPhoto->getBlobData();
if ($fp !== null)
{
$file = stream_get_contents($fp);
$file_srcs = '/uploads/gallery/'.$this->getId().'.jpg';
}
return $file_srcs;
}
I then call this in my template, like so:
$path = $item->getImagesPath();
if ($path)
{
echo '<img src="'.$path.'" alt="Thumbnail for '.$photo->getName().'" width="153" height="153" />';
}
Now this works well, but, I have some images that are either square in shape, or rectangular.
Giving them a size/width in the img src distorts some of them.
Is there anyway, in which I could resize/crop the images before they are displayed?
Thanks
sfThumbnailPlugin is what I've used on a number of projects and it is pretty awesome. There is an older version for Symfony 1.0 if that's what you're using. By default it uses GD, but you can have it use ImageMagick and do some pretty cool things with it.
You can probably use imagecreatefromstring and imagecopyresampled. This is code that I use, that I've changed to work with your blob. This also adds a white background if the original size width/height ratio doesn't match the destination image size.
static function CreateThumbnailFromBlob($blobData, $dstWidth = 100.0, $dstHeight = 100.0){
$oldImg = #imagecreatefromstring($olduri);
if($oldImg){
$realOldW = imagesx($oldImg);
$realOldH = imagesy($oldImg);
$destX = 0;
$destY = 0;
if($realOldH>=$realOldW && $realOldH>0){
$realY = $dstHeight;
$realX = round($realY*$realOldW/$realOldH);
$destX = round($dstWidth/2-$realX/2);
}else{
$realX = $dstWidth;
if($realOldW>0)
$realY = round($realX*$realOldH/$realOldW);
else
$realY = $dstHeight;
$destY = round($dstHeight/2-$realY/2);
}
$newImg = #imagecreatetruecolor($dstWidth, $dstHeight);
$white = imagecolorallocate($newImg, 255, 255, 255);
imagefill($newImg, 1, 1, $white);
imagecopyresampled($newImg,$oldImg,$destX,$destY,
0,0,$realX,$realY,$realOldW,$realOldH);
imagedestroy($oldImg);
return $newImg;
}
}
How are you adding images to the database?
If it is via an upload form, the best method would be to create a thumbnail of the appropriate size/dimensions using GD or another library and store it in a second blob column.
Otherwise you can specify a single dimension in the html and the picture will retain its dimensions.
Related
So I created gif file from 5 png files with using MagickCoalesceImages call and store it on disk.
How I can read these files back from gif file ?
MagickReadImage does not help
Hard to help without seeing the code, but I can assume you created 5 images with something like...
MagickWand
* gif2png;
gif2png = NewMagickWand();
MagickReadImage(gif2png, "input.gif");
MagickWriteImages(gif2png, "output_%02d.png", MagickFalse);
gif2png = DestroyMagickWand(gif2png);
How I can read these files back from gif file?
You would use MagickReadImage to decode the image from the file, and MagickAddImage to append the decoded image onto a image-stack.
MagickWand
* png2gif,
* temp;
// Create a blank image-stack.
png2gif = NewMagickWand();
char filename[PATH_MAX]; // PATH_MAX provided by limits.h
// Iterate over images to append.
for (int i = 0; i < 5; ++i) {
sprintf(filename, "output_%02d.png", i);
// Read image from disk.
temp = NewMagickWand();
MagickReadImage(temp, filename);
// Add "frame" to stack.
MagickAddImage(png2gif, temp);
temp = DestroyMagickWand(temp);
}
MagickWriteImages(png2gif, "output.gif", MagickTrue);
png2gif = DestroyMagickWand(png2gif);
Warning: The above example omits basic error handling, and assumes the filename names are a sequential series.
Update
From the comments, if you wish to extract a single frame as a PNG file, there are a few ways.
Fastest way is to use MagickWriteImages
MagickWriteImages(img, "output_%02d.png", MagickFalse);
Or use the image stack iterators.
for (MagickSetFirstIterator(img); MagickHasNextImage(img); MagickNextImage(img)) {
MagickWriteImage(img, "output_%02d.png");
}
Or, if the PNG filenames are defined, and you need to map them.
const char * filenames[5] = {
"first.png",
"second.png",
"third.png",
"forth.png",
"fifth.png"
};
for (int i = 0; i < 5; ++i) {
MagickSetIteratorIndex(img, i);
MagickWriteImage(img, filenames[i]);
}
Without seeing the code, we can't offer much help, and can only guess what an acceptable solution would be.
Scenario:
I am using OpenH264 with my App to encode into a video_file.mp4.
Environment:
Platform : MacOs Sierra
Compiler : Clang++
The code:
Following is the crux of the code I have:
void EncodeVideoFile() {
ISVCEncoder * encoder_;
std:string video_file_name = "/Path/to/some/folder/video_file.mp4";
EncodeFileParam * pEncFileParam;
SEncParamExt * pEnxParamExt;
float frameRate = 1000;
EUsageType usageType = EUsageType::CAMERA_VIDEO_REAL_TIME;
bool denoise = false;
bool lossless = true;
bool enable_ltr = false;
int layers = 1;
bool cabac = false;
int sliceMode = 1;
pEncFileParam = new EncodeFileParam;
pEncFileParam->eUsageType = EUsageType::CAMERA_VIDEO_REAL_TIME;
pEncFileParam->pkcFileName = video_file_name.c_str();
pEncFileParam->iWidth = frame_width;
pEncFileParam->iHeight = frame_height;
pEncFileParam->fFrameRate = frameRate;
pEncFileParam->iLayerNum = layers;
pEncFileParam->bDenoise = denoise;
pEncFileParam->bLossless = lossless;
pEncFileParam->bEnableLtr = enable_ltr;
pEncFileParam->bCabac = cabac;
int rv = WelsCreateSVCEncoder (&encoder_);
pEnxParamExt = new SEncParamExt;
pEnxParamExt->iUsageType = pEncFileParam->eUsageType;
pEnxParamExt->iPicWidth = pEncFileParam->iWidth;
pEnxParamExt->iPicHeight = pEncFileParam->iHeight;
pEnxParamExt->fMaxFrameRate = pEncFileParam->fFrameRate;
pEnxParamExt->iSpatialLayerNum = pEncFileParam->iLayerNum;
pEnxParamExt->bEnableDenoise = pEncFileParam->bDenoise;
pEnxParamExt->bIsLosslessLink = pEncFileParam->bLossless;
pEnxParamExt->bEnableLongTermReference = pEncFileParam->bEnableLtr;
pEnxParamExt->iEntropyCodingModeFlag = pEncFileParam->bCabac ? 1 : 0;
for (int i = 0; i < pEnxParamExt->iSpatialLayerNum; i++) {
pEnxParamExt->sSpatialLayers[i].sSliceArgument.uiSliceMode = pEncFileParam->eSliceMode;
}
encoder_->InitializeExt(pEnxParamExt);
int videoFormat = videoFormatI420;
encoder_->SetOption (ENCODER_OPTION_DATAFORMAT, &videoFormat);
int frameSize = frame_width * frame_height * 3 / 2;
int total_num = 500;
BufferedData buf;
buf.SetLength (frameSize);
// check the buffer before proceeding
if (buf.Length() != (size_t)frameSize) {
CloseEncoder();
return;
}
SFrameBSInfo info;
memset (&info, 0, sizeof (SFrameBSInfo));
SSourcePicture pic;
memset (&pic, 0, sizeof (SSourcePicture));
pic.iPicWidth = frame_width;
pic.iPicHeight = frame_height;
pic.iColorFormat = videoFormatI420;
pic.iStride[0] = pic.iPicWidth;
pic.iStride[1] = pic.iStride[2] = pic.iPicWidth >> 1;
pic.pData[0] = buf.data();
pic.pData[1] = pic.pData[0] + frame_width * frame_height;
pic.pData[2] = pic.pData[1] + (frame_width * frame_height >> 2);
for(int num = 0; num < total_num; num++) {
// try to encode the frame
rv = encoder_->EncodeFrame (&pic, &info);
}
if (encoder_) {
encoder_->Uninitialize();
WelsDestroySVCEncoder (encoder_);
}
}
Above code is something I pulled up from official usage examples of OpenH264 where BufferedData.h is a class I reused from OpenH264 utils
Issue:
But, I am getting the following error:
[OpenH264] this = 0x0x1038bc8c0, Error:ParamValidationExt(), width > 0, height > 0, width * height <= 9437184, invalid 0 x 0 in dependency layer settings!
[OpenH264] this = 0x0x1038bc8c0, Error:WelsInitEncoderExt(), ParamValidationExt failed return 2.
[OpenH264] this = 0x0x1038bc8c0, Error:CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.
Above does not crash the application but it goes through a blank run without creating the video_file.mp4 with the dummy data that I am trying to write into it.
Question:
There seems to be something wrong with the set up config I applying to pEnxParamExtwhich goes into encoder_->InitializeExt.
What am I doing wrong with the set up of the encoder?
Note:
I am not trying to hook up to any camera device. I am just trying to create a .mp4 video out of some dummy image data.
If you want to get complete and working OpenH264 Encoder Initialization procedure you can click... here.
According to your problem scenario, you are trying to create a video file(.mp4/.avi) from some dummy images. This task can be accomplished using two different libraries: i) Library for Codec, ii) Library for Container.
i) Library for Codec: It's so much easy to use a OpenH264 to compress data. One thing I must mention is that, OpenH264 always works with raw frames e.g. yuv420 data. So, if you want to compress your image data, you have to convert these image data into yuv420 color format. To get OpenH264 click... here
ii) Library for Container: After getting the encoded data you have to use another library to create the container with extension .mp4, .avi, .flv etc. There exists a lot of libraries in github to do that staff like FFmpeg, OpenCV, Bento4, MP4Maker, mp4parser etc. Before using these libraries please check in detail about the license issues. If you use FFmpeg, you will not need to use OpenH264 becuse FFmpeg itself works along with several codecs. You will also find lot more working examples as so many developers are working with video data out there.
Hope it helps. :)
I just started to use libxlsxwriter to create excel sheet. My problem is I don't know how to centralized the picture and how to print pictures on their original size. Just consider the set having only 3 columns and each column having different size for example 30,10,20. I need to know what is the calculation do I need to find offset and scale values.
lxw_image_options options = {.x_offset = 0, .y_offset = 0,.x_scale = 0.9, .y_scale = 0.9};
worksheet_insert_image_opt(worksheet, row, 0, img_path, &options);
With that, I need to Know How many rows the picture can hold.Then only I can create the upcoming set without overlap.
how to print pictures on their original size
libxlsxwriter inserts images into an xlsx file at their original size based on the width, height and DPI information in the image. It should insert images in exactly the same way as if you did it in Excel via the user interface.
However, images in OpenOffice or LibreOffice may not appear to the correct size. This isn't an libxlsxwriter issue: the same thing happens with Excel.
To insert images at precise positions you will need to know the dimensions of the images in pixels and also the DPI since Excel scales according to it's default DPI (usually 96) Here is an example of inserting two images in a row:
/*
* An example of inserting images with the libxlsxwriter library.
*/
#include "xlsxwriter.h"
int main() {
/* Create a new workbook and add a worksheet. */
lxw_workbook *workbook = workbook_new("demo.xlsx");
lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
lxw_image_options options = {.x_offset = 0, .y_offset = 0,
.x_scale = 1, .y_scale = 1};
double default_dpi = 96.0;
double image_dpi = 90.0;
int32_t image_height = 138;
int32_t image_offset = (int32_t)(image_height * default_dpi/image_dpi);
/* Insert the first image. */
worksheet_insert_image(worksheet, 1, 2, "logo.png");
/* Insert the second image relative to the first. */
options.y_offset += image_offset;
worksheet_insert_image_opt(worksheet, 1, 2, "logo.png", &options);
workbook_close(workbook);
return 0;
}
Output:
How many rows did picture hold?
I want to Present my findings here to improvise the result.
int row=1;
lxw_image_options options = {.x_offset = 0, .y_offset = 0};
worksheet_insert_image_opt(worksheet, row, 2,"logo.png", &options);
row+=(options.height/worksheet->default_row_pixels);
Here I used the variable options.height to calculate How many rows the picture hold. The libxlsxwriter did read the height from the image file in pixels. It uses struct variable option only for read initialized variable it will never write anything in the set. But I did by adding the line user_options->height=options->height; in the function worksheet_insert_image_opt at worksheet.c.
lxw_error worksheet_insert_image_opt(lxw_worksheet *self,
lxw_row_t row_num, lxw_col_t col_num,
const char *filename,
lxw_image_options *user_options)
{
FILE *image_stream;
char *short_name;
lxw_image_options *options;
if (!filename) {
LXW_WARN("worksheet_insert_image()/_opt(): "
"filename must be specified.");
return LXW_ERROR_NULL_PARAMETER_IGNORED;
}
/* Check that the image file exists and can be opened. */
image_stream = fopen(filename, "rb");
if (!image_stream) {
LXW_WARN_FORMAT1("worksheet_insert_image()/_opt(): "
"file doesn't exist or can't be opened: %s.",
filename);
return LXW_ERROR_PARAMETER_VALIDATION;
}
/* Get the filename from the full path to add to the Drawing object. */
short_name = lxw_basename(filename);
if (!short_name) {
LXW_WARN_FORMAT1("worksheet_insert_image()/_opt(): "
"couldn't get basename for file: %s.", filename);
fclose(image_stream);
return LXW_ERROR_PARAMETER_VALIDATION;
}
/* Create a new object to hold the image options. */
options = calloc(1, sizeof(lxw_image_options));
if (!options) {
fclose(image_stream);
return LXW_ERROR_MEMORY_MALLOC_FAILED;
}
if (user_options) {
memcpy(options, user_options, sizeof(lxw_image_options));
options->url = lxw_strdup(user_options->url);
options->tip = lxw_strdup(user_options->tip);
}
/* Copy other options or set defaults. */
options->filename = lxw_strdup(filename);
options->short_name = lxw_strdup(short_name);
options->stream = image_stream;
options->row = row_num;
options->col = col_num;
if (!options->x_scale)
options->x_scale = 1;
if (!options->y_scale)
options->y_scale = 1;
if (_get_image_properties(options) == LXW_NO_ERROR) {
user_options->height=options->height;
STAILQ_INSERT_TAIL(self->image_data, options, list_pointers);
return LXW_NO_ERROR;
}
else {
free(options);
return LXW_ERROR_IMAGE_DIMENSIONS;
}
}
this how I was calcuating rows. If there is a better way please let me know.
As per in this FileHelpers 3.1 example, you can automatically detect a CSV file format using the FileHelpers.Detection.SmartFormatDetector class.
But the example goes no further. How do you use this information to dynamically parse a CSV file? It must have something to do with the DelimitedFileEngine but I cannot see how.
Update:
I figured out a possible way but had to resort to using reflection (which does not feel right). Is there another/better way? Maybe using System.Dynamic? Anyway, here is the code I have so far, it ain't pretty but it works:
// follows on from smart detector example
FileHelpers.Detection.RecordFormatInfo lDetectedFormat = formats[0];
Type lDetectedClass = lDetectedFormat.ClassBuilderAsDelimited.CreateRecordClass();
List<FieldInfo> lFieldInfoList = new List<FieldInfo>(lDetectedFormat.ClassBuilderAsDelimited.FieldCount);
foreach (FileHelpers.Dynamic.DelimitedFieldBuilder lField in lDetectedFormat.ClassBuilderAsDelimited.Fields)
lFieldInfoList.Add(lDetectedClass.GetField(lField.FieldName));
FileHelperAsyncEngine lFileEngine = new FileHelperAsyncEngine(lDetectedClass);
int lRecNo = 0;
lFileEngine.BeginReadFile(cReadingsFile);
try
{
while (true)
{
object lRec = lFileEngine.ReadNext();
if (lRec == null)
break;
Trace.WriteLine("Record " + lRecNo);
lFieldInfoList.ForEach(f => Trace.WriteLine(" " + f.Name + " = " + f.GetValue(lRec)));
lRecNo++;
}
}
finally
{
lFileEngine.Close();
}
As I use the SmartFormatDetector to determine the exact format of the incoming Delimited files you can use following appoach:
private DelimitedClassBuilder GetFormat(string file)
{
var detector = new FileHelpers.Detection.SmartFormatDetector();
var format = detector.DetectFileFormat(file);
return format.First().ClassBuilderAsDelimited;
}
private List<T> ConvertFile2Objects<T>(string file, out DelimitedFileEngine engine)
{
var format = GetSeperator(file); // Get Here your FormatInfo
engine = new DelimitedFileEngine(typeof(T)); //define your DelimitdFileEngine
//set some Properties of the engine with what you need
engine.ErrorMode = ErrorMode.SaveAndContinue; //optional
engine.Options.Delimiter = format.Delimiter;
engine.Options.IgnoreFirstLines = format.IgnoreFirstLines;
engine.Options.IgnoreLastLines = format.IgnoreLastLines;
//process
var ret = engine.ReadFileAsList(file);
this.errorCount = engine.ErrorManager.ErrorCount;
var err = engine.ErrorManager.Errors;
engine.ErrorManager.SaveErrors("errors.out");
//return records do here what you need
return ret.Cast<T>().ToList();
}
This is an approach I use in a project, where I only know that I have to process Delimited files of multiple types.
Attention:
I noticed that with the files I recieved the SmartFormatDetector has a problem with tab delimiter. Maybe this should be considered.
Disclaimer: This code is not perfected but in a usable state. Modification and/or refactoring is adviced.
I actually try to read and write compressed tif-files with CIE Lab colorspace.
Unfortunally if I try to just read and after this write the tif back to the HDD the color is different from the soure tif.
Is the ImageIO lib able to read and write compressed tif files with CIE lab color space?
If it is possible I fear that something is wrong with the code. In the singleTiffs list are at least one tiff-ImageInputStream which is created in this way:
ImageIO.createImageInputStream(testTiff)
Would be great if someone could help me. Thanks a lot!
// Get iterator for input images
Iterator<ImageInputStream> iterator = singleTiffs.iterator();
// Get tif writer and set output to file
Iterator writers = ImageIO.getImageWritersByFormatName("tiff");
ImageWriter writer = (ImageWriter) writers.next();
ImageOutputStream ios = ImageIO.createImageOutputStream(newMultiPageTIFF);
writer.setOutput(ios);
// Write each image out to the new file
boolean firstImage = true;
while(iterator.hasNext())
{
ImageInputStream iis = iterator.next();
// Get a reader for the stream
Iterator readers = ImageIO.getImageReaders(iis);
ImageReader reader = (ImageReader) readers.next();
reader.setInput(iis);
// Read the stream metadata
// IIOMetadata streamMetadata = reader.getStreamMetadata();
// Read the image metadata - we are assuming there is only one image
// in the tiff
IIOMetadata imageMetadata = reader.getImageMetadata(0);
// Set up the writeParam
TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.US);
tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_COPY_FROM_METADATA);
BufferedImage bi = reader.read(0, null);
IIOImage image = new IIOImage(bi, null, imageMetadata);
if(firstImage == false)
writer.writeInsert(-1, image, tiffWriteParam);
else
{
writer.write(null, image, tiffWriteParam);
firstImage = false;
}
// Done writing all images for this image
reader.dispose();
}
// End writing of all files
writer.dispose();